370 lines
14 KiB
PHP
370 lines
14 KiB
PHP
<?php
|
|
|
|
if (!defined('_PS_VERSION_')) {
|
|
exit;
|
|
}
|
|
|
|
|
|
class IbanPro extends PaymentModule
|
|
{
|
|
|
|
public $paymentMethodName = 'IBAN';
|
|
public function __construct()
|
|
{
|
|
$this->name = 'ibanpro';
|
|
|
|
$this->tab = 'advertising_marketing';
|
|
$this->version = '1.0.0';
|
|
$this->author = 'panariga';
|
|
|
|
$this->need_instance = 0;
|
|
parent::__construct();
|
|
|
|
$this->displayName = $this->trans('Iban.pro');
|
|
$this->description = $this->trans('Iban.pro module for Ukraine');
|
|
$this->confirmUninstall = $this->trans('Are you sure about removing these details?');
|
|
$this->ps_versions_compliancy = array(
|
|
'min' => '1.7',
|
|
'max' => _PS_VERSION_,
|
|
);
|
|
}
|
|
|
|
public function install()
|
|
{
|
|
return parent::install() &&
|
|
$this->registerHook('displayOrderConfirmation') && $this->registerHook('paymentOptions');
|
|
}
|
|
|
|
|
|
public function uninstall()
|
|
{
|
|
if (!parent::uninstall()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Entry point for the module's configuration page.
|
|
* Handles form submission and displays the configuration form.
|
|
*/
|
|
public function getContent()
|
|
{
|
|
$output = '';
|
|
|
|
// Process form submission if it occurs
|
|
if (Tools::isSubmit('submitIbanTransferModule')) {
|
|
$output .= $this->postProcess();
|
|
}
|
|
|
|
// Display the configuration form
|
|
return $output . $this->renderForm();
|
|
}
|
|
|
|
/**
|
|
* Saves the configuration settings when the form is submitted.
|
|
*/
|
|
protected function postProcess()
|
|
{
|
|
if (Tools::isSubmit('submitIbanTransferModule')) {
|
|
// A list of configuration keys to update. This makes it easy to add more later.
|
|
$configKeys = [
|
|
'IBANTRANSFER_IBAN',
|
|
'IBANTRANSFER_RECEIVER_NAME',
|
|
'IBANTRANSFER_RECEIVER_CODE',
|
|
'IBANTRANSFER_DESCRIPTION_APPEND',
|
|
'IBANTRANSFER_API_TOKEN',
|
|
'IBANTRANSFER_OS_CREATION',
|
|
'IBANTRANSFER_OS_FULL_PAYMENT',
|
|
'IBANTRANSFER_OS_PARTIAL_PAYMENT',
|
|
];
|
|
|
|
foreach ($configKeys as $key) {
|
|
// We use Tools::getValue which sanitizes the input
|
|
Configuration::updateValue($key, Tools::getValue($key));
|
|
}
|
|
|
|
return $this->displayConfirmation($this->l('Settings have been updated successfully.'));
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Renders the configuration form using PrestaShop's HelperForm.
|
|
*/
|
|
public function renderForm()
|
|
{
|
|
// Define the structure of the configuration form
|
|
$fields_form = [];
|
|
|
|
// === Fieldset 1: Bank Account Details ===
|
|
$fields_form[0]['form'] = [
|
|
'legend' => [
|
|
'title' => $this->l('Bank Account Details'),
|
|
'icon' => 'icon-university', // A more appropriate icon
|
|
],
|
|
'input' => [
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('IBAN Account'),
|
|
'name' => 'IBANTRANSFER_IBAN',
|
|
'required' => true,
|
|
'desc' => $this->l('Enter the full IBAN for receiving payments.'),
|
|
'class' => 'fixed-width-xxl',
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Receiver Name'),
|
|
'name' => 'IBANTRANSFER_RECEIVER_NAME',
|
|
'required' => true,
|
|
'desc' => $this->l('Enter the full name of the account holder (individual or company).'),
|
|
'class' => 'fixed-width-xl',
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Receiver ID Code (EDRPOU/TIN)'),
|
|
'name' => 'IBANTRANSFER_RECEIVER_CODE',
|
|
'required' => true,
|
|
'desc' => $this->l('Enter the unique identification code for the receiver.'),
|
|
'class' => 'fixed-width-lg',
|
|
],
|
|
[
|
|
'type' => 'text',
|
|
'label' => $this->l('Append to Payment Description'),
|
|
'name' => 'IBANTRANSFER_DESCRIPTION_APPEND',
|
|
'required' => false,
|
|
'desc' => $this->l('This text will be added after the default description (e.g., "Payment for order #..."). You can use {order_reference} or {cart_id} as placeholders.'),
|
|
'class' => 'fixed-width-xxl',
|
|
],
|
|
],
|
|
'submit' => [
|
|
'title' => $this->l('Save'),
|
|
'class' => 'btn btn-default pull-right',
|
|
],
|
|
];
|
|
|
|
// === Fieldset 2: Order Statuses Configuration ===
|
|
$order_states = OrderState::getOrderStates((int)$this->context->language->id);
|
|
|
|
$fields_form[1]['form'] = [
|
|
'legend' => [
|
|
'title' => $this->l('Order Statuses'),
|
|
'icon' => 'icon-cogs',
|
|
],
|
|
'input' => [
|
|
[
|
|
'type' => 'select',
|
|
'label' => $this->l('Order Status on Creation'),
|
|
'name' => 'IBANTRANSFER_OS_CREATION',
|
|
'options' => [
|
|
'query' => $order_states,
|
|
'id' => 'id_order_state',
|
|
'name' => 'name',
|
|
],
|
|
'desc' => $this->l('The status for a new order created with this payment method (e.g., "Awaiting bank wire payment").'),
|
|
],
|
|
[
|
|
'type' => 'select',
|
|
'label' => $this->l('Order Status on Full Payment'),
|
|
'name' => 'IBANTRANSFER_OS_FULL_PAYMENT',
|
|
'options' => [
|
|
'query' => $order_states,
|
|
'id' => 'id_order_state',
|
|
'name' => 'name',
|
|
],
|
|
'desc' => $this->l('The status when the full payment is confirmed (e.g., "Payment accepted").'),
|
|
],
|
|
[
|
|
'type' => 'select',
|
|
'label' => $this->l('Order Status on Partial Payment'),
|
|
'name' => 'IBANTRANSFER_OS_PARTIAL_PAYMENT',
|
|
'options' => [
|
|
'query' => $order_states,
|
|
'id' => 'id_order_state',
|
|
'name' => 'name',
|
|
],
|
|
'desc' => $this->l('Optional: The status if a partial payment is received (e.g., "On backorder (paid)").'),
|
|
],
|
|
],
|
|
'submit' => [
|
|
'title' => $this->l('Save'),
|
|
'class' => 'btn btn-default pull-right',
|
|
],
|
|
];
|
|
|
|
// === Fieldset 3: API Integration ===
|
|
$fields_form[2]['form'] = [
|
|
'legend' => [
|
|
'title' => $this->l('API Integration (iban.pro)'),
|
|
'icon' => 'icon-key',
|
|
],
|
|
'input' => [
|
|
[
|
|
'type' => 'password', // Using 'password' type hides the token
|
|
'label' => $this->l('iban.pro Access Token'),
|
|
'name' => 'IBANTRANSFER_API_TOKEN',
|
|
'required' => false,
|
|
'desc' => $this->l('Enter your API access token from iban.pro to generate QR codes.'),
|
|
'class' => 'fixed-width-xxl',
|
|
],
|
|
],
|
|
'submit' => [
|
|
'title' => $this->l('Save'),
|
|
'class' => 'btn btn-default pull-right',
|
|
],
|
|
];
|
|
|
|
// --- HelperForm Boilerplate ---
|
|
$helper = new HelperForm();
|
|
$helper->module = $this;
|
|
$helper->name_controller = $this->name;
|
|
$helper->token = Tools::getAdminTokenLite('AdminModules');
|
|
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
|
|
$helper->default_form_language = (int)Configuration::get('PS_LANG_DEFAULT');
|
|
$helper->title = $this->displayName;
|
|
$helper->show_toolbar = true;
|
|
$helper->toolbar_scroll = true;
|
|
$helper->submit_action = 'submitIbanTransferModule';
|
|
|
|
// Load current values from the database
|
|
$configFields = [
|
|
'IBANTRANSFER_IBAN',
|
|
'IBANTRANSFER_RECEIVER_NAME',
|
|
'IBANTRANSFER_RECEIVER_CODE',
|
|
'IBANTRANSFER_DESCRIPTION_APPEND',
|
|
'IBANTRANSFER_API_TOKEN',
|
|
'IBANTRANSFER_OS_CREATION',
|
|
'IBANTRANSFER_OS_FULL_PAYMENT',
|
|
'IBANTRANSFER_OS_PARTIAL_PAYMENT'
|
|
];
|
|
foreach ($configFields as $field) {
|
|
$helper->fields_value[$field] = Configuration::get($field);
|
|
}
|
|
|
|
return $helper->generateForm($fields_form);
|
|
}
|
|
|
|
|
|
public function hookdisplayOrderConfirmation($params)
|
|
{
|
|
$order = $params['order'];
|
|
if ($order->payment == $this->paymentMethodName) {
|
|
return $this->getTPL($params['order']);
|
|
}
|
|
}
|
|
|
|
public function getTPL(Order $order)
|
|
{
|
|
|
|
$address = new Address($order->id_address_invoice);
|
|
$total = $order->total_paid;
|
|
$description = $order->reference . '; оплата замовлення #' . $order->id . '; ' . $address->lastname . ' ' . $address->firstname;
|
|
$NBULink = $this->getNBUv2($total, $description);
|
|
if (trim(shell_exec('command -v qrencode'))) {
|
|
// 3. If it exists, generate the QR code.
|
|
// CRITICAL: Always use escapeshellarg() on variables passed to shell commands
|
|
// to prevent command injection vulnerabilities.
|
|
$escapedNBULink = escapeshellarg($NBULink);
|
|
$qr = shell_exec("qrencode -o - -s 4 -t SVG $escapedNBULink");
|
|
|
|
// 4. (Optional but recommended) Add a final check in case the command fails for other reasons.
|
|
if (empty($qr)) {
|
|
$qr = $this->context->smarty->fetch($this->local_path . 'views/templates/front/emptyQR.svg');
|
|
}
|
|
} else {
|
|
// 5. If 'qrencode' is not found, assign the placeholder.
|
|
$qr = $this->context->smarty->fetch($this->local_path . 'views/templates/front/emptyQR.svg');
|
|
}
|
|
$this->context->smarty->assign([
|
|
'reciever_name' => Configuration::get('IBANTRANSFER_RECEIVER_NAME'),
|
|
'iban' => Configuration::get('IBANTRANSFER_IBAN'),
|
|
'reciever_code' => Configuration::get('IBANTRANSFER_RECEIVER_CODE'),
|
|
'description' => $description . ' ' . Configuration::get('IBANTRANSFER_DESCRIPTION_APPEND'),
|
|
'total' => $total,
|
|
'NBULink' => $NBULink,
|
|
'qr' => $qr,
|
|
|
|
]);
|
|
|
|
return $this->display(__FILE__, '/views/templates/front/displayOrderConfirmation.tpl');
|
|
}
|
|
|
|
public function getNBUv2($amount, $description)
|
|
{
|
|
|
|
$display = '';
|
|
$ibanSUM = sprintf('UAH%s', number_format((float) $amount, 2, '.', ''));
|
|
|
|
$codeContentsV2 = implode("\n", array(
|
|
mb_convert_encoding('BCD', 'ASCII'),
|
|
mb_convert_encoding(sprintf('%03d', '2'), 'ASCII'),
|
|
mb_convert_encoding('2', 'ASCII'),
|
|
mb_convert_encoding('UCT', 'ASCII'),
|
|
'',
|
|
mb_convert_encoding($this->reciever_name, 'windows-1251'),
|
|
mb_convert_encoding(Configuration::get('IBANTRANSFER_IBAN'), 'ASCII'),
|
|
mb_convert_encoding($ibanSUM, 'ASCII'),
|
|
mb_convert_encoding($this->reciever_code, 'windows-1251'),
|
|
'',
|
|
'',
|
|
mb_convert_encoding($description, 'windows-1251'),
|
|
$display,
|
|
'',
|
|
));
|
|
|
|
return 'https://bank.gov.ua/qr/' . $this->base64url_encode($codeContentsV2);
|
|
}
|
|
|
|
public static function base64url_encode($data)
|
|
{
|
|
// First of all you should encode $data to Base64 string
|
|
$b64 = base64_encode($data);
|
|
|
|
// Make sure you get a valid result, otherwise, return FALSE, as the base64_encode() function do
|
|
if ($b64 === false) {
|
|
return false;
|
|
}
|
|
|
|
// Convert Base64 to Base64URL by replacing “+” with “-” and “/” with “_”
|
|
$url = strtr($b64, '+/', '-_');
|
|
|
|
// Remove padding character from the end of line and return the Base64URL result
|
|
return rtrim($url, '=');
|
|
}
|
|
|
|
|
|
public function hookPaymentOptions($params)
|
|
{
|
|
|
|
if (!$this->active) {
|
|
return;
|
|
}
|
|
if (!Configuration::get('IBANTRANSFER_IBAN') || !Configuration::get('IBANTRANSFER_RECEIVER_CODE') || !Configuration::get('IBANTRANSFER_RECEIVER_NAME')) {
|
|
return;
|
|
}
|
|
|
|
$payment_options = [
|
|
|
|
$this->getPaymentOption(),
|
|
|
|
];
|
|
|
|
return $payment_options;
|
|
}
|
|
|
|
public function getPaymentOption()
|
|
{
|
|
$externalOption = new \PrestaShop\PrestaShop\Core\Payment\PaymentOption();
|
|
$externalOption->setCallToActionText($this->l('Оплата переказом за реквізитами IBAN'))
|
|
->setAction($this->context->link->getModuleLink($this->name, 'validation', ['methodPayment' => 'onlinePayment'], true))
|
|
// ->setInputs([ 'onlinePayment' => true, ])
|
|
->setAdditionalInformation($this->context->smarty->fetch('module:' . $this->name . '/views/templates/front/payment_info.tpl'))
|
|
// ->setLogo(Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/payment.jpg'))
|
|
;
|
|
|
|
return $externalOption;
|
|
}
|
|
}
|