diff --git a/README.md b/README.md index 36a424f..377cb74 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # PayWeb_PrestaShop_1.7 -## PayGate PrestaShop plugin v1.7.8 for PrestaShop v 1.7.6.x +## PayGate PrestaShop plugin v1.7.9 for PrestaShop v 1.7.7.x This is the PayGate PayWeb3 plugin for PrestaShop. Please feel free to contact the PayGate support team at support@paygate.co.za should you require any assistance. ## Installation [![How To Setup PayGate PayWeb for PrestaShop 1.7](https://appinlet.com/wp-content/uploads/2021/01/How-To-Setup-PayGate-PayWeb-for-PrestaShop-1.7.jpg)](https://www.youtube.com/watch?v=H3e624nH5Wk "How To Setup PayGate PayWeb for PrestaShop 1.7") -Please navigate to the [releases page](https://github.com/PayGate/PayWeb_PrestaShop_1.7/releases), download the latest release (v1.7.8) and unzip. You will then be able to follow the integration guide PDF which is included in the zip. +Please navigate to the [releases page](https://github.com/PayGate/PayWeb_PrestaShop_1.7/releases), download the latest release (v1.7.9) and unzip. You will then be able to follow the integration guide PDF which is included in the zip. ## Collaboration diff --git a/paygate/assets/images/PayGate_Plus_logo.svg b/paygate/assets/images/PayGate_Plus_logo.svg new file mode 100644 index 0000000..32d16e8 --- /dev/null +++ b/paygate/assets/images/PayGate_Plus_logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/PayGate_logo.svg b/paygate/assets/images/PayGate_logo.svg new file mode 100644 index 0000000..e5b0bb7 --- /dev/null +++ b/paygate/assets/images/PayGate_logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/mastercard-visa.svg b/paygate/assets/images/mastercard-visa.svg new file mode 100644 index 0000000..ccd49a7 --- /dev/null +++ b/paygate/assets/images/mastercard-visa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/masterpass.svg b/paygate/assets/images/masterpass.svg new file mode 100644 index 0000000..b12d5ab --- /dev/null +++ b/paygate/assets/images/masterpass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/mobicred.svg b/paygate/assets/images/mobicred.svg new file mode 100644 index 0000000..be10134 --- /dev/null +++ b/paygate/assets/images/mobicred.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/momopay.svg b/paygate/assets/images/momopay.svg new file mode 100644 index 0000000..7ba27c0 --- /dev/null +++ b/paygate/assets/images/momopay.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/sid.svg b/paygate/assets/images/sid.svg new file mode 100644 index 0000000..fe0f721 --- /dev/null +++ b/paygate/assets/images/sid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/snapscan.svg b/paygate/assets/images/snapscan.svg new file mode 100644 index 0000000..6c72916 --- /dev/null +++ b/paygate/assets/images/snapscan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/assets/images/zapper.svg b/paygate/assets/images/zapper.svg new file mode 100644 index 0000000..a67401a --- /dev/null +++ b/paygate/assets/images/zapper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/paygate/changelog.txt b/paygate/changelog.txt index 4b92c62..67a0940 100755 --- a/paygate/changelog.txt +++ b/paygate/changelog.txt @@ -1,23 +1,40 @@ ===================================== Date : Version: Description ===================================== - -2017-11-22: v1.0.0 : Initial Release. -2017-12-04: : Add return url. - : Code reformat. +2021-06-18: v1.7.9 : Change notify handler to match redirect. + Addresses double price issue. + Fix double order issue on some servers. + Code quality improvements. + Update for PrestaShop 1.7.7.x + Add payment type selection to checkout. -2018-08-06: v1.0.1 : Code format. - Logo changes. +2020-11-23: v1.7.8 : Add 'Disable IPN' feature. + Fix undefined $order issue. + Improve payment reference readability. -2019-07-03: v1.7.5 : Url encode notify. +2020-09-17: v1.7.7 : Fix sessions cleared in some browsers. + Resolve shipping ignored issue with some providers. 2019-12-07: v1.7.6 : Included PW3 query in confirmation.php (direct return). Handle cases where order has already been updated by notify. -2020-09-17: v1.7.7 : Fix sessions cleared in some browsers. - Resolve shipping ignored issue with some providers. +2019-07-03: v1.7.5 : Url encode notify. + +2018-08-06: v1.0.1 : Code format. + Logo changes. + +2017-12-04: : Add return url. + : Code reformat. + +2017-11-22: v1.0.0 : Initial Release. + + + + + + + + + -2020-11-23: v1.7.8 : Add 'Disable IPN' feature. - Fix undefined $order issue. - Improve payment reference readability. \ No newline at end of file diff --git a/paygate/classes/countries.php b/paygate/classes/countries.php index 9db7c00..584a261 100644 --- a/paygate/classes/countries.php +++ b/paygate/classes/countries.php @@ -1,6 +1,6 @@ [ + 'name' => 'paygate-paymethod', + 'label' => 'Credit Card', + 'img' => '../modules/paygate/assets/images/mastercard-visa.svg', + 'ptype' => 'CC', + 'type' => 'radio', + 'value' => 'creditcard', + 'title' => 'Credit Card', + ], + 'banktransfer' => [ + 'name' => 'paygate-paymethod', + 'label' => 'Bank Transfer', + 'img' => '../modules/paygate/assets/images/sid.svg', + 'ptype' => 'BT', + 'type' => 'radio', + + ], + 'zapper' => [ + 'name' => 'paygate-paymethod', + 'label' => 'Zapper', + 'img' => '../modules/paygate/assets/images/zapper.svg', + 'ptype' => '', + 'type' => 'radio', + ], + 'snapscan' => [ + 'name' => 'paygate-paymethod', + 'label' => 'SnapScan', + 'img' => '../modules/paygate/assets/images/snapscan.svg', + 'ptype' => 'EW', + 'type' => 'radio', + ], + 'mobicred' => [ + 'name' => 'paygate-paymethod', + 'label' => 'MobiCred', + 'img' => '../modules/paygate/assets/images/mobicred.svg', + 'ptype' => 'EW', + 'type' => 'radio', + ], + 'momopay' => [ + 'name' => 'paygate-paymethod', + 'label' => 'MomoPay', + 'img' => '../modules/paygate/assets/images/momopay.svg', + 'ptype' => 'EW', + 'type' => 'radio', + ], + 'masterpass' => [ + 'name' => 'paygate-paymethod', + 'label' => 'MasterPass', + 'img' => '../modules/paygate/assets/images/masterpass.svg', + 'ptype' => 'EW', + 'type' => 'radio', + ], + ]; + } + +} diff --git a/paygate/config.xml b/paygate/config.xml index ca3bde2..7fc3bdb 100755 --- a/paygate/config.xml +++ b/paygate/config.xml @@ -1,17 +1,17 @@ paygate - + @@ -19,4 +19,4 @@ 1 1 - \ No newline at end of file + diff --git a/paygate/controllers/front/confirmation.php b/paygate/controllers/front/confirmation.php index 4aee2fd..60d4509 100755 --- a/paygate/controllers/front/confirmation.php +++ b/paygate/controllers/front/confirmation.php @@ -1,6 +1,6 @@ context->cookie->cart_id); - $status = null; + $order = Order::getByCartId($cart->id); - $cart = new Cart( $this->context->cookie->cart_id ); - $key = Tools::getValue( 'secure_key' ); - $ispaid = false; + $status = null; // Check to see if there is already an order for this cart - it may have been created by notify (validate.php) - if ( $cart->orderExists() ) { - // Get order - $order = Order::getByCartId( $cart->id ); - $ispaid = $order->hasBeenPaid(); + if ($order && $order->hasBeenPaid()) { + Tools::redirect( + $this->context->link->getPageLink( + 'order-confirmation', + null, + null, + 'key=' . $cart->secure_key . '&id_cart=' . (int)($cart->id) . '&id_module=' . (int)($this->module->id) + ) + ); } - if ( $ispaid ) { - Tools::redirect( $this->context->link->getPageLink( 'order-confirmation', null, null, 'key=' . $cart->secure_key . '&id_cart=' . (int) ( $cart->id ) . '&id_module=' . (int) ( $this->module->id ) ) ); + $pg_id = Configuration::get('PAYGATE_ID'); + $pg_key = Configuration::get('PAYGATE_ENCRYPTION_KEY'); + $reference = $this->context->cookie->reference; + + if (!$this->isResponseValid($cart)) { + Tools::redirect( + $this->context->link->getPageLink( + 'cart', + null, + null, + 'action=show' + ) + ); } - if ( $key == $cart->secure_key && isset( $_POST['TRANSACTION_STATUS'] ) && !empty( $_POST['TRANSACTION_STATUS'] ) ) { - - switch ( $_POST['TRANSACTION_STATUS'] ) { - case '1': - // Make POST request to PayGate to query the transaction and get full response data - $post = $_POST; - $pg_checksum = array_pop( $post ); - $reference = $this->context->cookie->reference; - $pg_id = Configuration::get( 'PAYGATE_ID' ); - $pg_key = Configuration::get( 'PAYGATE_ENCRYPTION_KEY' ); - $our_checksum = md5( $pg_id . implode( '', $post ) . $reference . $pg_key ); - - if ( hash_equals( $our_checksum, $pg_checksum ) ) { - $data = []; - $data['PAYGATE_ID'] = $pg_id; - $data['PAY_REQUEST_ID'] = $post['PAY_REQUEST_ID']; - $data['REFERENCE'] = $reference; - $data['CHECKSUM'] = md5( implode( '', $data ) . $pg_key ); - $fieldsString = http_build_query( $data ); - - // Open connection - $ch = curl_init(); - - // Set the url, number of POST vars, POST data - curl_setopt( $ch, CURLOPT_URL, 'https://secure.paygate.co.za/payweb3/query.trans' ); - curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); - curl_setopt( $ch, CURLOPT_NOBODY, false ); - curl_setopt( $ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST'] ); - curl_setopt( $ch, CURLOPT_POST, true ); - curl_setopt( $ch, CURLOPT_POSTFIELDS, $fieldsString ); - - // Execute post - $result = curl_exec( $ch ); - parse_str( $result, $result ); - curl_close( $ch ); - - if ( is_array( $result ) && isset( $result['TRANSACTION_STATUS'] ) ) { - // Update purchase status - $method_name = $this->module->displayName; - if (Configuration::get( 'PAYGATE_IPN_TOGGLE' )) { - if ( !$order ) { - $this->module->validateOrder( $cart->id, _PS_OS_PAYMENT_, (float) ( $result['AMOUNT'] / 100.0 ), - $method_name, null, array( 'transaction_id' => $result['USER1'] ), null, false, $cart->secure_key ); - } else { - $order->addOrderPayment( (float) ( $result['AMOUNT'] / 100.0 ), $method_name, $cart->secure_key ); - } - } - Tools::redirect( $this->context->link->getPageLink( 'order-confirmation', null, null, 'key=' . $cart->secure_key . '&id_cart=' . (int) ( $cart->id ) . '&id_module=' . (int) ( $this->module->id ) ) ); + switch ($_POST['TRANSACTION_STATUS']) { + case '1': + // Make POST request to PayGate to query the transaction and get full response data + $post = $_POST; + + $data = []; + $data['PAYGATE_ID'] = $pg_id; + $data['PAY_REQUEST_ID'] = $post['PAY_REQUEST_ID']; + $data['REFERENCE'] = $reference; + $data['CHECKSUM'] = md5(implode('', $data) . $pg_key); + $fieldsString = http_build_query($data); + + $result = $this->makeQueryRequest($fieldsString); + + if (!empty($result)) { + // Update purchase status + $extra_vars['transaction_id'] = $result['USER1']; + $method_name = $this->module->displayName; + if (!$order) { + $this->module->validateOrder( + (int)$cart->id, + _PS_OS_PAYMENT_, + (float)($result['AMOUNT'] / 100.0), + $method_name, + NULL, + $extra_vars, + NULL, + false, + $cart->secure_key + ); + } else { + if(!$order->hasBeenPaid()) { + $order->addOrderPayment( + (float)($result['AMOUNT'] / 100.0), + $method_name, + $result['USER1'] + ); } } - break; + Tools::redirect( + $this->context->link->getPageLink( + 'order-confirmation', + null, + null, + 'key=' . $cart->secure_key . '&id_cart=' . (int)($cart->id) . '&id_module=' . (int)($this->module->id) + ) + ); + } + + break; + + case '2': + $status = 2; + break; + + case '4': + $status = 4; + break; + + default: + break; + } - case '2': - $status = 2; - break; - case '4': - $status = 4; - break; + $this->context->smarty->assign('status', $status); - default: - break; - } + $this->setTemplate('module:paygate/views/templates/front/confirmation.tpl'); + } + private function isResponseValid($cart) + { + $key = Tools::getValue('secure_key'); + if ($key != $cart->secure_key || empty($_POST['TRANSACTION_STATUS'])) { + return false; } - - $this->context->smarty->assign( 'status', $status ); - - $this->setTemplate( 'module:paygate/views/templates/front/confirmation.tpl' ); + $post = $_POST; + $pg_checksum = array_pop($post); + $reference = $this->context->cookie->reference; + $pg_id = Configuration::get('PAYGATE_ID'); + $pg_key = Configuration::get('PAYGATE_ENCRYPTION_KEY'); + $our_checksum = md5($pg_id . implode('', $post) . $reference . $pg_key); + if (!hash_equals($pg_checksum, $our_checksum)) { + return false; + } + return true; } + private function makeQueryRequest($fieldsString) + { + // Open connection + $ch = curl_init(); + + // Set the url, number of POST vars, POST data + curl_setopt($ch, CURLOPT_URL, 'https://secure.paygate.co.za/payweb3/query.trans'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_NOBODY, false); + curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST']); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fieldsString); + + // Execute post + $result = curl_exec($ch); + parse_str($result, $result); + curl_close($ch); + + if (is_array($result) && isset($result['TRANSACTION_STATUS'])) { + return $result; + } + } } diff --git a/paygate/controllers/front/payment.php b/paygate/controllers/front/payment.php index 23ab073..945bb30 100755 --- a/paygate/controllers/front/payment.php +++ b/paygate/controllers/front/payment.php @@ -1,6 +1,6 @@ module->name . '/classes/countries.php'; + require_once _PS_MODULE_DIR_ . $this->module->name . '/classes/methods.php'; require_once _PS_MODULE_DIR_ . $this->module->name . '/paygate.php'; $iso_code = $this->context->language->iso_code; $cart_id = $this->context->cart->id; $customer_id = $this->context->cart->id_customer; $secure_key = $this->context->cart->secure_key; + + $paygateMethodsList = new PaygateMethodsList(); + $this->paygatePayMethods = $paygateMethodsList->getPaygateMethodsList(); // Buyer details $customer = new Customer( (int) ( $customer_id ) ); @@ -51,103 +58,52 @@ public function initContent() $this->context->cookie->reference = $reference; $amount = filter_var( $total * 100, FILTER_SANITIZE_NUMBER_INT ); $currency = filter_var( $currency->iso_code, FILTER_SANITIZE_STRING ); - $returnUrl = filter_var( $this->context->link->getModuleLink( $this->module->name, 'confirmation', ['secure_key' => $secure_key], true ), FILTER_SANITIZE_URL ); + $returnUrl = filter_var( $this->context->link->getModuleLink( $this->module->name, 'confirmation', ['secure_key' => $secure_key, 'cart_id' => $cart_id], true ), FILTER_SANITIZE_URL ); $transDate = filter_var( date( 'Y-m-d H:i:s' ), FILTER_SANITIZE_STRING ); $locale = filter_var( $iso_code, FILTER_SANITIZE_STRING ); $country = filter_var( $country_code3, FILTER_SANITIZE_STRING ); $email = filter_var( $customer->email, FILTER_SANITIZE_EMAIL ); - $payMethod = ''; - $payMethodDetail = ''; $notifyUrl = filter_var( $this->context->link->getModuleLink( $this->module->name, 'validate', array(), true ), FILTER_SANITIZE_STRING ); $userField1 = $cart_id; $userField2 = $secure_key; $userField3 = $this->module->id; - $doVault = ''; - $vaultID = ''; $encryption_key = Configuration::get( 'PAYGATE_ENCRYPTION_KEY' ); - $checksum_source = $paygateID . $reference . $amount . $currency . $returnUrl . $transDate; - - if ( $locale ) { - $checksum_source .= $locale; - } - - if ( $country ) { - $checksum_source .= $country; - } - - if ( $email ) { - $checksum_source .= $email; - } - - if ( $payMethod ) { - $checksum_source .= $payMethod; - } - - if ( $payMethodDetail ) { - $checksum_source .= $payMethodDetail; - } - - if ( $notifyUrl ) { - $checksum_source .= $notifyUrl; - } - - if ( $userField1 ) { - $checksum_source .= $userField1; - } - - if ( $userField2 ) { - $checksum_source .= $userField2; - } - - if ( $userField3 ) { - $checksum_source .= $userField3; - } - - if ( $doVault != '' ) { - $checksum_source .= $doVault; - } - - if ( $vaultID != '' ) { - $checksum_source .= $vaultID; - } - - $checksum_source .= $encryption_key; - - $checksum = md5( $checksum_source ); - $returnUrl = urlencode( $returnUrl ); - $notifyUrl = urlencode( $notifyUrl ); $initiateData = array( 'PAYGATE_ID' => $paygateID, 'REFERENCE' => $reference, 'AMOUNT' => $amount, 'CURRENCY' => $currency, - 'RETURN_URL' => $returnUrl, + 'RETURN_URL' => urlencode($returnUrl), 'TRANSACTION_DATE' => $transDate, 'LOCALE' => $locale, 'COUNTRY' => $country, 'EMAIL' => $email, - 'PAY_METHOD' => $payMethod, - 'PAY_METHOD_DETAIL' => $payMethodDetail, + 'PAY_METHOD' => 'CC', 'NOTIFY_URL' => $notifyUrl, 'USER1' => $userField1, 'USER2' => $userField2, - 'USER3' => $userField3, - 'VAULT' => $doVault, - 'VAULT_ID' => $vaultID, - 'CHECKSUM' => $checksum, + 'USER3' => $userField3 ); - $fields_string = ''; - - // Url-ify the data for the POST - foreach ( $initiateData as $key => $value ) { - $fields_string .= $key . '=' . $value . '&'; + // Do not add notify return url if it is not enabled + if(Configuration::get('PAYGATE_IPN_TOGGLE')){ + unset($initiateData['NOTIFY_URL']); } - $fields_string = rtrim( $fields_string, '&' ); + if(isset($_POST['paygatePayMethodRadio'])){ + $payMethod = $this->paygatePayMethods[$_POST['paygatePayMethodRadio']]['ptype']; + if($payMethod !== null){ + $initiateData['PAY_METHOD'] = $payMethod; + } + } - $responseData = ''; + $checksum_source = ''; + foreach ($initiateData as $initiateDatum){ + $checksum_source .= $initiateDatum; + } + $checksum_source .= $encryption_key; + $initiateData['CHECKSUM'] = md5($checksum_source); try { // Open connection @@ -158,7 +114,7 @@ public function initContent() curl_setopt( $ch, CURLOPT_NOBODY, false ); curl_setopt( $ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST'] ); curl_setopt( $ch, CURLOPT_POST, 1 ); - curl_setopt( $ch, CURLOPT_POSTFIELDS, $fields_string ); + curl_setopt( $ch, CURLOPT_POSTFIELDS, $initiateData ); // Execute post $result = curl_exec( $ch ); @@ -167,7 +123,7 @@ public function initContent() curl_close( $ch ); } catch ( Exception $e ) { - + echo $e->getMessage(); } $r = []; diff --git a/paygate/controllers/front/validate.php b/paygate/controllers/front/validate.php index 99953b4..ae79f9e 100644 --- a/paygate/controllers/front/validate.php +++ b/paygate/controllers/front/validate.php @@ -1,6 +1,6 @@ module->logData( "=========Notify Response: " . date( 'Y-m-d H:i:s' ) . "============\n\n" ); - - if ( !$errors && !$toggleIPN ) { - foreach ( $_POST as $key => $val ) { - $post_data .= $key . '=' . $val . "\n"; - $notify_data[$key] = stripslashes( $val ); + $notify_data = array(); - if ( $key == 'PAYGATE_ID' ) { - $checkSumParams .= Configuration::get( 'PAYGATE_ID' ); - } else { - if ( $key != 'CHECKSUM' ) { - $checkSumParams .= $val; - } - } - if ( empty( $notify_data ) ) { - $error_msg = 'Notify post response is empty'; - $errors = true; - } - } - - $checkSumParams .= Configuration::get( 'ENCRYPTION_KEY' ); + // Sanitize POST data + foreach ($_POST as $key => $value){ + $notify_data[$key] = stripslashes($value); } - $this->module->logData( $post_data ); - $this->module->logData( "\n" ); + $this->module->logData("=========Notify Response: " . date('Y-m-d H:i:s') . "============\n\n"); - if ( empty( Context::getContext()->link ) ) { - Context::getContext()->link = new Link(); + if (!$this->validateResponse()) { + // Notify PayGate that information has been received + die('OK'); } - // Verify security signature - if ( !$errors && !$toggleIPN ) { - $checkSumParams = md5( $checkSumParams ); - if ( !hash_equals( $checkSumParams, $notify_data['CHECKSUM'] ) ) { - $error_message = 'Invalid checksum, checksum: ' . $checkSumParams; - } + if (empty(Context::getContext()->link)) { + Context::getContext()->link = new Link(); } // Check status and update order - if ( !$errors && !$toggleIPN) { - $transaction_id = $notify_data['TRANSACTION_ID']; - $method_name = $this->module->displayName; + $method_name = $this->module->displayName; - if ( $notify_data['PAY_METHOD_DETAIL'] != '' ) { - $method_name = 'PayGate'; - } - switch ( $notify_data['TRANSACTION_STATUS'] ) { - case '1': - // Update the purchase status - $this->module->paygateValidate( - (int) $notify_data['USER1'], + if ($notify_data['PAY_METHOD_DETAIL'] != '') { + $method_name = 'PayGate'; + } + switch ($notify_data['TRANSACTION_STATUS']) { + case '1': + $cart_id = $notify_data['USER1']; + $cart = new Cart($cart_id); + if ($cart->orderExists()) { + $order = Order::getByCartId($cart_id); + if ($order && $order->hasBeenPaid()) { + exit(); + } + } + + // Update the purchase status + if (!$order) { + $extra_vars['transaction_id'] = $notify_data['USER1']; + $this->module->validateOrder( + (int)$cart->id, _PS_OS_PAYMENT_, - ( (int) $notify_data['AMOUNT'] ) / 100, + (float)($notify_data['AMOUNT'] / 100.0), $method_name, - null, - array( 'transaction_id' => $transaction_id ), - null, + NULL, + $extra_vars, + NULL, false, - $notify_data['USER2'] + $cart->secure_key + ); + } else { + $order->addOrderPayment( + (float)($notify_data['AMOUNT'] / 100.0), + $method_name, + $notify_data['USER1'] ); - $this->module->logData( "Done updating order status\n\n" ); - break; + } - case '2': - // Failed status - break; + $this->module->logData("Done updating order status\n\n"); + break; - case '4': - // Cancelled status - break; + case '2': + // Failed status + break; - default: - // If unknown status, do nothing (safest course of action) - break; - } - } + case '4': + // Cancelled status + break; - if ( $errors ) { - $this->module->logData( $error_msg . "\n" ); + default: + // If unknown status, do nothing (safest course of action) + break; } + // Notify PayGate that information has been received + die('OK'); + } + + private function validateResponse() + { + $post_data = ''; + $checkSumParams = ''; + $disableIPN = Configuration::get('PAYGATE_IPN_TOGGLE'); + if ($disableIPN) { + return false; + } + foreach ($_POST as $key => $val) { + $post_data .= $key . '=' . $val . "\n"; + + if ($key == 'PAYGATE_ID') { + $checkSumParams .= Configuration::get('PAYGATE_ID'); + } else { + if ($key != 'CHECKSUM') { + $checkSumParams .= $val; + } + } + } + $this->module->logData($post_data); + $this->module->logData("\n"); - die( 'OK' ); + $checkSumParams .= Configuration::get('ENCRYPTION_KEY'); + // Verify security signature + $checkSumParams = md5($checkSumParams); + if (!hash_equals($checkSumParams, $_POST['CHECKSUM'])) { + $this->module->logData('Invalid checksum, checksum: ' . $checkSumParams); + return false; + } } } diff --git a/paygate/paygate.php b/paygate/paygate.php index c66eb61..358ac23 100755 --- a/paygate/paygate.php +++ b/paygate/paygate.php @@ -1,6 +1,6 @@ name = 'paygate'; $this->tab = 'payments_gateways'; - $this->version = '1.7.8'; + $this->version = '1.7.9'; $this->author = 'PayGate'; $this->controllers = array( 'payment', 'validation' ); - + + $paygateMethodsList = new PaygateMethodsList(); + $this->paygatePayMethods = $paygateMethodsList->getPaygateMethodsList(); + $this->bootstrap = true; parent::__construct(); @@ -65,20 +73,66 @@ public function uninstall() return ( parent::uninstall() ); } + /** + * @param $params + * @return array|PaymentOption[] + */ public function hookPaymentOptions( $params ) { if ( !$this->active ) { - return; + return []; } $this->updateOrAddToTable(); $this->clearOldOrders(); + // Get and display Pay Methods set in configuration + $action = $this->context->link->getModuleLink($this->name, 'payment', [], true); + $payOptionsHtml = << +

Make Payment Via PayGate

+HTML; + $pt = 0; + foreach ($this->paygatePayMethods as $key => $paygatePayMethod) { + $k = 'PAYGATE_PAYMENT_METHODS_' . $key; + if (Configuration::get($k) != '') { + $pt++; + } + } + + if($pt > 0){ + $payOptionsHtml .= <<Choose a PayGate Payment Method below:

+HTML; + } + + foreach ($this->paygatePayMethods as $key => $paygatePayMethod) { + $k = 'PAYGATE_PAYMENT_METHODS_' . $key; + if (Configuration::get($k) != '') { + $payOptionsHtml .= << +{$paygatePayMethod['label']} +{$paygatePayMethod['label']}

+HTML; + } + } + + $inputs = []; + foreach ($this->paygatePayMethods as $key => $paygatePayMethod) { + $k = 'PAYGATE_PAYMENT_METHODS_' . $key; + if (Configuration::get($k) != '') { + $inputs[$key] = $paygatePayMethod; + } + } + + $payOptionsHtml .= ''; + $paymentOption = new PaymentOption(); - $paymentOption->setCallToActionText( 'Pay Via Paygate' ) - ->setAction( $this->context->link->getModuleLink( $this->name, 'payment', [], true ) ) - ->setAdditionalInformation( "

Make Payment Via Paygate

Visa and MasterCard accepted.

" ) - ->setLogo( Media::getMediaPath( _PS_MODULE_DIR_ . $this->name . '/logo.png' ) ); + $paymentOption->setCallToActionText( 'Pay via PayGate' ) + ->setForm($payOptionsHtml) + ->setLogo(Media::getMediaPath(_PS_MODULE_DIR_ . $this->name . '/logo.png')) + ->setAction($this->context->link->getModuleLink($this->name, 'payment', [], true)); + return [$paymentOption]; } @@ -88,7 +142,7 @@ public function clearOldOrders() $sql = 'SELECT `cart_id` FROM ' . _DB_PREFIX_ . 'paygate;'; $results = Db::getInstance()->ExecuteS( $sql ); foreach ( $results as $id ) { - foreach ( $id as $key => $cartID ) { + foreach ( $id as $cartID ) { $check_cart = new cart( $cartID ); if ( $check_cart->orderExists() ) { Db::getInstance()->delete( 'paygate', 'cart_id =' . $cartID ); @@ -211,7 +265,7 @@ public function updateOrAddToTable() $check_if_row_exists = Db::getInstance()->getValue( 'SELECT cart_id FROM ' . _DB_PREFIX_ . 'paygate WHERE cart_id="' . (int) $cart_id . '"' ); - if ( $check_if_row_exists == false ) { + if ( $check_if_row_exists == '' ) { Db::getInstance()->insert( 'paygate', array( @@ -284,24 +338,24 @@ public function renderForm() ), array( 'type' => 'switch', - 'label' => $this->trans( 'Disable IPN', array(), 'Modules.Paygate.Admin' ), + 'label' => $this->trans( 'Disable IPN', array(), self::PAYGATE_ADMIN ), 'name' => 'PAYGATE_IPN_TOGGLE', 'values' => array( array( 'id' => 'active_on', 'value' => 1, - 'label' => $this->trans( 'IPN', array(), 'Modules.Paygate.Admin' ), + 'label' => $this->trans( 'IPN', array(), self::PAYGATE_ADMIN ), ), array( 'id' => 'active_off', 'value' => 0, - 'label' => $this->trans( 'Redirect', array(), 'Modules.Paygate.Admin' ), + 'label' => $this->trans( 'Redirect', array(), self::PAYGATE_ADMIN ), ), ), ), array( 'type' => 'switch', - 'label' => $this->trans( 'Debug', array(), 'Modules.Paygate.Admin' ), + 'label' => $this->trans( 'Debug', array(), self::PAYGATE_ADMIN ), 'name' => 'PAYGATE_LOGS', 'values' => array( array( @@ -316,6 +370,52 @@ public function renderForm() ), ), ), + array( + 'type' => 'checkbox', + 'label' => $this->trans('Enable Payment Method(s)', array(), self::PAYGATE_ADMIN), + 'name' => 'PAYGATE_PAYMENT_METHODS', + 'values' => array( + 'query' => array( + array( + 'id' => 'creditcard', + 'name' => 'Credit CardsCredit Cards', + 'val' => 'creditcard', + ), + array( + 'id' => 'banktransfer', + 'name' => 'Bank TransferBank Transfer', + 'val' => 'banktransfer', + ), + array( + 'id' => 'zapper', + 'name' => 'ZapperZapper', + 'val' => 'zapper', + ), + array( + 'id' => 'snapscan', + 'name' => 'SnapscanSanpscan', + 'val' => 'snapscan', + ), + array( + 'id' => 'mobicred', + 'name' => 'MobiCredMobiCred', + 'val' => 'mobicred', + ), + array( + 'id' => 'momopay', + 'name' => 'MomoPayMomoPay', + 'val' => 'momopay', + ), + array( + 'id' => 'masterpass', + 'name' => 'MasterPassMasterPass', + 'val' => 'masterpass', + ), + ), + 'id' => 'id', + 'name' => 'name', + ), + ), ), 'submit' => array( 'title' => $this->trans( 'Save', array(), 'Admin.Actions' ), @@ -367,6 +467,34 @@ private function _postProcess() Configuration::updateValue( 'PAYGATE_ENCRYPTION_KEY', Tools::getValue( 'PAYGATE_ENCRYPTION_KEY' ) ); Configuration::updateValue( 'PAYGATE_LOGS', Tools::getValue( 'PAYGATE_LOGS' ) ); Configuration::updateValue( 'PAYGATE_IPN_TOGGLE', Tools::getValue( 'PAYGATE_IPN_TOGGLE' ) ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_creditcard', + Tools::getValue('PAYGATE_PAYMENT_METHODS_creditcard') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_banktransfer', + Tools::getValue('PAYGATE_PAYMENT_METHODS_banktransfer') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_zapper', + Tools::getValue('PAYGATE_PAYMENT_METHODS_zapper') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_snapscan', + Tools::getValue('PAYGATE_PAYMENT_METHODS_snapscan') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_mobicred', + Tools::getValue('PAYGATE_PAYMENT_METHODS_mobicred') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_momopay', + Tools::getValue('PAYGATE_PAYMENT_METHODS_momopay') + ); + Configuration::updateValue( + 'PAYGATE_PAYMENT_METHODS_masterpass', + Tools::getValue('PAYGATE_PAYMENT_METHODS_masterpass') + ); } $this->_html .= $this->displayConfirmation( $this->trans( 'Settings updated', array(), 'Admin.Notifications.Success' ) @@ -381,8 +509,56 @@ public function getConfigFieldsValues() 'PAYGATE_ENCRYPTION_KEY', Configuration::get( 'PAYGATE_ENCRYPTION_KEY' ) ), - 'PAYGATE_LOGS' => Tools::getValue( 'PAYGATE_LOGS', Configuration::get( 'PAYGATE_LOGS' ) ), - 'PAYGATE_IPN_TOGGLE' => Tools::getValue( 'PAYGATE_IPN_TOGGLE', Configuration::get( 'PAYGATE_IPN_TOGGLE' ) ), + 'PAYGATE_LOGS' => Tools::getValue( + 'PAYGATE_LOGS', + Configuration::get('PAYGATE_LOGS') + ), + 'PAYGATE_IPN_TOGGLE' => Tools::getValue( + 'PAYGATE_IPN_TOGGLE', + Configuration::get('PAYGATE_IPN_TOGGLE') + ), + 'PAYGATE_PAYMENT_METHODS_creditcard' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_creditcard', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_creditcard' + ) + ), + 'PAYGATE_PAYMENT_METHODS_banktransfer' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_banktransfer', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_banktransfer' + ) + ), + 'PAYGATE_PAYMENT_METHODS_zapper' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_zapper', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_zapper' + ) + ), + 'PAYGATE_PAYMENT_METHODS_snapscan' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_snapscan', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_snapscan' + ) + ), + 'PAYGATE_PAYMENT_METHODS_mobicred' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_mobicred', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_mobicred' + ) + ), + 'PAYGATE_PAYMENT_METHODS_momopay' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_momopay', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_momopay' + ) + ), + 'PAYGATE_PAYMENT_METHODS_masterpass' => Tools::getValue( + 'PAYGATE_PAYMENT_METHODS_masterpass', + Configuration::get( + 'PAYGATE_PAYMENT_METHODS_masterpass' + ) + ), ); } @@ -395,714 +571,6 @@ public function logData( $post_data ) } } - public function paygateValidate( - $id_cart, - $id_order_state, - $amount_paid, - $payment_method = 'Unknown', - $message = null, - $extra_vars = array(), - $currency_special = null, - $dont_touch_amount = false, - $secure_key = false, - Shop $shop = null - ) { - if ( !isset( $this->context ) ) { - $this->context = Context::getContext(); - } - $cart = new Cart( (int) $id_cart ); - $customer = new Customer( (int) $cart->id_customer ); - // Re-cache the tax calculation method as the tax cart is loaded before the customer - $cart->setTaxCalculationMethod(); - - $language = new Language( (int) $cart->id_lang ); - $shop = ( $shop ? $shop : new Shop( (int) $cart->id_shop ) ); - ShopUrl::resetMainDomainCache(); - $id_currency = $currency_special ? (int) $currency_special : (int) $cart->id_currency; - $currency = new Currency( (int) $id_currency, null, (int) $shop->id ); - if ( Configuration::get( 'PS_TAX_ADDRESS_TYPE' ) == 'id_address_delivery' ) { - $context_country = $this->context->country; ///csk - } - - $order_status = new OrderState( (int) $id_order_state, (int) $language->id ); - - // Check if the order already exists - if ( $cart->OrderExists() == false ) { - $sql1 = 'SELECT delivery_option_list FROM `' . _DB_PREFIX_ . 'paygate` WHERE cart_id = ' . (int) $cart->id . ';'; - $test = Db::getInstance()->getValue( $sql1 ); - $json_delivery_option_list = json_decode( $test ); - $sql3 = 'SELECT package_list FROM `' . _DB_PREFIX_ . 'paygate` WHERE cart_id = ' . (int) $cart->id . ';'; - $test2 = Db::getInstance()->getValue( $sql3 ); - $json_package_list = json_decode( $test2 ); - $sql2 = 'SELECT cart_delivery_option FROM `' . _DB_PREFIX_ . 'paygate` WHERE cart_id = ' . (int) $cart->id . ';'; - $test1 = Db::getInstance()->getValue( $sql2 ); - $json_cart_delivery_option = json_decode( $test1 ); - - // Typcast object to array recursively to allow for integer keys - $toArray = function ( $x ) use ( &$toArray ) { - return is_scalar( $x ) - ? $x - : array_map( $toArray, (array) $x ); - }; - $delivery_option_list = $toArray( $json_delivery_option_list ); - $package_list = $toArray( $json_package_list ); - $cart_delivery_option = $toArray( $json_cart_delivery_option ); - - // If some delivery options are not defined, or not valid, use the first valid option - foreach ( $delivery_option_list as $id_address => $package ) { - if ( !isset( $cart_delivery_option[$id_address] ) || !array_key_exists( - $cart_delivery_option[$id_address], - $package - ) ) { - foreach ( $package as $key => $val ) { - $cart_delivery_option[$id_address] = $key; - - break; - } - } - } - - $order_list = array(); - $order_detail_list = array(); - do { - $reference = Order::generateReference(); - } while ( Order::getByReference( $reference )->count() ); - - $currentOrderReference = $reference; - $sql = 'SELECT cart_total FROM `' . _DB_PREFIX_ . 'paygate` WHERE cart_id = ' . (int) $id_cart . ';'; - $test = Db::getInstance()->getValue( $sql ); - $cart_total_paid = (float) Tools::ps_round( (float) $test, 2 ); - foreach ( $cart_delivery_option as $id_address => $key_carriers ) { - foreach ( $delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data ) { - foreach ( $data['package_list'] as $id_package ) { - // Rewrite the id_warehouse - $package_list[$id_address][$id_package]['id_warehouse'] = (int) $this->context->cart->getPackageIdWarehouse( - $package_list[$id_address][$id_package], - (int) $id_carrier - ); - $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier; - } - } - } - // Make sure CartRule caches are empty - CartRule::cleanCache(); - $cart_rules = $this->context->cart->getCartRules(); - foreach ( $cart_rules as $cart_rule ) { - if ( ( $rule = new CartRule( (int) $cart_rule['obj']->id ) ) && Validate::isLoadedObject( $rule ) ) { - if ( $error = $rule->checkValidity( $this->context, true, true ) ) { - $this->context->cart->removeCartRule( (int) $rule->id ); - if ( isset( $this->context->cookie, $this->context->cookie->id_customer ) && $this->context->cookie->id_customer && !empty( $rule->code ) ) { - Tools::redirect( - 'index.php?controller=order&submitAddDiscount=1&discount_name=' . urlencode( $rule->code ) - ); - } else { - $rule_name = isset( $rule->name[(int) $this->context->cart->id_lang] ) ? $rule->name[(int) $this->context->cart->id_lang] : $rule->code; - $error = $this->trans( - 'The cart rule named "%1s" (ID %2s) used in this cart is not valid and has been withdrawn from cart', - array( $rule_name, (int) $rule->id ), - 'Admin.Payment.Notification' - ); - PrestaShopLogger::addLog( $error, 3, '0000002', 'Cart', (int) $this->context->cart->id ); - } - } - } - } - - foreach ( $package_list as $id_address => $packageByAddress ) { - foreach ( $packageByAddress as $id_package => $package ) { - $orderData = $this->createOrderViaPaygate( - $cart, - $currency, - $package['product_list'], - $id_address, - $this->context, - $reference, - $secure_key, - $payment_method, - $this->name, - $dont_touch_amount, - $amount_paid, - $package_list[$id_address][$id_package]['id_warehouse'], - $cart_total_paid, - self::DEBUG_MODE, - $order_status, - $id_order_state, - isset( $package['id_carrier'] ) ? $package['id_carrier'] : null - ); - $order = $orderData['order']; - $order_list[] = $order; - $order_detail_list[] = $orderData['orderDetail']; - } - } - - // The country can only change if the address used for the calculation is the delivery address, - // and if multi-shipping is activated - if ( Configuration::get( 'PS_TAX_ADDRESS_TYPE' ) == 'id_address_delivery' ) { - $this->context->country = $context_country; - } - - // Register Payment only if the order status validates the order - if ( $order_status->logable ) { - // The last order loop in the foreach and linked to the order reference, not id - if ( isset( $extra_vars['transaction_id'] ) ) { - $transaction_id = $extra_vars['transaction_id']; - } else { - $transaction_id = null; - } - - if ( !$order->addOrderPayment( $amount_paid, null, $transaction_id ) ) { - } - } - - $only_one_gift = false; - $products = $this->context->cart->getProducts(); - - // Make sure CartRule caches are empty - CartRule::cleanCache(); - foreach ( $order_detail_list as $key => $order_detail ) { - /** @var OrderDetail $order_detail */ - $order = $order_list[$key]; - if ( isset( $order->id ) ) { - if ( !$secure_key ) { - $message .= '
' . $this->trans( - 'Warning: the secure key is empty, check your payment account before validation', - array(), - 'Admin.Payment.Notification' - ); - } - if ( isset( $message ) & !empty( $message ) ) { - $msg = new Message(); - $message = strip_tags( $message, '
' ); - if ( Validate::isCleanHtml( $message ) ) { - if ( self::DEBUG_MODE ) { - PrestaShopLogger::addLog( - 'PaymentModule::validateOrder - Message is about to be added', - 1, - null, - 'Cart', - (int) $id_cart, - true - ); - } - $msg->message = $message; - $msg->id_cart = (int) $id_cart; - $msg->id_customer = (int) ( $order->id_customer ); - $msg->id_order = (int) $order->id; - $msg->private = 1; - $msg->add(); - } - } - - $products_list = ''; - $virtual_product = true; - - $product_var_tpl_list = array(); - foreach ( $order->product_list as $product ) { - $price = Product::getPriceStatic( - (int) $product['id_product'], - false, - ( $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null ), - 6, - null, - false, - true, - $product['cart_quantity'], - false, - (int) $order->id_customer, - (int) $order->id_cart, - (int) $order->{Configuration::get( 'PS_TAX_ADDRESS_TYPE' )}, - $specific_price, - true, - true, - null, - true, - $product['id_customization'] - ); - $price_wt = Product::getPriceStatic( - (int) $product['id_product'], - true, - ( $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null ), - 2, - null, - false, - true, - $product['cart_quantity'], - false, - (int) $order->id_customer, - (int) $order->id_cart, - (int) $order->{Configuration::get( 'PS_TAX_ADDRESS_TYPE' )}, - $specific_price, - true, - true, - null, - true, - $product['id_customization'] - ); - - $product_price = Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round( - $price, - 2 - ) : $price_wt; - - $product_var_tpl = array( - 'id_product' => $product['id_product'], - 'reference' => $product['reference'], - 'name' => $product['name'] . ( isset( $product['attributes'] ) ? ' - ' . $product['attributes'] : '' ), - 'price' => Tools::displayPrice( - $product_price * $product['quantity'], - $this->context->currency, - false - ), - 'quantity' => $product['quantity'], - 'customization' => array(), - ); - - if ( isset( $product['price'] ) && $product['price'] ) { - $product_var_tpl['unit_price'] = Tools::displayPrice( - $product_price, - $this->context->currency, - false - ); - $product_var_tpl['unit_price_full'] = Tools::displayPrice( - $product_price, - $this->context->currency, - false - ) - . ' ' . $product['unity']; - } else { - $product_var_tpl['unit_price'] = $product_var_tpl['unit_price_full'] = ''; - } - - $customized_datas = Product::getAllCustomizedDatas( - (int) $order->id_cart, - null, - true, - null, - (int) $product['id_customization'] - ); - if ( isset( $customized_datas[$product['id_product']][$product['id_product_attribute']] ) ) { - $product_var_tpl['customization'] = array(); - foreach ( $customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization ) { - $customization_text = ''; - if ( isset( $customization['datas'][Product::CUSTOMIZE_TEXTFIELD] ) ) { - foreach ( $customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text ) { - $customization_text .= '' . $text['name'] . ': ' . $text['value'] . '
'; - } - } - - if ( isset( $customization['datas'][Product::CUSTOMIZE_FILE] ) ) { - $customization_text .= $this->trans( - '%d image(s)', - array( - count( - $customization['datas'][Product::CUSTOMIZE_FILE] - ), - ), - 'Admin.Payment.Notification' - ) . '
'; - } - - $customization_quantity = (int) $customization['quantity']; - - $product_var_tpl['customization'][] = array( - 'customization_text' => $customization_text, - 'customization_quantity' => $customization_quantity, - 'quantity' => Tools::displayPrice( - $customization_quantity * $product_price, - $this->context->currency, - false - ), - ); - } - } - - $product_var_tpl_list[] = $product_var_tpl; - // Check if is not a virutal product to display shipping - if ( !$product['is_virtual'] ) { - $virtual_product &= false; - } - } - - $product_list_txt = ''; - $product_list_html = ''; - if ( empty( $product_var_tpl_list ) ) { - $product_list_txt = $this->getEmailTemplateContent( - 'order_conf_product_list.txt', - Mail::TYPE_TEXT, - $product_var_tpl_list - ); - $product_list_html = $this->getEmailTemplateContent( - 'order_conf_product_list.tpl', - Mail::TYPE_HTML, - $product_var_tpl_list - ); - } - - $total_reduction_value_ti = 0; - $total_reduction_value_tex = 0; - - $cart_rules_list = $this->createOrderCartRulesViaPaygate( - $order, - $this->context->cart, - $order_list, - $total_reduction_value_ti, - $total_reduction_value_tex, - $id_order_state - ); - - $cart_rules_list_txt = ''; - $cart_rules_list_html = ''; - if ( count( $cart_rules_list ) > 0 ) { - $cart_rules_list_txt = $this->getEmailTemplateContent( - 'order_conf_cart_rules.txt', - Mail::TYPE_TEXT, - $cart_rules_list - ); - $cart_rules_list_html = $this->getEmailTemplateContent( - 'order_conf_cart_rules.tpl', - Mail::TYPE_HTML, - $cart_rules_list - ); - } - - // Specify order id for message - $old_message = Message::getMessageByCartId( (int) $this->context->cart->id ); - if ( $old_message && !$old_message['private'] ) { - $update_message = new Message( (int) $old_message['id_message'] ); - $update_message->id_order = (int) $order->id; - $update_message->update(); - - // Add this message in the customer thread - $customer_thread = new CustomerThread(); - $customer_thread->id_contact = 0; - $customer_thread->id_customer = (int) $order->id_customer; - $customer_thread->id_shop = (int) $this->context->shop->id; - $customer_thread->id_order = (int) $order->id; - $customer_thread->id_lang = (int) $this->context->language->id; - $customer_thread->email = $this->context->customer->email; - $customer_thread->status = 'open'; - $customer_thread->token = Tools::passwdGen( 12 ); - $customer_thread->add(); - - $customer_message = new CustomerMessage(); - $customer_message->id_customer_thread = $customer_thread->id; - $customer_message->id_employee = 0; - $customer_message->message = $update_message->message; - $customer_message->private = 1; - - if ( !$customer_message->add() ) { - $this->errors[] = $this->trans( - 'An error occurred while saving message', - array(), - 'Admin.Payment.Notification' - ); - } - } - - if ( self::DEBUG_MODE ) { - PrestaShopLogger::addLog( - 'PaymentModule::validateOrder - Hook validateOrder is about to be called', - 1, - null, - 'Cart', - (int) $id_cart, - true - ); - } - - // Hook validate order - Hook::exec( - 'actionValidateOrder', - array( - 'cart' => $this->context->cart, - 'order' => $order, - 'customer' => $this->context->customer, - 'currency' => $this->context->currency, - 'orderStatus' => $order_status, - ) - ); - - foreach ( $this->context->cart->getProducts() as $product ) { - if ( $order_status->logable ) { - ProductSale::addProductSale( (int) $product['id_product'], (int) $product['cart_quantity'] ); - } - } - - if ( self::DEBUG_MODE ) { - PrestaShopLogger::addLog( - 'PaymentModule::validateOrder - Order Status is about to be added', - 1, - null, - 'Cart', - (int) $id_cart, - true - ); - } - - // Set the order status - $new_history = new OrderHistory(); - $new_history->id_order = (int) $order->id; - $new_history->changeIdOrderState( (int) $id_order_state, $order, true ); - $new_history->addWithemail( true, $extra_vars ); - - // Switch to back order if needed - if ( Configuration::get( 'PS_STOCK_MANAGEMENT' ) && - ( $order_detail->getStockState() || - $order_detail->product_quantity_in_stock < 0 ) ) { - $history = new OrderHistory(); - $history->id_order = (int) $order->id; - $history->changeIdOrderState( - Configuration::get( - $order->hasBeenPaid() ? 'PS_OS_OUTOFSTOCK_PAID' : 'PS_OS_OUTOFSTOCK_UNPAID' - ), - $order, - true - ); - $history->addWithemail(); - } - - unset( $order_detail ); - - // Order is reloaded because the status just changed - $order = new Order( (int) $order->id ); - - // Send an e-mail to customer (one order = one email) - if ( $id_order_state != Configuration::get( 'PS_OS_ERROR' ) && $id_order_state != Configuration::get( - 'PS_OS_CANCELED' - ) && $this->context->customer->id ) { - $invoice = new Address( (int) $order->id_address_invoice ); - $delivery = new Address( (int) $order->id_address_delivery ); - $delivery_state = $delivery->id_state ? new State( (int) $delivery->id_state ) : false; - $invoice_state = $invoice->id_state ? new State( (int) $invoice->id_state ) : false; - $carrier = $order->id_carrier ? new Carrier( $order->id_carrier ) : false; - - $data = array( - '{firstname}' => $this->context->customer->firstname, - '{lastname}' => $this->context->customer->lastname, - '{email}' => $this->context->customer->email, - '{delivery_block_txt}' => $this->_getFormatedAddress( - $delivery, - AddressFormat::FORMAT_NEW_LINE - ), - '{invoice_block_txt}' => $this->_getFormatedAddress( - $invoice, - AddressFormat::FORMAT_NEW_LINE - ), - '{delivery_block_html}' => $this->_getFormatedAddress( - $delivery, - '
', - array( - 'firstname' => '%s', - 'lastname' => '%s', - ) - ), - '{invoice_block_html}' => $this->_getFormatedAddress( - $invoice, - '
', - array( - 'firstname' => '%s', - 'lastname' => '%s', - ) - ), - '{delivery_company}' => $delivery->company, - '{delivery_firstname}' => $delivery->firstname, - '{delivery_lastname}' => $delivery->lastname, - '{delivery_address1}' => $delivery->address1, - '{delivery_address2}' => $delivery->address2, - '{delivery_city}' => $delivery->city, - '{delivery_postal_code}' => $delivery->postcode, - '{delivery_country}' => $delivery->country, - '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', - '{delivery_phone}' => ( $delivery->phone ) ? $delivery->phone : $delivery->phone_mobile, - '{delivery_other}' => $delivery->other, - '{invoice_company}' => $invoice->company, - '{invoice_vat_number}' => $invoice->vat_number, - '{invoice_firstname}' => $invoice->firstname, - '{invoice_lastname}' => $invoice->lastname, - '{invoice_address2}' => $invoice->address2, - '{invoice_address1}' => $invoice->address1, - '{invoice_city}' => $invoice->city, - '{invoice_postal_code}' => $invoice->postcode, - '{invoice_country}' => $invoice->country, - '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', - '{invoice_phone}' => ( $invoice->phone ) ? $invoice->phone : $invoice->phone_mobile, - '{invoice_other}' => $invoice->other, - '{order_name}' => $order->getUniqReference(), - '{date}' => Tools::displayDate( date( 'Y-m-d H:i:s' ), null, 1 ), - '{carrier}' => ( $virtual_product || !isset( $carrier->name ) ) ? $this->trans( - 'No carrier', - array(), - 'Admin.Payment.Notification' - ) : $carrier->name, - '{payment}' => Tools::substr( $order->payment, 0, 255 ), - '{products}' => $product_list_html, - '{products_txt}' => $product_list_txt, - '{discounts}' => $cart_rules_list_html, - '{discounts_txt}' => $cart_rules_list_txt, - '{total_paid}' => Tools::displayPrice( - $order->total_paid, - $this->context->currency, - false - ), - '{total_products}' => Tools::displayPrice( - Product::getTaxCalculationMethod( - ) == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, - $this->context->currency, - false - ), - '{total_discounts}' => Tools::displayPrice( - $order->total_discounts, - $this->context->currency, - false - ), - '{total_shipping}' => Tools::displayPrice( - $order->total_shipping, - $this->context->currency, - false - ), - '{total_shipping_tax_excl}' => Tools::displayPrice( - $order->total_shipping_tax_excl, - $this->context->currency, - false - ), - '{total_shipping_tax_incl}' => Tools::displayPrice( - $order->total_shipping_tax_incl, - $this->context->currency, - false - ), - '{total_wrapping}' => Tools::displayPrice( - $order->total_wrapping, - $this->context->currency, - false - ), - '{total_tax_paid}' => Tools::displayPrice( - ( $order->total_products_wt - $order->total_products ) + ( $order->total_shipping_tax_incl - $order->total_shipping_tax_excl ), - $this->context->currency, - false - ), - ); - - if ( is_array( $extra_vars ) ) { - $data = array_merge( $data, $extra_vars ); - } - - // Join PDF invoice - if ( (int) Configuration::get( 'PS_INVOICE' ) && $order_status->invoice && $order->invoice_number ) { - $order_invoice_list = $order->getInvoicesCollection(); - Hook::exec( 'actionPDFInvoiceRender', array( 'order_invoice_list' => $order_invoice_list ) ); - $pdf = new PDF( - $order_invoice_list, - PDF::TEMPLATE_INVOICE, - $this->context->smarty - ); - $file_attachement['content'] = $pdf->render( false ); - $file_attachement['name'] = Configuration::get( - 'PS_INVOICE_PREFIX', - (int) $order->id_lang, - null, - $order->id_shop - ) . sprintf( '%06d', $order->invoice_number ) . '.pdf'; - $file_attachement['mime'] = 'application/pdf'; - } else { - $file_attachement = null; - } - - if ( self::DEBUG_MODE ) { - PrestaShopLogger::addLog( - 'PaymentModule::validateOrder - Mail is about to be sent', - 1, - null, - 'Cart', - (int) $id_cart, - true - ); - } - - $orderLanguage = new Language( (int) $order->id_lang ); - - if ( Validate::isEmail( $this->context->customer->email ) ) { - Mail::Send( - (int) $order->id_lang, - 'order_conf', - Context::getContext()->getTranslator()->trans( - 'Order confirmation', - array(), - 'Emails.Subject', - $orderLanguage->locale - ), - $data, - $this->context->customer->email, - $this->context->customer->firstname . ' ' . $this->context->customer->lastname, - null, - null, - $file_attachement, - null, - _PS_MAIL_DIR_, - false, - (int) $order->id_shop - ); - } - } - - // Updates stock in shops - if ( Configuration::get( 'PS_ADVANCED_STOCK_MANAGEMENT' ) ) { - $product_list = $order->getProducts(); - foreach ( $product_list as $product ) { - // If the available quantities depend on the physical stock - if ( StockAvailable::dependsOnStock( $product['product_id'] ) ) { - StockAvailable::synchronize( $product['product_id'], $order->id_shop ); - } - } - } - - $order->updateOrderDetailTax(); - - // Sync all stock - ( new StockManager() )->updatePhysicalProductQuantity( - (int) $order->id_shop, - (int) Configuration::get( 'PS_OS_ERROR' ), - (int) Configuration::get( 'PS_OS_CANCELED' ), - null, - (int) $order->id - ); - } else { - $error = $this->trans( 'Order creation failed', array(), 'Admin.Payment.Notification' ); - PrestaShopLogger::addLog( $error, 4, '0000002', 'Cart', (int) ( $order->id_cart ) ); - die( Tools::displayError( $error ) ); - } - } - - // Use the last order as currentOrder - if ( isset( $order ) && $order->id ) { - $this->currentOrder = (int) $order->id; - } - - if ( self::DEBUG_MODE ) { - PrestaShopLogger::addLog( - 'PaymentModule::validateOrder - End of validateOrder', - 1, - null, - 'Cart', - (int) $id_cart, - true - ); - } - - return true; - } else { - $error = $this->trans( - 'Cart cannot be loaded or an order has already been placed using this cart', - array(), - 'Admin.Payment.Notification' - ); - PrestaShopLogger::addLog( $error, 4, '0000001', 'Cart', (int) ( $this->context->cart->id ) ); - $this->logData( - "Cart cannot be loaded or an order has already been placed using this cart with id =>" . $id_cart . "\n" - ); - die( Tools::displayError( $error ) ); - } - } - public function createOrderViaPaygate( Cart $cart, Currency $currency, @@ -1239,8 +707,6 @@ public function createOrderCartRulesViaPaygate( $total_reduction_value_tex, $id_order_state ) { - $cart_rule_used = array(); - // Prepare cart calculator to correctly get the value of each cart rule $calculator = $cart->newCalculator( $order->product_list, $cart->getCartRules(), $order->id_carrier ); $calculator->processCalculation( _PS_PRICE_COMPUTE_PRECISION_ ); @@ -1280,117 +746,14 @@ public function createOrderCartRulesViaPaygate( if ( count( $order_list ) == 1 && $remainingValue > 0 && $cartRule->partial_use == 1 && $cartRuleReductionAmountConverted > 0 ) { - // Create a new voucher from the original - $voucher = new CartRule( - (int) $cartRule->id - ); // We need to instantiate the CartRule without lang parameter to allow saving it - unset( $voucher->id ); - - // Set a new voucher code - $voucher->code = empty( $voucher->code ) ? substr( - md5( $order->id . '-' . $order->id_customer . '-' . $cartRule->id ), - 0, - 16 - ) : $voucher->code . '-2'; - if ( preg_match( - '/\-([0-9]{1,2})\-([0-9]{1,2})$/', - $voucher->code, - $matches - ) && $matches[1] == $matches[2] ) { - $voucher->code = preg_replace( - '/' . $matches[0] . '$/', - '-' . ( intval( $matches[1] ) + 1 ), - $voucher->code - ); - } - - // Set the new voucher value - $voucher->reduction_amount = $remainingValue; - if ( $voucher->reduction_tax ) { - // Add total shipping amout only if reduction amount > total shipping - if ( $voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl ) { - $voucher->reduction_amount -= $order->total_shipping_tax_incl; - } - } else { - // Add total shipping amout only if reduction amount > total shipping - if ( $voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl ) { - $voucher->reduction_amount -= $order->total_shipping_tax_excl; - } - } - if ( $voucher->reduction_amount <= 0 ) { - continue; - } - - if ( $this->context->customer->isGuest() ) { - $voucher->id_customer = 0; - } else { - $voucher->id_customer = $order->id_customer; - } - - $voucher->quantity = 1; - $voucher->reduction_currency = $order->id_currency; - $voucher->quantity_per_user = 1; - if ( $voucher->add() ) { - // If the voucher has conditions, they are now copied to the new voucher - CartRule::copyConditions( $cartRule->id, $voucher->id ); - $orderLanguage = new Language( (int) $order->id_lang ); - - $params = array( - '{voucher_amount}' => Tools::displayPrice( - $voucher->reduction_amount, - $this->context->currency, - false - ), - '{voucher_num}' => $voucher->code, - '{firstname}' => $this->context->customer->firstname, - '{lastname}' => $this->context->customer->lastname, - '{id_order}' => $order->reference, - '{order_name}' => $order->getUniqReference(), - ); - Mail::Send( - (int) $order->id_lang, - 'voucher', - Context::getContext()->getTranslator()->trans( - 'New voucher for your order %s', - array( $order->reference ), - 'Emails.Subject', - $orderLanguage->locale - ), - $params, - $this->context->customer->email, - $this->context->customer->firstname . ' ' . $this->context->customer->lastname, - null, - null, - null, - null, - _PS_MAIL_DIR_, - false, - (int) $order->id_shop - ); - } - - $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti; - $values['tax_excl'] = $order->total_products - $total_reduction_value_tex; - if ( 1 == $voucher->free_shipping ) { - $values['tax_incl'] += $order->total_shipping_tax_incl; - $values['tax_excl'] += $order->total_shipping_tax_excl; - } + $values = $this->createNewVoucher($cartRule,$order,$values,$total_reduction_value_ti,$total_reduction_value_tex); } $total_reduction_value_ti += $values['tax_incl']; $total_reduction_value_tex += $values['tax_excl']; $order->addCartRule( $cartRule->id, $cartRule->name, $values, 0, $cartRule->free_shipping ); - if ( $id_order_state != Configuration::get( 'PS_OS_ERROR' ) && $id_order_state != Configuration::get( - 'PS_OS_CANCELED' - ) && !in_array( $cartRule->id, $cart_rule_used ) ) { - $cart_rule_used[] = $cartRule->id; - - // Create a new instance of Cart Rule without id_lang, in order to update its quantity - $cart_rule_to_update = new CartRule( (int) $cartRule->id ); - $cart_rule_to_update->quantity = max( 0, $cart_rule_to_update->quantity - 1 ); - $cart_rule_to_update->update(); - } + $this->updateCartRuleData($cartRule, $id_order_state); $cart_rules_list[] = array( 'voucher_name' => $cartRule->name, @@ -1404,5 +767,123 @@ public function createOrderCartRulesViaPaygate( return $cart_rules_list; } + + public function updateCartRuleData($cartRule, $id_order_state){ + $cart_rule_used = array(); + if ( $id_order_state != Configuration::get( 'PS_OS_ERROR' ) && $id_order_state != Configuration::get( + 'PS_OS_CANCELED' + ) && !in_array( $cartRule->id, $cart_rule_used ) ) { + $cart_rule_used[] = $cartRule->id; + + // Create a new instance of Cart Rule without id_lang, in order to update its quantity + $cart_rule_to_update = new CartRule( (int) $cartRule->id ); + $cart_rule_to_update->quantity = max( 0, $cart_rule_to_update->quantity - 1 ); + $cart_rule_to_update->update(); + } + } + + public function createNewVoucher($cartRule,$order,$values,$total_reduction_value_ti,$total_reduction_value_tex){ + + + // Create a new voucher from the original + $voucher = new CartRule( + (int) $cartRule->id + ); // We need to instantiate the CartRule without lang parameter to allow saving it + unset( $voucher->id ); + + // Set a new voucher code + $voucher->code = empty( $voucher->code ) ? substr( + md5( $order->id . '-' . $order->id_customer . '-' . $cartRule->id ), + 0, + 16 + ) : $voucher->code . '-2'; + if ( preg_match( + '/\-([0-9]{1,2})\-([0-9]{1,2})$/', + $voucher->code, + $matches + ) && $matches[1] == $matches[2] ) { + $voucher->code = preg_replace( + '/' . $matches[0] . '$/', + '-' . ( intval( $matches[1] ) + 1 ), + $voucher->code + ); + } + + // Set the new voucher value + $voucher = $this->setNewVoucherValue($voucher,$remainingValue,$order); + + $voucher->quantity = 1; + $voucher->reduction_currency = $order->id_currency; + $voucher->quantity_per_user = 1; + if ( $voucher->add() && $voucher->reduction_amount > 0 ) { + // If the voucher has conditions, they are now copied to the new voucher + CartRule::copyConditions( $cartRule->id, $voucher->id ); + $orderLanguage = new Language( (int) $order->id_lang ); + + $params = array( + '{voucher_amount}' => Tools::displayPrice( + $voucher->reduction_amount, + $this->context->currency, + false + ), + '{voucher_num}' => $voucher->code, + '{firstname}' => $this->context->customer->firstname, + '{lastname}' => $this->context->customer->lastname, + '{id_order}' => $order->reference, + '{order_name}' => $order->getUniqReference(), + ); + Mail::Send( + (int) $order->id_lang, + 'voucher', + Context::getContext()->getTranslator()->trans( + 'New voucher for your order %s', + array( $order->reference ), + 'Emails.Subject', + $orderLanguage->locale + ), + $params, + $this->context->customer->email, + $this->context->customer->firstname . ' ' . $this->context->customer->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + false, + (int) $order->id_shop + ); + } + + $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti; + $values['tax_excl'] = $order->total_products - $total_reduction_value_tex; + if ( 1 == $voucher->free_shipping ) { + $values['tax_incl'] += $order->total_shipping_tax_incl; + $values['tax_excl'] += $order->total_shipping_tax_excl; + } + + return $values; + } + + public function setNewVoucherValue($voucher,$remainingValue,$order){ + $voucher->reduction_amount = $remainingValue; + if ( $voucher->reduction_tax ) { + // Add total shipping amout only if reduction amount > total shipping + if ( $voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl ) { + $voucher->reduction_amount -= $order->total_shipping_tax_incl; + } + } else { + // Add total shipping amout only if reduction amount > total shipping + if ( $voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl ) { + $voucher->reduction_amount -= $order->total_shipping_tax_excl; + } + } + + if ( $this->context->customer->isGuest() ) { + $voucher->id_customer = 0; + } else { + $voucher->id_customer = $order->id_customer; + } + return $voucher; + } } diff --git a/paygate/views/templates/front/confirmation.tpl b/paygate/views/templates/front/confirmation.tpl index 859aef9..74583d6 100644 --- a/paygate/views/templates/front/confirmation.tpl +++ b/paygate/views/templates/front/confirmation.tpl @@ -1,11 +1,11 @@ {* - * Copyright (c) 2020 PayGate (Pty) Ltd + * Copyright (c) 2021 PayGate (Pty) Ltd * * Author: App Inlet (Pty) Ltd - * + * * Released under the GNU General Public License *} -{extends file='page.tpl'} +{extends file='page.tpl'} {block name='content'}
@@ -20,4 +20,4 @@

-{/block} \ No newline at end of file +{/block} diff --git a/paygate/views/templates/front/payment-redirect.tpl b/paygate/views/templates/front/payment-redirect.tpl index 0de63c2..d31de38 100644 --- a/paygate/views/templates/front/payment-redirect.tpl +++ b/paygate/views/templates/front/payment-redirect.tpl @@ -1,8 +1,8 @@ {* - * Copyright (c) 2020 PayGate (Pty) Ltd + * Copyright (c) 2021 PayGate (Pty) Ltd * * Author: App Inlet (Pty) Ltd - * + * * Released under the GNU General Public License *}