diff --git a/doc/readme_en_oscommerce.pdf b/doc/readme_en_oscommerce.pdf
new file mode 100644
index 0000000..195dddc
Binary files /dev/null and b/doc/readme_en_oscommerce.pdf differ
diff --git a/doc/readme_ru_oscommerce.pdf b/doc/readme_ru_oscommerce.pdf
new file mode 100644
index 0000000..4f475e6
Binary files /dev/null and b/doc/readme_ru_oscommerce.pdf differ
diff --git a/doc/remove.mp4 b/doc/remove.mp4
new file mode 100644
index 0000000..e11bce2
Binary files /dev/null and b/doc/remove.mp4 differ
diff --git a/doc/upload_and_deploy.mp4 b/doc/upload_and_deploy.mp4
new file mode 100644
index 0000000..4458e5b
Binary files /dev/null and b/doc/upload_and_deploy.mp4 differ
diff --git a/source/License.md b/source/License.md
new file mode 100644
index 0000000..4979403
--- /dev/null
+++ b/source/License.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 PaynetEasy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/source/README.md b/source/README.md
new file mode 100644
index 0000000..3433208
--- /dev/null
+++ b/source/README.md
@@ -0,0 +1,70 @@
+# PaynetEasy Payment Module for OsCommerce v4
+
+This is a Payment Module for OsCommerce v4, that gives you the ability to process payments through payment service providers running on PaynetEasy.
+
+## Requirements
+
+ * OsCommerce v4
+ * PHP Versions >= 7.0.0 ![GitHub](https://img.shields.io/badge/php-%3E%3D7.0.0-lightgrey)
+
+*Note:* this module has been tested only with OsCommerce v4+.
+
+## Installation (App Shop / Local Storage)
+
+ * Upload ```plugin-oscommerce.zip``` to a ```App Shop / Local Storage```
+
+ * Click + sign in Action column to Install module from there.
+
+## Installation (Manual)
+
+ * Unpack zip.
+
+ * Navigate project folder ```lib\common\modules\orderPayment``` and upload unpack contents from ```plugin-oscommerce``` there.
+
+ * Move file ```ot_payneteasy.php``` from ```lib\common\modules\orderPayment``` to ```lib\common\modules\orderTotal``` if installer doesn't move.
+
+ * Move file ```StoredCards.php``` from ```lib\common\modules\orderPayment``` to ```lib\frontend\design\boxes\account``` if installer doesn't move.
+
+ * Move file ```stored-cards.tpl``` from ```lib\common\modules\orderPayment``` to ```lib\frontend\themes\basic\boxes\account``` if installer doesn't move.
+
+## Deletion
+
+ * Go to ```App Shop / Local Storage``` delete module from there
+
+ * For Manual Navigate folder ```lib\common\modules\orderPayment``` delete payneteasy folder and file from there
+
+ * Go to ```lib\common\modules\orderTotal``` delete ot_payneteasy.php from there.
+
+ * Go to ```lib\frontend\design\boxes\account``` delete StoredCards.php from there.
+
+ * Go to ```lib\frontend\themes\basic\boxes\account``` delete stored-cards.tpl from there.
+
+ * Remove Stored Cards Block references from these tables TABLE_DESIGN_BOXES, TABLE_DESIGN_BOXES_SETTINGS, design_boxes_cache
+ TABLE_TRANSLATION
+
+## Configuration
+
+ * Login inside the __Admin Panel__ and go to ```Modules``` -> ```Payment``` -> ```Online```
+ * Check the Payment Module Panel ```PaynetEasy``` is visible in the list of installed Payment Method,
+ apply filter Show not installed, if for In-Active module use Show inactive filter.
+ * Click to ```PaynetEasy Payment Method``` and click the button ```Edit``` under the right side panel to expand the available settings
+ * Set ```Enable PaynetPos``` to ```Yes```, set the correct credentials, select your prefered payment method and additional settings and click ```Update```
+
+ #### Enable SurchargeFee
+ * Next go to ```Modules``` -> ```Order structure```
+ * Check the Module ```SurchargeFee``` is visible in the list of not installed, install it.
+ * Click to ```SurchargeFee``` and click the button ```Edit``` under the right side panel to expand the available settings
+ * Set ```Display Surcharge Fee``` to ```Yes```, Sort Order and click ```Update```
+ * Drag ```SurchargeFee``` above the Total Module so that surcharge fee if enable must be calculated under grand total.
+
+## Test data
+
+If you setup the module with default values, you can ask your payneteasy manager
+
+### Test card details
+
+Use the following test cards to make successful test payment:
+
+ Test Card:
+
+ * Visa - 4444555566661111- CVV 123 - non 3d secude approved 321 - 3d secure approved 777 - declined Expiry Date - 12/25
diff --git a/source/distribution.json b/source/distribution.json
new file mode 100644
index 0000000..34e62ea
--- /dev/null
+++ b/source/distribution.json
@@ -0,0 +1,35 @@
+{
+ "name": "PaynetEasy",
+ "description": "This is a Payment Module for Oscommerce, that gives you the ability to process payments through payment service providers running on PaynetEasy.",
+ "type": "payment",
+ "version": "2.0.0",
+ "authors": [
+ {
+ "name": "Payneasy.com",
+ "email": "info@payneteasy.com",
+ "homepage": "https://payneteasy.com/",
+ "role": "Owner"
+ }
+ ],
+ "src": [
+ {
+ "action": "add",
+ "type": "file",
+ "path": "payneteasy.php"
+ },
+ {
+ "action": "add",
+ "type": "file",
+ "path": "ot_payneteasy.php"
+ },
+ {
+ "action": "copy",
+ "type": "dir",
+ "path": "payneteasy"
+ }
+ ],
+ "require": {
+ "platform": "True"
+ },
+ "class": "payneteasy"
+}
\ No newline at end of file
diff --git a/source/ot_payneteasy.php b/source/ot_payneteasy.php
new file mode 100644
index 0000000..4901961
--- /dev/null
+++ b/source/ot_payneteasy.php
@@ -0,0 +1,83 @@
+code = 'ot_payneteasy';
+ $this->title = '';
+ if (!defined('MODULE_ORDER_TOTAL_PAYNETEASY_STATUS')) {
+ $this->enabled = false;
+ return false;
+ }
+ $this->enabled = ((MODULE_ORDER_TOTAL_PAYNETEASY_STATUS == 'true') ? true : false);
+ $this->sort_order = MODULE_ORDER_TOTAL_PAYNETEASY_SORT_ORDER;
+
+ $this->output = array();
+ }
+
+ function process($replacing_value = -1) {
+ $module = $this->manager->getPayment();
+
+ $this->output = [];
+
+ if( MODULE_PAYMENT_PAYNETEASY_STATUS == 'True' && $module == "payneteasy" ) {
+
+ $order = $this->manager->getOrderInstance();
+ \common\helpers\Php8::nullArrProps($order->info, ['total_paid_exc_tax', 'total_paid_inc_tax', 'currency', 'currency_value']);
+ $currencies = \Yii::$container->get('currencies');
+ $this->output = [];
+ }
+ }
+
+ public function describe_status_key() {
+ return new ModuleStatus('MODULE_ORDER_TOTAL_PAYNETEASY_STATUS', 'true', 'false');
+ }
+
+ public function describe_sort_key() {
+ return new ModuleSortOrder('MODULE_ORDER_TOTAL_PAYNETEASY_SORT_ORDER');
+ }
+
+ public function configure_keys() {
+ return array(
+ 'MODULE_ORDER_TOTAL_PAYNETEASY_STATUS' =>
+ array(
+ 'value' => 'true',
+ 'sort_order' => '1',
+ 'set_function' => 'tep_cfg_select_option(array(\'true\', \'false\'), ',
+ ),
+ 'MODULE_ORDER_TOTAL_PAYNETEASY_SORT_ORDER' =>
+ array(
+ 'title' => 'Sort Order',
+ 'value' => '90',
+ 'description' => 'Sort order of display.',
+ 'sort_order' => '2',
+ ),
+ );
+ }
+
+}
diff --git a/source/payneteasy.php b/source/payneteasy.php
new file mode 100644
index 0000000..2536516
--- /dev/null
+++ b/source/payneteasy.php
@@ -0,0 +1,842 @@
+ 'PaynetEasy',
+ 'MODULE_PAYMENT_PAYNETEASY_TEXT_DESCRIPTION' => 'The PaynetEasy Payment Gateway enables merchants to accept credit card online during checkout.',
+ 'MODULE_PAYMENT_PAYNETEASY_ERROR' => 'There has been an error processing your credit card',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JANUARY' => 'January',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_FEBRUARY' => 'February',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_MARCH' => 'March',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_APRIL' => 'April',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_MAY' => 'May',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JUNE' => 'June',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JULY' => 'July',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_AUGUST' => 'August',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_SEPTEMBER' => 'September',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_OCTOBER' => 'October',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_NOVEMBER' => 'November',
+ 'MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_DECEMBER' => 'December',
+ 'MODULE_PAYMENT_PAYNETEASY_RESPONSE_TEXT' => 'PaynetEasy payment completed for %1$s.%2$s Transaction ID: %3$s.%4$s Approval Code: %5$s.%6$s RRN: %7$s',
+ ];
+
+ /**
+ * class constructor
+ */
+ function __construct($order_id = -1) {
+ parent::__construct();
+
+ $this->code = 'payneteasy';
+ $this->title = MODULE_PAYMENT_PAYNETEASY_TEXT_TITLE;
+ $this->description = MODULE_PAYMENT_PAYNETEASY_TEXT_DESCRIPTION;
+ if (!defined('MODULE_PAYMENT_PAYNETEASY_STATUS')) {
+ $this->enabled = false;
+ return false;
+ }
+
+ $this->sort_order = MODULE_PAYMENT_PAYNETEASY_SORT_ORDER;
+ $this->enabled = ((MODULE_PAYMENT_PAYNETEASY_STATUS == 'True') ? true : false);
+ $this->order_id = $order_id;
+ $this->order_status = MODULE_PAYMENT_PAYNETEASY_ORDER_STATUS_ID;
+ $this->paid_status = 0;
+
+ //remove keys if validate key false in last submit
+ if( defined('MODULE_PAYMENT_PAYNETEASY_VALIDATEKEY') && MODULE_PAYMENT_PAYNETEASY_VALIDATEKEY == "No" ) {
+ tep_db_query("UPDATE ".TABLE_PLATFORMS_CONFIGURATION." SET configuration_value='' WHERE configuration_key='MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID' AND platform_id='".(int)$platform_id."'");
+ tep_db_query("UPDATE ".TABLE_PLATFORMS_CONFIGURATION." SET configuration_value='' WHERE configuration_key='MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY' AND platform_id='".(int)$platform_id."'");
+ tep_db_query("UPDATE ".TABLE_PLATFORMS_CONFIGURATION." SET configuration_value='' WHERE configuration_key='MODULE_PAYMENT_PAYNETEASY_LOGIN' AND platform_id='".(int)$platform_id."'");
+ tep_db_query("UPDATE ".TABLE_PLATFORMS_CONFIGURATION." SET configuration_value='' WHERE configuration_key='MODULE_PAYMENT_PAYNETEASY_AUTHTOKEN' AND platform_id='".(int)$platform_id."'");
+ }
+
+ if( $this->manager ) {
+ $platform_id = $this->manager->getPlatformId();
+ $return_url = \Yii::$app->urlManager->createUrl('payneteasy/return-payment');
+ $refund_url = \Yii::$app->urlManager->createUrl('payneteasy/refund-payment');
+ $balancepayment_url = \Yii::$app->urlManager->createUrl('payneteasy/balance-payment');
+ $opyID = \Yii::$app->request->get('opyID');
+ $script = 'var payneteasy = {
+ platform_id : '.$platform_id.',
+ return_url : "'.$return_url.'",
+ refund_url : "'.$refund_url.'",
+ balancepayment_url : "'.$balancepayment_url.'",
+ opyID : "'.$opyID.'"
+ };';
+ \Yii::$app->getView()->registerJs($script);
+ }
+
+ if ($this->checkView() == "admin") {
+ $adminrefund = tep_catalog_href_link('lib/common/modules/orderPayment/payneteasy/js/adminrefund.js');
+ $adminrefundcss = tep_catalog_href_link('lib/common/modules/orderPayment/payneteasy/css/adminrefund.css');
+ \Yii::$app->getView()->registerJsFile($adminrefund);
+ \Yii::$app->getView()->registerCssFile($adminrefundcss);
+ } else {
+ $branddetection = tep_href_link('lib/common/modules/orderPayment/payneteasy/js/BrandDetection.js');
+ $creditcard = tep_href_link('lib/common/modules/orderPayment/payneteasy/js/creditcard.js');
+ $cc = tep_href_link('lib/common/modules/orderPayment/payneteasy/js/cc.js');
+ $payneteasycss = tep_href_link('lib/common/modules/orderPayment/payneteasy/css/payneteasy.css');
+ \Yii::$app->getView()->registerJsFile($branddetection);
+ \Yii::$app->getView()->registerJsFile($creditcard);
+ \Yii::$app->getView()->registerJsFile($cc);
+ \Yii::$app->getView()->registerCssFile($payneteasycss);
+ }
+ $this->update_status();
+ }
+
+ function getScriptName() {
+ global $PHP_SELF;
+ if (class_exists('\Yii') && is_object(\Yii::$app)) {
+ return \Yii::$app->controller->id;
+ } else {
+ return basename($PHP_SELF);
+ }
+ }
+
+ function checkView() {
+ $view = "admin";
+ if (tep_session_name() != 'tlAdminID') {
+ if ($this->getScriptName() == 'checkout' /* FILENAME_CHECKOUT_PAYMENT */) {
+ $view = "checkout";
+ } else {
+ $view = "frontend";
+ }
+ }
+ return $view;
+ }
+
+ function update_status() {
+ if (($this->enabled == true) && ((int) MODULE_PAYMENT_PAYNETEASY_ZONE > 0)) {
+ $check_flag = false;
+ $check_query = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_PAYNETEASY_ZONE . "' and zone_country_id = '" . $this->billing['country']['id'] . "' order by zone_id");
+ while ($check = tep_db_fetch_array($check_query)) {
+ if ($check['zone_id'] < 1) {
+ $check_flag = true;
+ break;
+ } elseif ($check['zone_id'] == $this->billing['zone_id']) {
+ $check_flag = true;
+ break;
+ }
+ }
+
+ if ($check_flag == false) {
+ $this->enabled = false;
+ }
+ }
+ }
+
+ function selection() {
+
+ //if store currency not euro then ignore payneteasy payment gateway
+ $transaction_currency = \Yii::$app->settings->get('currency');
+ if (strtolower($transaction_currency) != "eur") {
+ $this->enabled = false;
+ return false;
+ }
+
+ $months_array = array();
+ $months_array[0] = array('', 'Month');
+ $months_array[1] = array('01', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JANUARY);
+ $months_array[2] = array('02', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_FEBRUARY);
+ $months_array[3] = array('03', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_MARCH);
+ $months_array[4] = array('04', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_APRIL);
+ $months_array[5] = array('05', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_MAY);
+ $months_array[6] = array('06', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JUNE);
+ $months_array[7] = array('07', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_JULY);
+ $months_array[8] = array('08', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_AUGUST);
+ $months_array[9] = array('09', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_SEPTEMBER);
+ $months_array[10] = array('10', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_OCTOBER);
+ $months_array[11] = array('11', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_NOVEMBER);
+ $months_array[12] = array('12', MODULE_PAYMENT_PAYNETEASY_CC_TEXT_MONTH_DECEMBER);
+
+ $today = getdate();
+ $years_array = array();
+ $years_array[] = array('','Year');
+
+ for ($i = $today['year']; $i < $today['year'] + 10; $i++) {
+ $years_array[$i] = array(strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ strftime('%Y', mktime(0, 0, 0, 1, 1, $i)));
+ }
+
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'American Express') ) {
+ $amex = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/amex.png');
+ $logos .= '';
+ }
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'Visa') ) {
+ $visa = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/visa.png');
+ $logos .= '';
+ }
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'MasterCard') ) {
+ $mastercard = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/mastercard.png');
+ $logos .= '';
+ }
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'Discover') ) {
+ $discover = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/discover.png');
+ $logos .= '';
+ }
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'JCB') ) {
+ $jcb = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/jcb.png');
+ $logos .= '';
+ }
+ if( strstr(MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS,'Diners') ) {
+ $diners = tep_href_link('lib/common/modules/orderPayment/payneteasy/images/diners.png');
+ $logos .= '';
+ }
+
+ if ($this->checkView() == "admin") {
+ $paynetlogo = tep_catalog_href_link('lib/common/modules/orderPayment/payneteasy/logo/PaynetLogo.svg');
+ } else {
+ $paynetlogo = tep_href_link('lib/common/modules/orderPayment/payneteasy/logo/PaynetLogo.svg');
+ }
+
+ $billing_address = $this->manager->getBillingAddress();
+
+ $customer_id = \Yii::$app->user->getId();
+
+ $script = '';
+
+ return array('id' => $this->code,
+ 'module' => (MODULE_PAYMENT_PAYNETEASY_SHOWLOGO=='Yes'?'':MODULE_PAYMENT_PAYNETEASY_FRONT_TITLE).$script
+ );
+
+ }
+
+ public function install($platform_id) {
+ $languages_id = \common\classes\language::get_id(DEFAULT_LANGUAGE);
+
+ $get_current_status_id = tep_db_fetch_array(tep_db_query(
+ "SELECT MAX(orders_status_id) AS current_max_id FROM ".TABLE_ORDERS_STATUS." "
+ ));
+ $new_status_id = intval($get_current_status_id['current_max_id'])+1;
+
+ //check refunded order status if exist get id or insert then get id
+ $order_status_query = tep_db_query("SELECT orders_status_id FROM " . TABLE_ORDERS_STATUS . " WHERE orders_status_name = 'Refunded' AND language_id = '" . $languages_id . "'");
+ if ( tep_db_num_rows($order_status_query) <= 0 ) {
+ tep_db_query(
+ "INSERT INTO ".TABLE_ORDERS_STATUS." (orders_status_id, orders_status_groups_id, language_id, orders_status_name,
+ orders_status_template, automated, orders_status_template_confirm, orders_status_template_sms,
+ order_evaluation_state_id, order_evaluation_state_default, orders_status_allocate_allow,
+ orders_status_release_deferred, orders_status_send_ga, comment_template_id, hidden)
+ VALUES (".$new_status_id.", 5, ".$languages_id.", 'Refunded', 'Order Status Update', 0, 'Order Status Update', '', 60, 0, 1, 0, -1, 0, 0)"
+ );
+ }
+
+ //check partial refunded order status if exist get id or insert then get id
+ $order_status_query = tep_db_query("SELECT orders_status_id FROM " . TABLE_ORDERS_STATUS . " WHERE orders_status_name = 'Partially refunded' AND language_id = '" . $languages_id . "'");
+ if ( tep_db_num_rows($order_status_query) <= 0 ) {
+ tep_db_query(
+ "INSERT INTO ".TABLE_ORDERS_STATUS." (orders_status_id, orders_status_groups_id, language_id, orders_status_name,
+ orders_status_template, automated, orders_status_template_confirm, orders_status_template_sms,
+ order_evaluation_state_id, order_evaluation_state_default, orders_status_allocate_allow,
+ orders_status_release_deferred, orders_status_send_ga, comment_template_id, hidden)
+ VALUES (".$new_status_id.", 2, ".$languages_id.", 'Partially refunded', 'Order Status Update', 0, 'Order Status Update', '', 60, 0, 1, 0, -1, 0, 0)"
+ );
+ }
+
+ tep_db_query("CREATE TABLE `payneteasy_payments` (`paynet_order_id` int(11) NOT NULL, `merchant_order_id` int(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ //copy ot_payneteasy.php file to orderTotal module
+ if( file_exists(__DIR__."/ot_payneteasy.php") && copy(__DIR__."/ot_payneteasy.php",__DIR__."/../orderTotal/ot_payneteasy.php") ) {
+ unlink(__DIR__."/ot_payneteasy.php");
+ }
+
+ //check if table already exist or create new
+ $install_query = tep_db_query("Show tables like 'payneteasy_vault'");
+ if ( tep_db_num_rows($install_query) <= 0 ) {
+
+ tep_db_query("CREATE TABLE `payneteasy_vault` (`customer_id` int(11) NOT NULL, `vault_customer_id` int(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;");
+
+ tep_db_query("ALTER TABLE `payneteasy_vault` ADD PRIMARY KEY (`customer_id`,`vault_customer_id`);");
+
+ }
+
+ parent::install($platform_id);
+
+ }
+
+ function process_button() {
+ return false;
+ }
+
+ function _post_transaction()
+ {
+
+ }
+
+ function _start_transaction($order)
+ {
+ $billing = $order->billing;
+ $shipping = $order->delivery;
+ $customer = $order->customer;
+
+ $payneteasy_card_number = $this->manager->get('payneteasy-card-number');
+ $payneteasy_card_expiry_month = $this->manager->get('payneteasy-card-expiry-month');
+ $payneteasy_card_expiry_year = $this->manager->get('payneteasy-card-expiry-year');
+ $payneteasy_card_name = $this->manager->get('payneteasy-card-name');
+ $payneteasy_card_cvv = $this->manager->get('payneteasy-card-cvv');
+ $payneteasy_card_address = $this->manager->get('payneteasy-card-address');
+ $payneteasy_card_zip = $this->manager->get('payneteasy-card-zip');
+ $payneteasy_remote_address = $this->manager->get('payneteasy-remote-address');
+
+ $card_data = [
+ 'credit_card_number' => $payneteasy_card_number?:'',
+ 'card_printed_name' => $payneteasy_card_name?:'',
+ 'expire_month' => $payneteasy_card_expiry_month?:'',
+ 'expire_year' => $payneteasy_card_expiry_year?:'',
+ 'cvv2' => $payneteasy_card_cvv?:'',
+ ];
+
+ $data = [
+ 'client_orderid' => (string)$order->order_id,
+ 'order_desc' => 'Order # ' . $order->order_id,
+ 'amount' => $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']),
+ 'currency' => trim($order->info['currency'])?:'',
+ 'address1' => $payneteasy_card_address?:$billing["street_address"],
+ 'city' => $billing["city"]?:$shipping["city"],
+ 'zip_code' => $payneteasy_card_zip?:$billing["postcode"],
+ 'country' => $billing["country"]["iso_code_2"]?:$shipping["country"]["iso_code_2"],
+ 'phone' => $billing["telephone"]?:$shipping["telephone"],
+ 'email' => $customer["email_address"],
+ 'ipaddress' => $_SERVER['REMOTE_ADDR'],
+ 'cvv2' => $card_data['cvv2'],
+ 'credit_card_number' => $card_data['credit_card_number'],
+ 'card_printed_name' => $card_data['card_printed_name'],
+ 'expire_month' => $card_data['expire_month'],
+ 'expire_year' => $card_data['expire_year'],
+ 'first_name' => $customer['first_name'],
+ 'last_name' => $customer['last_name'],
+// 'redirect_success_url' => HTTP_SERVER.'/checkout/success?order_id='.$order->order_id,
+ 'redirect_success_url' => tep_href_link('callback/webhooks.payment.' . $this->code, 'action=success&orders_id=' . $order->order_id, 'SSL'),
+// 'redirect_fail_url' => HTTP_SERVER.'/checkout?payment_error=PaynetEasy&order_id='.$order->order_id,
+ 'redirect_fail_url' => tep_href_link('callback/webhooks.payment.' . $this->code, 'action=error&orders_id=' . $order->order_id, 'SSL'),
+// 'redirect_url' => HTTP_SERVER.'/checkout/success?order_id='.$order->order_id,
+ 'redirect_url' => tep_href_link('callback/webhooks.payment.' . $this->code, 'action=success&orders_id=' . $order->order_id, 'SSL'),
+ 'server_callback_url' => tep_href_link('callback/webhooks.payment.' . $this->code, 'action=success&orders_id=' . $order->order_id, 'SSL'),
+ ];
+
+ $payment_payneteasy_endpoint_id = MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID;
+
+ $payment_payneteasy_control_key = MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY;
+
+ $data['control'] = $this->signPaymentRequest($data, $payment_payneteasy_endpoint_id, $payment_payneteasy_control_key);
+
+ $sandbox = MODULE_PAYMENT_PAYNETEASY_SANDBOX;
+ $action_url = MODULE_PAYMENT_PAYNETEASY_LIVE_URL;
+
+ if ($sandbox == 'Yes')
+ $sandbox = true;
+ else
+ $sandbox = false;
+
+ if ($sandbox)
+ $action_url = MODULE_PAYMENT_PAYNETEASY_SANDBOX_URL;
+
+ $payment_payneteasy_payment_method = MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD;
+ $payment_payneteasy_endpoint_id = MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID;
+
+ $paynetApi = new PaynetApi(
+ MODULE_PAYMENT_PAYNETEASY_LOGIN,
+ MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY,
+ $payment_payneteasy_endpoint_id,
+ $payment_payneteasy_payment_method,
+ $sandbox
+ );
+
+ if ($payment_payneteasy_payment_method == 'Form') {
+ $response = $paynetApi->saleForm(
+ $data,
+ $payment_payneteasy_payment_method,
+ $sandbox,
+ $action_url,
+ $payment_payneteasy_endpoint_id
+ );
+ } elseif ($payment_payneteasy_payment_method == 'Direct') {
+ $response = $paynetApi->saleDirect(
+ $data,
+ $payment_payneteasy_payment_method,
+ $sandbox,
+ $action_url,
+ $payment_payneteasy_endpoint_id
+ );
+ }
+
+ tep_db_query(
+ "INSERT INTO payneteasy_payments (paynet_order_id, merchant_order_id)
+ VALUES (".$response['paynet-order-id'].", ".$response['merchant-order-id'].")"
+ );
+ return $response;
+ }
+
+ function _save_order() {
+ global $languages_id;
+
+ if (!empty($this->order_id) && $this->order_id > 0) {
+ return;
+ }
+
+ $order = $this->manager->getOrderInstance();
+
+ $order->save_order();
+
+ $order->save_details();
+
+ $order->save_products(false);
+
+ $stock_updated = false;
+
+ $this->order_id = $order->order_id;
+ }
+
+ function before_process()
+ {
+ return false;
+ }
+
+ function after_process()
+ {
+ $order = $this->manager->getOrderInstance();
+ $response = $this->_start_transaction($order);
+ $status = $this->getPaymentStatus($order);
+ $reset_cart = false;
+ if (trim($status['status']) == 'processing') {
+ if (MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD == 'Form') {
+ tep_redirect($response['redirect-url']);
+ } elseif (MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD == 'Direct') {
+ if (MODULE_PAYMENT_PAYNETEASY_THREE_D_SECURE == 'Yes') {
+ print $status['html'];
+ }
+ }
+ } elseif (trim($status['status']) == 'approved' || $status['status'] == 'approved') {
+ $reset_cart = true;
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_SUCCESSFUL;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = 'OK';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($response);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 100006, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ } elseif (trim($status['status']) == 'error' || $status['status'] == 'error') {
+ $reset_cart = true;
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_CANCELLED;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = '';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($status);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 5, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ $error_url = tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code . (tep_not_null($status['error-message']) ? '&error=' . $status['error-message'] : '') . '&' . tep_session_name() . '=' . tep_session_id(), 'SSL', false);
+ tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode($result['data']['message']), 'SSL'));
+ tep_redirect($error_url);
+ } elseif (trim($status['status']) == 'declined') {
+ $reset_cart = true;
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_CANCELLED;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = '';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($status);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 5, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ $error_url = tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'payment_error=' . $this->code . (tep_not_null($status['error-message']) ? '&error=' . $status['error-message'] : '') . '&' . tep_session_name() . '=' . tep_session_id(), 'SSL', false);
+ tep_redirect($error_url);
+ }
+ if ($reset_cart) {
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ }
+ }
+
+ public function call_webhooks() {
+ $order = $this->manager->getOrderInstanceWithId('\common\classes\Order', (int)$_POST['merchant_order']);
+ $status = $this->getPaymentStatus($order);
+ if (trim($status['status']) == 'approved' || $status['status'] == 'approved') {
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_SUCCESSFUL;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = 'OK';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($status);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 100006, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+
+ tep_redirect(HTTP_SERVER.'/checkout/success?order_id='.$order->order_id);
+ } elseif (trim($status['status']) == 'error' || $status['status'] == 'error') {
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_CANCELLED;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = '';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($status);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 5, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ echo '
';
+ echo '
Error:
';
+ echo $status['error-message'];
+ echo '
Return on homepage
';
+ echo '
';
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ } elseif (trim($status['status']) == 'declined') {
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = $this->code;
+ $orderPayment->orders_payment_module_name = $this->title;
+ $orderPayment->orders_payment_transaction_id = $status['paynet-order-id'];
+ $orderPayment->orders_payment_id_parent = 0;
+ $orderPayment->orders_payment_order_id = $order->order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_CANCELLED;
+ $orderPayment->orders_payment_amount = $this->formatCurrencyRaw($order->info['total_inc_tax'], $order->info['currency']);
+ $orderPayment->orders_payment_currency = trim($order->info['currency']);
+ $orderPayment->orders_payment_currency_rate = (float) $order->info['currency_value'];
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($order));
+ $orderPayment->orders_payment_transaction_status = '';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($status);
+ $orderPayment->save();
+ \common\helpers\Order::setStatus($order->order_id, 5, [
+ 'comments' => '',
+ 'customer_notified' => 0,
+ ]);
+ echo '';
+ echo '
Your payment was declined
';
+ echo $status['error-message'];
+ echo '
Return on homepage
';
+ echo '
';
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ tep_db_query("DELETE FROM " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " WHERE customers_id = '" . (int) $order->customer['id'] . "'");
+ }
+ }
+
+ function get_error()
+ {
+ $error = array('title' => 'Payment error',
+ 'error' => stripslashes(urldecode($_GET['error'])));
+ return $error;
+ }
+
+ function pre_confirmation_check()
+ {
+ $payneteasy_card_number = $_POST['payneteasy-card-number'];
+ $payneteasy_card_number = str_replace(' ','',$payneteasy_card_number);
+ $payneteasy_card_expiry_month = $_POST['payneteasy-card-expiry-month'];
+ $payneteasy_card_expiry_year = $_POST['payneteasy-card-expiry-year'];
+ $payneteasy_card_name = $_POST['payneteasy-card-name'];
+ $payneteasy_card_cvv = $_POST['payneteasy-card-cvv'];
+ $payneteasy_card_address = $_POST['payneteasy-card-address'];
+ $payneteasy_card_zip = $_POST['payneteasy-card-zip'];
+
+ $this->manager->set('payneteasy-card-number', $payneteasy_card_number);
+ $this->manager->set('payneteasy-card-expiry-month', $payneteasy_card_expiry_month);
+ $this->manager->set('payneteasy-card-expiry-year', $payneteasy_card_expiry_year);
+ $this->manager->set('payneteasy-card-name', $payneteasy_card_name);
+ $this->manager->set('payneteasy-card-cvv', $payneteasy_card_cvv);
+ $this->manager->set('payneteasy-card-address', $payneteasy_card_address);
+ $this->manager->set('payneteasy-card-zip', $payneteasy_card_zip);
+ $this->manager->set('payneteasy-remote-address', $_SERVER['REMOTE_ADDR']);
+ }
+
+ function formatCurrencyRaw($total, $currency_code = null, $currency_value = null) {
+
+ if (!isset($currency_code)) {
+ $currency_code = DEFAULT_CURRENCY;
+ }
+
+ if (!isset($currency_value) || !is_numeric($currency_value)) {
+ $currencies = \Yii::$container->get('currencies');
+ $currency_value = $currencies->currencies[$currency_code]['value'];
+ }
+
+ return number_format(self::round($total * $currency_value, $currencies->currencies[$currency_code]['decimal_places']), $currencies->currencies[$currency_code]['decimal_places'], '.', '');
+ }
+
+
+ function isOnline() {
+ return true;
+ }
+
+ public function configure_keys() {
+ return array(
+ 'MODULE_PAYMENT_PAYNETEASY_STATUS' => array(
+ 'title' => 'Enable PaynetPos',
+ 'value' => 'True',
+ 'description' => 'Do you want to accept PaynetEasy payments?',
+ 'sort_order' => '1',
+ 'set_function' => 'tep_cfg_select_option(array(\'True\', \'False\'), ',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_FRONT_TITLE' => array(
+ 'title' => 'Title',
+ 'value' => '',
+ 'description' => 'PaynetEasy APP Checkout Title',
+ 'sort_order' => '2',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_SANDBOX_URL' => array(
+ 'title' => 'Gateway url (SANDBOX)',
+ 'value' => '',
+ 'description' => 'https://sandbox.payneteasy.com/ etc.',
+ 'sort_order' => '3',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_LIVE_URL' => array(
+ 'title' => 'Gateway url (LIVE)',
+ 'value' => '',
+ 'description' => 'https://gate.payneteasy.com/ etc.',
+ 'sort_order' => '4',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_THREE_D_SECURE' => array(
+ 'title' => '3D Secure',
+ 'value' => 'No',
+ 'description' => '3D Secure or Non 3D Secure (WORK ONLY WITH DIRECT INTEGRATION METHOD).',
+ 'sort_order' => '5',
+ 'set_function' => 'multiOption(\'dropdown\', array(\'Yes\', \'No\'), ',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID' => array(
+ 'title' => 'Endpoint ID',
+ 'value' => '',
+ 'description' => 'Merchant ENDPOINT ID is required to call the API',
+ 'sort_order' => '6',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY' => array(
+ 'title' => 'Control Key',
+ 'value' => '',
+ 'description' => 'Merchant Control Key is required to call the API',
+ 'sort_order' => '7',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_LOGIN' => array(
+ 'title' => 'Login',
+ 'value' => '',
+ 'description' => 'Request header used by the merchant resource for additional authentication when accessing the payment gateway.',
+ 'sort_order' => '8',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_SANDBOX' => array(
+ 'title' => 'Use Sandbox',
+ 'value' => 'Yes',
+ 'description' => 'Set No if Production Keys are set OR Set Yes if Sandbox Keys are set then Live payments will not be taken.',
+ 'sort_order' => '9',
+ 'set_function' => 'multiOption(\'dropdown\', array(\'Yes\', \'No\'), ',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD' => array(
+ 'title' => 'Integration method',
+ 'value' => 'Direct',
+ 'description' => 'Select integration method (Direct or Form).',
+ 'sort_order' => '10',
+ 'set_function' => 'multiOption(\'dropdown\', array(\'Direct\', \'Form\'), ',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_SHOWLOGO' => array(
+ 'title' => 'Show Logo',
+ 'value' => 'Yes',
+ 'description' => 'Set Yes to show logo at checkout page OR Set No to show only title while selecting payment method.',
+ 'sort_order' => '11',
+ 'set_function' => 'multiOption(\'dropdown\', array(\'Yes\', \'No\'), ',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_ZONE' => array(
+ 'title' => 'Payment Zone',
+ 'value' => '0',
+ 'description' => 'If a zone is selected, only enable this payment method for that zone.',
+ 'sort_order' => '12',
+ 'use_function' => '\\common\\helpers\\Zones::get_zone_class_title',
+ 'set_function' => 'tep_cfg_pull_down_zone_classes(',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_ORDER_STATUS_ID' => array(
+ 'title' => 'Set Order Status',
+ 'value' => '0',
+ 'description' => 'Set the status of orders made with this payment module to this value.',
+ 'sort_order' => '13',
+ 'set_function' => 'tep_cfg_pull_down_order_statuses(',
+ 'use_function' => '\\common\\helpers\\Order::get_order_status_name',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_SORT_ORDER' => array(
+ 'title' => 'Sort order of display',
+ 'value' => '0',
+ 'description' => 'Sort order of PaynetEasy display. Lowest is displayed first.',
+ 'sort_order' => '14',
+ ),
+ 'MODULE_PAYMENT_PAYNETEASY_ACCEPTED_CARDS' => array(
+ 'title' => 'Accepted Cards',
+ 'value' => '',
+ 'description' => 'Allow Credit or Debit cards while purchasing at checkout page',
+ 'sort_order' => '15',
+ 'set_function' => "tep_cfg_select_multioption(array('American Express', 'Visa', 'MasterCard', 'Discover', 'JCB', 'Diners'),",
+ ),
+ );
+ }
+
+
+
+ public function describe_status_key()
+ {
+ return new ModuleStatus('MODULE_PAYMENT_PAYNETEASY_STATUS', 'True', 'False');
+ }
+
+ public function describe_sort_key()
+ {
+ return new ModuleSortOrder('MODULE_PAYMENT_PAYNETEASY_SORT_ORDER');
+ }
+
+ public function getPaymentStatus($order)
+ {
+ $paynet_order_id = tep_db_fetch_array(tep_db_query("SELECT paynet_order_id FROM payneteasy_payments WHERE merchant_order_id = '" . $order->order_id . "'"));
+
+ $data = [
+ 'login' => MODULE_PAYMENT_PAYNETEASY_LOGIN,
+ 'client_orderid' => (string)$order->order_id,
+ 'orderid' => $paynet_order_id['paynet_order_id'],
+ ];
+ $data['control'] = $this->signStatusRequest($data, MODULE_PAYMENT_PAYNETEASY_LOGIN, MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY);
+
+ $sandbox = MODULE_PAYMENT_PAYNETEASY_SANDBOX;
+ $action_url = MODULE_PAYMENT_PAYNETEASY_LIVE_URL;
+
+ if ($sandbox == 'Yes')
+ $sandbox = true;
+ else
+ $sandbox = false;
+
+ if ($sandbox)
+ $action_url = MODULE_PAYMENT_PAYNETEASY_SANDBOX_URL;
+
+ $paynetApi = new PaynetApi(
+ MODULE_PAYMENT_PAYNETEASY_LOGIN,
+ MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY,
+ MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID,
+ MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD,
+ $sandbox
+ );
+
+ $response = $paynetApi->status($data, MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD, $sandbox, $action_url, MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID);
+
+ if (
+ !isset($response['status'])
+ ) {
+// throw new Exception('No information about payment status.');
+ }
+
+ return $response;
+ }
+
+ private function signStatusRequest($requestFields, $login, $merchantControl)
+ {
+ $base = '';
+ $base .= $login;
+ $base .= $requestFields['client_orderid'];
+ $base .= $requestFields['orderid'];
+
+ return $this->signString($base, $merchantControl);
+ }
+
+ private function signPaymentRequest($data, $endpointId, $merchantControl)
+ {
+ $base = '';
+ $base .= $endpointId;
+ $base .= $data['client_orderid'];
+ $base .= $data['amount'] * 100;
+ $base .= $data['email'];
+
+ return $this->signString($base, $merchantControl);
+ }
+
+ private function signString($s, $merchantControl)
+ {
+ return sha1($s . $merchantControl);
+ }
+
+}
\ No newline at end of file
diff --git a/source/payneteasy/Bootstrap.php b/source/payneteasy/Bootstrap.php
new file mode 100644
index 0000000..0cb9f5e
--- /dev/null
+++ b/source/payneteasy/Bootstrap.php
@@ -0,0 +1,35 @@
+id == 'app-backend') {
+ $app->controllerMap = array_merge($app->controllerMap, [
+ 'payneteasy' => ['class' => __NAMESPACE__ . '\backend\controllers\PayneteasyController'],
+ ]);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/source/payneteasy/api/PaynetApi.php b/source/payneteasy/api/PaynetApi.php
new file mode 100644
index 0000000..2074212
--- /dev/null
+++ b/source/payneteasy/api/PaynetApi.php
@@ -0,0 +1,131 @@
+login = $login;
+ $this->password = $password;
+ $this->endpoint = $endpoint;
+ $this->integration_method = $integration_method;
+ $this->type = $type;
+ }
+
+ public function saleDirect($data, $integration_method, $type, $action_url, $endpoint)
+ {
+ return $this->execute('sale/' . $endpoint, $data, 'POST', $integration_method, $type, $action_url);
+ }
+
+ public function return($data, $integration_method, $type, $action_url, $endpoint)
+ {
+ return $this->execute('return/' . $endpoint, $data, 'POST', $integration_method, $type, $action_url);
+ }
+
+ public function status($data, $integration_method, $type, $action_url, $endpoint)
+ {
+ return $this->execute('status/' . $endpoint, $data, 'POST', $integration_method, $type, $action_url);
+ }
+
+ public function saleForm($data, $integration_method, $type, $action_url, $endpoint)
+ {
+ return $this->execute('sale-form/' . $endpoint, $data, 'POST', $integration_method, $type, $action_url);
+ }
+
+ protected function execute($action, $data, $method, $integration_method, $type, $action_url) {
+ return $this->curlRequestHandler($action, $data, $method, $integration_method, $type, $action_url);
+ }
+
+ protected function curlRequestHandler($action, $data, $method, $integration_method, $type, $action_url)
+ {
+ $curl = curl_init($action_url.$this->url.$action);
+
+ curl_setopt_array($curl, array
+ (
+ CURLOPT_HEADER => 0,
+ CURLOPT_USERAGENT => 'Payneteasy-Client/1.0',
+ CURLOPT_SSL_VERIFYHOST => 0,
+ CURLOPT_SSL_VERIFYPEER => 0,
+ CURLOPT_POST => 1,
+ CURLOPT_RETURNTRANSFER => 1
+ ));
+
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
+
+ $response = curl_exec($curl);
+
+ if(curl_errno($curl))
+ {
+ $error_message = 'Error occurred: ' . curl_error($curl);
+ $error_code = curl_errno($curl);
+ }
+ elseif(curl_getinfo($curl, CURLINFO_HTTP_CODE) != 200)
+ {
+ $error_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
+ $error_message = "Error occurred. HTTP code: '{$error_code}'";
+ }
+
+ curl_close($curl);
+
+ if (!empty($error_message))
+ {
+ throw new \Exception($error_message, $error_code);
+ }
+
+ if(empty($response))
+ {
+ throw new \Exception('Host response is empty');
+ }
+
+ $responseFields = array();
+
+ parse_str($response, $responseFields);
+
+ return $responseFields;
+
+ }
+
+ protected function parseHeadersToArray($rawHeaders)
+ {
+ $lines = explode("\r\n", $rawHeaders);
+ $headers = [];
+ foreach($lines as $line) {
+ if (strpos($line, ':') === false ){
+ continue;
+ }
+ list($key, $value) = explode(': ', $line);
+ $headers[$key] = $value;
+ }
+ return $headers;
+ }
+
+ protected function encode($data)
+ {
+ if (is_string($data)) {
+ return $data;
+ }
+ $result = json_encode($data);
+ $error = json_last_error();
+ if ($error != JSON_ERROR_NONE) {
+ throw new \Exception('JSON Error: ' . json_last_error_msg());
+ }
+ return $result;
+ }
+
+ public static function prepareOrderId($orderId, $forUrl = false)
+ {
+ $orderId = str_replace(['/','#','?','|',' '], ['-'], $orderId);
+ if ($forUrl) {
+ $orderId = urlencode($orderId);
+ }
+ return $orderId;
+ }
+}
diff --git a/source/payneteasy/backend/controllers/PayneteasyController.php b/source/payneteasy/backend/controllers/PayneteasyController.php
new file mode 100644
index 0000000..a7691f6
--- /dev/null
+++ b/source/payneteasy/backend/controllers/PayneteasyController.php
@@ -0,0 +1,338 @@
+ ' '.$error_message.'',
+// 'error' => true
+// );
+// echo json_encode($result);
+// exit();
+ }
+
+ public function actionRefundPayment()
+ {
+
+ }
+
+ function formatCurrencyRaw($total, $currency_code = null, $currency_value = null)
+ {
+
+ if (!isset($currency_code)) {
+ $currency_code = DEFAULT_CURRENCY;
+ }
+
+ if (!isset($currency_value) || !is_numeric($currency_value)) {
+ $currencies = \Yii::$container->get('currencies');
+ $currency_value = $currencies->currencies[$currency_code]['value'];
+ }
+
+ return number_format(self::round($total * $currency_value, $currencies->currencies[$currency_code]['decimal_places']), $currencies->currencies[$currency_code]['decimal_places'], '.', '');
+ }
+
+ public function actionBalancePayment()
+ {
+ if( \Yii::$app->request->isPost === FALSE ) return;
+ $post = \Yii::$app->request->post();
+ $opyID = $post['opyID'];
+ $paymentRecord = \common\helpers\OrderPayment::getRecord($opyID);
+ if ($paymentRecord instanceof \common\models\OrdersPayment) {
+ $orderPaymentAmountAvailable = \common\helpers\OrderPayment::getAmountAvailable($paymentRecord);
+ $result = array(
+ 'amount' => sprintf("%1.2f",$orderPaymentAmountAvailable),
+ 'message' => 'Amount already refunded!',
+ 'error' => false
+ );
+ echo json_encode($result);
+ } else {
+ $result = array(
+ 'error' => true
+ );
+ echo json_encode($result);
+ }
+ }
+
+ public function actionReturnPayment()
+ {
+ if( \Yii::$app->request->isPost === FALSE ) return;
+
+ $post = \Yii::$app->request->post();
+
+ if( !$post['platform_id'] ) $this->showError('The Platform ID is missing.');
+ elseif( !$post['opyID'] ) $this->showError('The Payment ID is missing.');
+ elseif( !$post['uuid'] ) $this->showError('The UUID is missing.');
+ elseif( !$post['amount'] ) $this->showError('The amount is missing.');
+ elseif( !is_numeric($post['amount']) ) $this->showError('The amount is invalid.');
+
+// $query = tep_db_query(
+// "select configuration_key, configuration_value from " . TABLE_PLATFORMS_CONFIGURATION . " ".
+// "where platform_id = '".intval($post['platform_id'])."' AND configuration_key in (
+// 'MODULE_PAYMENT_PAYNETEASY_FRONT_TITLE',
+// 'MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID',
+// 'MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY',
+// 'MODULE_PAYMENT_PAYNETEASY_LOGIN',
+// 'MODULE_PAYMENT_PAYNETEASY_SANDBOX',
+// )"
+// );
+//
+// while( $row = tep_db_fetch_array($query) ) {
+// define($row["configuration_key"], $row["configuration_value"]);
+// }
+
+ $transactionId = '';
+
+ $order_id = 0;
+ $order_currency = '';
+ $partialRefund = false;
+ $opyID = $post['opyID'];
+ $paymentRecord = \common\helpers\OrderPayment::getRecord($opyID);
+ if ($paymentRecord instanceof \common\models\OrdersPayment) {
+ $order_id = $paymentRecord["orders_payment_order_id"];
+ $order_currency = $paymentRecord["orders_payment_currency"];
+ $currency_value = $paymentRecord["orders_payment_currency_rate"];
+ $payment = json_decode($paymentRecord["orders_payment_transaction_full"], true);
+ $transactionId = $payment["Transaction ID"];
+
+ $orderPaymentAmountAvailable = \common\helpers\OrderPayment::getAmountAvailable($paymentRecord);
+ if ($post['amount'] > $orderPaymentAmountAvailable) {
+ $post['amount'] = $orderPaymentAmountAvailable;
+ }
+ if ($post['amount'] <= 0) {
+ $this->showError('Amount already refunded!');
+ }
+ if ($post['amount'] < $orderPaymentAmountAvailable) {
+ $partialRefund = true;
+ }
+ } else {
+ $this->showError('Parent payment record not found!');
+ }
+
+ if( !$order_id ) $this->showError('The order id is missing.');
+
+ $cartInstance = new \common\classes\shopping_cart((int)$order_id);
+ if (is_object($cartInstance)) {
+ $managerInstance = \common\services\OrderManager::loadManager($cartInstance);
+ if (is_object($managerInstance)) {
+ $orderInstance = $managerInstance->getOrderInstanceWithId('\common\classes\Order', (int)$order_id);
+ if (is_object($orderInstance)) {
+ Yii::$app->get('platform')->config((int)$post['platform_id'])->constant_up();
+ $managerInstance->set('platform_id', (int)$post['platform_id']);
+ }
+ }
+ }
+
+ $sandbox = MODULE_PAYMENT_PAYNETEASY_SANDBOX;
+ $action_url = MODULE_PAYMENT_PAYNETEASY_LIVE_URL;
+
+ if ($sandbox == 'Yes')
+ $sandbox = true;
+ else
+ $sandbox = false;
+
+ if ($sandbox)
+ $action_url = MODULE_PAYMENT_PAYNETEASY_SANDBOX_URL;
+
+ $payment_payneteasy_payment_method = MODULE_PAYMENT_PAYNETEASY_PAYMENT_METHOD;
+ $payment_payneteasy_endpoint_id = MODULE_PAYMENT_PAYNETEASY_ENDPOINT_ID;
+
+ $paynetApi = new PaynetApi(
+ MODULE_PAYMENT_PAYNETEASY_LOGIN,
+ MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY,
+ $payment_payneteasy_endpoint_id,
+ $payment_payneteasy_payment_method,
+ $sandbox
+ );
+
+ $paynet_order_id = tep_db_fetch_array(tep_db_query("SELECT paynet_order_id FROM payneteasy_payments WHERE merchant_order_id = '" . $order_id . "'"));
+
+ $data = [
+ 'login' => MODULE_PAYMENT_PAYNETEASY_LOGIN,
+ 'client_orderid' => $order_id,
+ 'orderid' => $paynet_order_id['paynet_order_id'],
+ 'comment' => 'Order cancel'
+ ];
+
+ $data['control'] = $this->signPaymentRequest($data, $payment_payneteasy_endpoint_id, MODULE_PAYMENT_PAYNETEASY_CONTROL_KEY);
+
+ $response = $paynetApi->return($data, $payment_payneteasy_payment_method, $sandbox, $action_url, $payment_payneteasy_endpoint_id);
+
+ if( trim($response['type']) == "validation-error" ) {
+ $error_message = $response['error-message'];
+// if( isset($response->desc) )
+// $error_message .= "
".$response->desc;
+ $result = array(
+ 'message' => ' '.$error_message.'',
+ 'error' => true
+ );
+ echo json_encode($result);
+ } else {
+ $currencies = \Yii::$container->get('currencies');
+// $orders_payment_transaction_id = $response->txnid;
+// $orders_payment_token = $response->token;
+// $orders_payment_rrn = $response->rrn;
+// $orders_payment_approval_code = $response->approval_code;
+//
+// $result = array (
+// "Transaction ID" => $orders_payment_transaction_id,
+// "Token" => $orders_payment_token,
+// "RRN" => $orders_payment_rrn,
+// "Approval Code" => $orders_payment_approval_code
+// );
+//
+// $response_string = sprintf(
+// 'PaynetPos payment %1$s for %2$s.%3$s Transaction ID: %4$s.%5$s Approval Code: %6$s.%7$s RRN: %8$s',
+// "completed",
+// $currencies->format($post['amount'], true, $order_currency, $currency_value),
+// "
",
+// $orders_payment_transaction_id,
+// "
",
+// $orders_payment_approval_code,
+// "
",
+// $orders_payment_rrn
+// );
+//
+ $orderPayment = new \common\models\OrdersPayment();
+ $orderPayment->orders_payment_module = 'payneteasy';
+ $orderPayment->orders_payment_module_name = MODULE_PAYMENT_PAYNETEASY_FRONT_TITLE;
+ $orderPayment->orders_payment_transaction_id = $paynet_order_id['paynet_order_id'];
+ $orderPayment->orders_payment_id_parent = $opyID;
+ $orderPayment->orders_payment_order_id = $order_id;
+ $orderPayment->orders_payment_is_credit = 0;
+ $orderPayment->deferred = 0;
+ $orderPayment->orders_payment_status = \common\helpers\OrderPayment::OPYS_REFUNDED;
+ $orderPayment->orders_payment_amount = $post['amount'];
+ $orderPayment->orders_payment_currency = trim($order_currency);
+ $orderPayment->orders_payment_currency_rate = (float) $currency_value;
+ $orderPayment->orders_payment_snapshot = json_encode(\common\helpers\OrderPayment::getOrderPaymentSnapshot($orderInstance));
+ $orderPayment->orders_payment_transaction_status = 'OK';
+ $orderPayment->orders_payment_transaction_commentary = '';
+ $orderPayment->orders_payment_date_create = date('Y-m-d H:i:s');
+ $orderPayment->orders_payment_transaction_full = json_encode($response);
+ global $login_id;
+ $orderPayment->orders_payment_admin_create = (int)$login_id;
+
+ if( $orderPayment->save() ) {
+
+ $languages_id = \common\classes\language::get_id(DEFAULT_LANGUAGE);
+
+ $updated = $orderInstance->updatePaidTotals();
+
+ if( !$partialRefund ) {
+
+ //check refunded order status if exist get id or insert then get id
+ $order_status_query = tep_db_query("SELECT orders_status_id FROM " . TABLE_ORDERS_STATUS . " WHERE orders_status_name = 'Refunded' AND language_id = '" . $languages_id . "'");
+ if ( tep_db_num_rows($order_status_query) > 0 ) {
+ $order_status = tep_db_fetch_array($order_status_query);
+ \common\helpers\Order::setStatus($order_id, (int)$order_status['orders_status_id'], [
+ 'customer_notifsssied' => 1,
+ ]);
+ }
+
+ }
+
+ if( $partialRefund ) {
+
+ //check partial refunded order status if exist get id or insert then get id
+ $order_status_query = tep_db_query("SELECT orders_status_id FROM " . TABLE_ORDERS_STATUS . " WHERE orders_status_name = 'Partially refunded' AND language_id = '" . $languages_id . "'");
+ if ( tep_db_num_rows($order_status_query) > 0 ) {
+ $order_status = tep_db_fetch_array($order_status_query);
+ \common\helpers\Order::setStatus($order_id, (int)$order_status['orders_status_id'], [
+ 'customer_notifsssied' => 1,
+ ]);
+ }
+
+ }
+
+// $response_string = sprintf(
+// ' Success!
The Payment %2$s has been %1$s successfully.%3$sTransaction ID: %4$s.%5$s Approval Code: %6$s.%7$s RRN: %8$s
',
+// "refunded",
+// $currencies->format($post['amount'], true, $order_currency, $currency_value),
+// "
",
+// $orders_payment_transaction_id,
+// "
",
+// $orders_payment_approval_code,
+// "
",
+// $orders_payment_rrn
+// );
+//
+// $result = array(
+// 'message' => $response_string,
+// 'error' => false
+// );
+// echo json_encode($result);
+//
+ } else {
+
+ $result = array(
+ 'message' => ' Error while updating Order totals!',
+ 'error' => true
+ );
+ echo json_encode($result);
+
+ }
+
+ }
+ }
+
+ private function signPaymentRequest($requestFields, $endpointId, $merchantControl)
+ {
+ $base = '';
+ $base .= $endpointId;
+ $base .= $requestFields['client_orderid'];
+ $base .= $requestFields['amount'] * 100;
+ $base .= $requestFields['email'];
+
+ return $this->signString($base, $merchantControl);
+ }
+
+ private function signString($s, $merchantControl)
+ {
+ return sha1($s . $merchantControl);
+ }
+
+}
\ No newline at end of file
diff --git a/source/payneteasy/css/adminrefund.css b/source/payneteasy/css/adminrefund.css
new file mode 100644
index 0000000..294fbac
--- /dev/null
+++ b/source/payneteasy/css/adminrefund.css
@@ -0,0 +1,129 @@
+.payneteasy-container {
+ width: 28em;
+ background-color: #ffffff;
+ padding: 2em 2em;
+ position: absolute;
+ transform: translate(-50%, -50%);
+ top: 50%;
+ left: 50%;
+ z-index: 99999;
+ text-align: center;
+ border-radius: 0.8em;
+ box-shadow: 0 45px 60px rgba(30, 22, 1, 0.3);
+}
+.payneteasy-container #timerbox {
+ display: none;
+}
+.payneteasy-container .badge {
+ font-weight: bold;
+ color: #000;
+ background: #ffb800;
+}
+.payneteasy-container .text-error {
+ color: #ff0000;
+ display: inline-block;
+}
+.payneteasy-container #resendcode {
+ color: #7952b3;
+ border:0px;
+ background: #ffffff;
+}
+.payneteasy-container .disabledresendcode {
+ opacity: 0.5;
+}
+.payneteasy-container .inputfield {
+ width: 100%;
+ display: flex;
+ margin-top: 1em;
+ margin-bottom: 2em;
+ justify-content: space-around;
+}
+.payneteasy-container .input {
+ height: 2em;
+ width: 2em;
+ border: 1px solid #dad9df;
+ outline: none;
+ text-align: center;
+ font-size: 1.5em;
+ border-radius: 0.2em;
+ background-color: #ffffff;
+ outline: none;
+ /*Hide number field arrows*/
+ -moz-appearance: textfield;
+}
+.payneteasy-container input[type="number"]::-webkit-outer-spin-button,
+.payneteasy-container input[type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+.payneteasy-container .input:disabled {
+ color: #89888b;
+}
+.payneteasy-container .input:focus {
+ border: 3px solid #ffb800;
+}
+.payneteasy-container .buttonbox {
+ margin: 1em auto;
+ display: block;
+ width: 100%;
+ text-align: center;
+}
+.payneteasy-container .buttonbox button {
+ margin-left: 4px;
+ margin-right: 4px;
+}
+.warn,
+.warn::before,
+.warn::after
+{
+ position: relative;
+ padding: 0;
+ margin: 0;
+}
+
+.warn {
+ font-size: 25px;
+ margin-right: 5px;
+ display: inline-block;
+ color: transparent;
+}
+
+.warn.warning {
+ display: inline-block;
+ top: 0.225em;
+ width: 1.15em;
+ height: 1.15em;
+ text-align: center;
+ overflow: hidden;
+ border: none;
+ background-color: transparent;
+ border-radius: 0.625em;
+}
+
+.warn.warning::before {
+ content: "";
+ display: block;
+ top: -0.08em;
+ left: 0.0em;
+ position: absolute;
+ border: transparent 0.6em solid;
+ border-bottom-color: #fd3;
+ border-bottom-width: 1em;
+ border-top-width: 0;
+ box-shadow: #999 0 1px 1px;
+}
+
+.warn.warning::after {
+ display: block;
+ position: absolute;
+ top: 0.3em;
+ left: 0;
+ width: 100%;
+ padding: 0 1px;
+ text-align: center;
+ font-family: "Garamond";
+ content: "!";
+ font-size: 0.65em;
+ font-weight: bold;
+ color: #333;
+}
\ No newline at end of file
diff --git a/source/payneteasy/css/payneteasy.css b/source/payneteasy/css/payneteasy.css
new file mode 100644
index 0000000..348e734
--- /dev/null
+++ b/source/payneteasy/css/payneteasy.css
@@ -0,0 +1,89 @@
+#frmCheckout button[type="submit"]:disabled {
+ opacity:0.5;
+ cursor: not-allowed;
+}
+#frmCheckout button[type="submit"]:disabled, .w-checkout-continue-btn .or-text:first-of-type {
+ display:none
+}
+#paynetCcBox .logobox {
+ text-align:right;
+}
+#paynetCcBox .required-message-wrap {
+ display:none;
+ width:100%;
+}
+#paynetCcBox .payneteasy-cc-logo {
+ width:70px;
+ opacity:0.3;
+}
+#paynetCcBox .col-25 {
+ float:right;
+}
+#paynetCcBox .col-75 {
+ margin-right:10px;
+ float:left;
+ position:relative;
+}
+#paynetCcBox .col-75 {
+ float:left;
+}
+#paynetCcBox input[type=text],#paynetCcBox select,#paynetCcBox input[type=password] {
+ width:100%;
+ margin-bottom:0px;
+ resize:vertical;
+}
+#paynetCcBox .required-message-wrap {
+ margin-bottom:5px;
+}
+#paynetCcBox label {
+ padding:12px 12px 0px 0;
+ display:inline-block;
+}
+#paynetCcBox .container {
+ border-radius:5px;
+ background-color:#f2f2f2;
+ padding:20px;
+}
+#paynetCcBox .col-25 {
+ width:36%;
+ margin-right:4%;
+ position:relative;
+}
+#paynetCcBox .col-75 {
+ width:56%;
+}
+#paynetCcBox .col-100 {
+ width:96%;
+}
+#paynetCcBox .payneteasy-card-head, #paynetCcBox .payneteasy-card-head label {
+ cursor: pointer;
+ font-weight: bold;
+}
+#paynetCcBox .row-new-card {
+ margin-top: 10px;
+ border-top: 1px solid #ccc;
+}
+#paynetCcBox #new-card-panel {
+ display:block;
+ margin-left:4%;
+ width:96%;
+}
+#paynetCcBox .col-50-1 {
+ float:left;
+ width:48%;
+}
+#paynetCcBox .col-50-2 {
+ float:right;
+ width:48%;
+}
+#paynetCcBox .row:after {
+ content:"";
+ display:table;
+ clear:both;
+}
+@media screen and (max-width:600px) {
+ #paynetCcBox .col-25,#paynetCcBox .col-75 {
+ width:100%;
+ margin-top:0;
+ }
+}
\ No newline at end of file
diff --git a/source/payneteasy/images/amex.png b/source/payneteasy/images/amex.png
new file mode 100644
index 0000000..366f6e2
Binary files /dev/null and b/source/payneteasy/images/amex.png differ
diff --git a/source/payneteasy/images/diners.png b/source/payneteasy/images/diners.png
new file mode 100644
index 0000000..0134bf0
Binary files /dev/null and b/source/payneteasy/images/diners.png differ
diff --git a/source/payneteasy/images/discover.png b/source/payneteasy/images/discover.png
new file mode 100644
index 0000000..ac653f0
Binary files /dev/null and b/source/payneteasy/images/discover.png differ
diff --git a/source/payneteasy/images/jcb.png b/source/payneteasy/images/jcb.png
new file mode 100644
index 0000000..f70bfd5
Binary files /dev/null and b/source/payneteasy/images/jcb.png differ
diff --git a/source/payneteasy/images/mastercard.png b/source/payneteasy/images/mastercard.png
new file mode 100644
index 0000000..b274d7e
Binary files /dev/null and b/source/payneteasy/images/mastercard.png differ
diff --git a/source/payneteasy/images/visa.png b/source/payneteasy/images/visa.png
new file mode 100644
index 0000000..7d21c22
Binary files /dev/null and b/source/payneteasy/images/visa.png differ
diff --git a/source/payneteasy/js/BrandDetection.js b/source/payneteasy/js/BrandDetection.js
new file mode 100644
index 0000000..888425e
--- /dev/null
+++ b/source/payneteasy/js/BrandDetection.js
@@ -0,0 +1,109 @@
+PaynetEasyBrandDetection = function() {
+};
+
+PaynetEasyBrandDetection.prototype.option =
+{
+ 'minlength': 6
+};
+
+PaynetEasyBrandDetection.prototype.creditcard =
+{
+ 'carte-bleue': {
+ 'pattern': /^(415006|497|407497|513)/,
+ 'cardlength': [13, 16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'carta-si': {
+ 'pattern': /^(45399[78]|432913|5255)/,
+ 'cardlength': [16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'dankort': {
+ 'pattern': /^(4571|5019)/,
+ 'cardlength': [16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'china-unionpay': {
+ 'pattern': /^(62|88)/,
+ 'cardlength': [16, 17, 18, 19],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'discover': {
+ 'pattern': /^6(011|5)/,
+ 'cardlength': [16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'diners-club': {
+ 'pattern': /^3(0[0-5]|[68])/,
+ 'cardlength': [14],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'maestro': {
+ 'pattern': /^(5018|5020|5038|5893|6304|6759|6761|6762|6763|0604|6390)/,
+ 'cardlength': [12, 13, 14, 15, 16, 17, 18, 19],
+ 'luhn': false,
+ 'cvc': [0, 3, 4]
+ },
+ 'jcb': {
+ 'pattern': /^(2131|1800|35)/,
+ 'cardlength': [16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'amex': {
+ 'pattern': /^(3[47])/,
+ 'cardlength': [15],
+ 'luhn': false,
+ 'cvc': [3, 4]
+ },
+ 'mastercard': {
+ 'pattern': /^(5[1-5])/,
+ 'cardlength': [16],
+ 'luhn': false,
+ 'cvc': [3]
+ },
+ 'visa': {
+ 'pattern': /^(4)/,
+ 'cardlength': [13, 16],
+ 'luhn': false,
+ 'cvc': [3]
+ }
+};
+
+PaynetEasyBrandDetection.prototype.hasOwnProperty = function(property) {
+ return this[property] !== undefined;
+};
+
+PaynetEasyBrandDetection.prototype.detect = function(cardnumber)
+{
+ var brand = 'unknown';
+ if (cardnumber.length >= this.option.minlength) {
+ for (var cardinfo in this.creditcard) {
+ if (this.creditcard[cardinfo].pattern.test(cardnumber)) {
+ brand = cardinfo;
+ break;
+ }
+ }
+ }
+ return brand;
+};
+
+PaynetEasyBrandDetection.prototype.validate = function(cardnumber)
+{
+ if (this.creditcard.hasOwnProperty(this.detect(cardnumber))) {
+ return this.creditcard[this.detect(cardnumber)].cardlength.indexOf(cardnumber.length) !== -1;
+ }
+
+ return false;
+};
+
+PaynetEasyBrandDetection.prototype.luhn = function(cardnumber)
+{
+ //todo
+};
\ No newline at end of file
diff --git a/source/payneteasy/js/adminrefund.js b/source/payneteasy/js/adminrefund.js
new file mode 100644
index 0000000..b0f4468
--- /dev/null
+++ b/source/payneteasy/js/adminrefund.js
@@ -0,0 +1,127 @@
+$(document).ready(function () {
+
+ if( $('input[type="submit"]').length > 0 && $('input[type="submit"]').val() == "Update" ) {
+ $('#order_payment_edit').delegate('#refundbutton', 'click', function (e) {
+ var vamount = $('input[name=orders_payment_amount]').val();
+ if( !vamount ) {
+ alert('Please enter valid amount.');
+ $('input[name=orders_payment_amount]').focus();
+ return;
+ }
+ else if( !$.isNumeric(vamount) ) {
+ alert('Please enter valid amount.');
+ $('input[name=orders_payment_amount]').focus();
+ $('input[name=orders_payment_amount]').select();
+ return;
+ }
+ $(this).prop('disabled',true);
+ $.fn.returnPayment();
+ });
+
+ $.fn.timerCount = function() {
+ var timer2 = "1:30";
+ var interval = setInterval(function() {
+ var timer = timer2.split(':');
+ var minutes = parseInt(timer[0], 10);
+ var seconds = parseInt(timer[1], 10);
+ --seconds;
+ minutes = (seconds < 0) ? --minutes : minutes;
+ seconds = (seconds < 0) ? 59 : seconds;
+ seconds = (seconds < 10) ? '0' + seconds : seconds;
+ $('#timebox').html('0'+minutes + ':' + seconds);
+ if (minutes < 0) clearInterval(interval);
+ if ((seconds <= 0) && (minutes <= 0)) {
+ clearInterval(interval);
+ $('#timerbox').hide();
+ $("#resendcode").prop('disabled',false);
+ $("#resendcode").removeClass('disabledresendcode');
+ }
+ timer2 = minutes + ':' + seconds;
+ }, 1000);
+ }
+
+ $.fn.returnPayment = function() {
+ $.post(payneteasy.return_url, { platform_id: payneteasy.platform_id, opyID: payneteasy.opyID, amount: $('input[name=orders_payment_amount]').val() }, function( data ) {
+ data = JSON.parse(data);
+ console.log(data);
+ if(!data) {
+ if( data.message ) $("#resp").html(data.message);
+ } else {
+ $('input[name=payneteasy_uuid]').val(data.uuid);
+ }
+ });
+ }
+
+
+ $('#order_payment_edit').delegate('#resendcode', 'click', function (e) {
+ e.preventDefault();
+ $.each($('.input'), function (index, value) {
+ $(this).val('');
+ });
+ $("#resp").html('');
+ });
+
+ $('#order_payment_edit').delegate('#donebutton', 'click', function (e) {
+ location.reload();
+ });
+
+ $.fn.balancepayment = function() {
+ $.post(payneteasy.balancepayment_url, { opyID: payneteasy.opyID }, function( data ) {
+ data = JSON.parse(data);
+ if( !data.error && Number(data.amount) <= 0 ) {
+ $('#order_payment_edit input[type="submit"]').parent().append('');
+ $('#order_payment_edit input[type="submit"]').hide();
+ $('textarea[name="orders_payment_transaction_commentary"]').val('');
+ }
+ else {
+ $('input[name=orders_payment_amount]').val(data.amount);
+ $('#order_payment_edit input[type="submit"]').parent().append('');
+ $('textarea[name="orders_payment_transaction_commentary"]').val('');
+ $('#order_payment_edit input[type="submit"]').show();
+ }
+ });
+ }
+
+ $.fn.checkAllBox = function() {
+ var fullstring = '';
+ $.each($('.input'), function (index, value) {
+ fullstring += $(this).val();
+ });
+ }
+
+ $('#order_payment_edit').delegate('.input', 'input', function (e) {
+ $(this).val(
+ $(this)
+ .val()
+ .replace(/[^0-9]/g, "").substr(0,1)
+ );
+ $.fn.checkAllBox();
+ });
+
+ $('#order_payment_edit').delegate('.input', 'keyup', function (e) {
+ let key = e.keyCode || e.charCode;
+ if (key == 8 || key == 46 || key == 37 || key == 40) {
+ // Backspace or Delete or Left Arrow or Down Arrow
+ $(this).prev().focus();
+ } else if (key == 38 || key == 39 || $(this).val() != "") {
+ // Right Arrow or Top Arrow or Value not empty
+ $(this).next().focus();
+ }
+ });
+
+ $('#order_payment_edit').delegate('.input', 'paste', function (e) {
+ var obj = $('.input');
+ var paste_data = e.originalEvent.clipboardData.getData("text");
+ var paste_data_splitted = paste_data.split("");
+ $.each(paste_data_splitted, function (index, value) {
+ obj.eq(index).val(value);
+ });
+ });
+
+ setTimeout(function(){
+ $.fn.balancepayment();
+ }, 500);
+
+ }
+
+});
\ No newline at end of file
diff --git a/source/payneteasy/js/cc.js b/source/payneteasy/js/cc.js
new file mode 100644
index 0000000..f01dc28
--- /dev/null
+++ b/source/payneteasy/js/cc.js
@@ -0,0 +1,269 @@
+$(document).ready(function () {
+
+ $('form[name="one_page_checkout"]').submit(function (e) {
+ hideErrorBoxes();
+
+ var ccErrorFlag = true;
+ var cc = new PaynetEasyCC();
+
+ if (!cc.isValid($("#payneteasy-card-number").val())) {
+ $("#payneteasy-card-number-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if (!cc.isExpirationDateValid($("#payneteasy-card-expiry-month").val(), $("#payneteasy-card-expiry-year").val())) {
+ $("#payneteasy-card-expiry-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if ($("#payneteasy-card-name").val().length <= 0) {
+ $("#payneteasy-card-name-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if (!cc.isSecurityCodeValid($("#payneteasy-card-number").val(), $("#payneteasy-card-cvv").val())) {
+ $("#payneteasy-card-cvv-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if ($("#payneteasy-card-address").length > 0 && $("#payneteasy-card-address").val().length <= 0) {
+ $("#payneteasy-card-address-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if ($("#payneteasy-card-zip").length > 0 && $("#payneteasy-card-zip").val().length <= 0) {
+ $("#payneteasy-card-zip-error").fadeIn('slow');
+ ccErrorFlag = false;
+ }
+
+ if (!ccErrorFlag) {
+ $('.w-checkout-continue-btn button[type=submit]').prop('disabled', false);
+ $('.w-checkout-continue-btn button[type=submit]').addClass('disabled-area');
+ if( $('.hide-page').length > 0 ) $('.hide-page').remove();
+ if( $('.fake-input').length > 0 ) $('.fake-input').remove();
+ return ccErrorFlag;
+ }
+ return true;
+ });
+
+ window.PaynetEasyCreateCCForm = function()
+ {
+ if ( $('input[name=payment][value="payneteasy"]').length <= 0 ) return;
+
+ if ($('input[name=payment][value="payneteasy"]').is(':checked')){
+ console.log(payneteasy_payment_method);
+ if (payneteasy_payment_method == 'Direct') {
+
+ if( $('#paynetCcBox').length > 0 ) $('#paynetCcBox').remove();
+ var payneteasy_avs_string = '';
+ var payneteasy_new_card = '';
+
+ // if( payneteasy_avs_options == 'zipandaddress' ) payneteasy_avs_string = '';
+ // else if( payneteasy_avs_options == 'address' ) payneteasy_avs_string = '';
+ // else if( payneteasy_avs_options == 'zip' ) payneteasy_avs_string = '';
+
+ var formString = ''+payneteasy_new_card+'
Please select valid expiration date.
';
+ $("").attr('id','paynetCcBox').html(formString).appendTo($(".payment_class_payneteasy").parents('.type-1')[1]);
+
+ for ( var cc_month_counter in payneteasy_cc_months ) {
+ var cc_month_value = payneteasy_cc_months[cc_month_counter][0];
+ var cc_month_text = $("").html(payneteasy_cc_months[cc_month_counter][1]).text();
+ $('').val(cc_month_value).text(cc_month_text).appendTo($('#payneteasy-card-expiry-month'));
+ };
+
+ for ( var cc_year_counter in payneteasy_cc_years ) {
+ var cc_year_value = payneteasy_cc_years[cc_year_counter][0];
+ var cc_year_text = payneteasy_cc_years[cc_year_counter][1];
+ $('').val(cc_year_value).text(cc_year_text).appendTo($('#payneteasy-card-expiry-year'));
+ };
+
+ window.PaynetEasyAddCardDetection();
+ hideErrorBoxes();
+
+ $(".payneteasy-card-head").click(function() {
+ var ind = parseInt( $(this).attr("rel") );
+ $(".payneteasy-payment-card").eq(ind-1).prop('checked', true);
+ $(".payneteasy-payment-card").change();
+ });
+
+ $(".payneteasy-payment-card").change(function() {
+ if( $(this).val() == 1 && $(this).is(":checked") ) {
+ $("#new-card-panel").slideUp();
+ }
+ else if( $(this).val() == 2 && $(this).is(":checked") ) {
+ $("#new-card-panel").slideDown();
+ }
+ });
+
+ setTimeout(function() {
+ var address = ($('#shipping_address-street_address').length>0?$('#shipping_address-street_address').val():payneteasy_street_address);
+ var postcode = ($('#shipping_address-postcode').length>0?$('#shipping_address-postcode').val():payneteasy_postcode);
+ $("#payneteasy-card-address").val(address);
+ $("#payneteasy-card-zip").val(postcode);
+ },1000);
+ }
+ } else {
+ $('#paynetCcBox').remove();
+ }
+
+ }
+
+ window.PaynetEasyAddCardDetection = function()
+ {
+ $('#payneteasy-card-number').on('keydown',function(e){
+ var deleteKeyCode = 8;
+ var tabKeyCode = 9;
+ var backspaceKeyCode = 46;
+ if ((e.key>=0 && e.key<=9) ||
+ e.which === deleteKeyCode || // for delete key,
+ e.which === tabKeyCode || // for tab key
+ e.which === backspaceKeyCode) // for backspace
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ });
+
+ $('#payneteasy-card-number').keyup(function() {
+ checkErrors();
+ var val = $(this).val();
+ var newval = '';
+ var cardNumber = val.replace(/\s/g, '');
+ for(var i=0; i < cardNumber.length; i++) {
+ if(i%4 == 0 && i > 0) newval = newval.concat(' ');
+ newval = newval.concat(cardNumber[i]);
+ }
+ $(this).val(newval);
+ var detector = new PaynetEasyBrandDetection();
+ var brand = detector.detect(cardNumber);
+ $('.payneteasy-cc-logo').css('opacity','0.3');
+ if (brand && brand != "unknown") {
+ if($('#payneteasy-cc-'+brand).length <= 0 ) {
+ alert(brand.toUpperCase()+" credit card is not accepted");
+ $('#payneteasy-card-number').val("");
+ }
+ else {
+ $('#payneteasy-cc-'+brand).css('opacity','1');
+ }
+ }
+ });
+
+ $('#payneteasy-card-expiry-month').change(function (e) {
+ checkErrors();
+ });
+
+ $('#payneteasy-card-expiry-year').change(function (e) {
+ checkErrors();
+ });
+
+ $('#payneteasy-card-name').keyup(function (e) {
+ checkErrors();
+ });
+
+ $("#payneteasy-card-name").on("keydown", function(event){
+ // Allow controls such as backspace, tab etc.
+ var arr = [8,9,16,17,20,32,35,36,37,38,39,40,45,46];
+ // Allow letters
+ for(var i = 65; i <= 90; i++){
+ arr.push(i);
+ }
+ // Prevent default if not in array
+ if(jQuery.inArray(event.which, arr) === -1){
+ return false;
+ }
+ else return true;
+ });
+
+ $('#payneteasy-card-cvv').keyup(function (e) {
+ checkErrors();
+ });
+
+ $('#payneteasy-card-cvv').on('keydown',function(e){
+ var deleteKeyCode = 8;
+ var tabKeyCode = 9;
+ var backspaceKeyCode = 46;
+ if ((e.key>=0 && e.key<=9) ||
+ (e.which>=96 && e.which<=105) || // for num pad numeric keys
+ e.which === deleteKeyCode || // for delete key,
+ e.which === tabKeyCode || // for tab key
+ e.which === backspaceKeyCode) // for backspace
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ });
+
+ if( $('#payneteasy-card-address').length > 0 ) {
+ $('#payneteasy-card-address').keyup(function (e) {
+ checkErrors();
+ });
+ }
+
+ if( $('#payneteasy-card-zip').length > 0 ) {
+ $('#payneteasy-card-zip').keyup(function (e) {
+ checkErrors();
+ });
+
+ $('#payneteasy-card-zip').on('keydown',function(e){
+ var deleteKeyCode = 8;
+ var tabKeyCode = 9;
+ var backspaceKeyCode = 46;
+ if ((e.key>=0 && e.key<=9) ||
+ (e.which>=96 && e.which<=105) || // for num pad numeric keys
+ e.which === deleteKeyCode || // for delete key,
+ e.which === tabKeyCode || // for tab key
+ e.which === backspaceKeyCode) // for backspace
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ });
+ }
+
+ }
+
+ function checkErrors()
+ {
+ var allentered = true;
+ if( $("#payneteasy-card-number").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-expiry-month").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-expiry-year").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-name").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-cvv").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-address").length > 0 && $("#payneteasy-card-address").val().length <= 0 ) allentered = false;
+ if( $("#payneteasy-card-zip").length > 0 && $("#payneteasy-card-zip").val().length <= 0 ) allentered = false;
+ if( allentered ) {
+ $('.w-checkout-continue-btn button[type=submit]').prop('disabled', false);
+ $('.w-checkout-continue-btn button[type=submit]').removeClass('disabled-area');
+ }
+ }
+
+ function hideErrorBoxes()
+ {
+ $("#payneteasy-card-cvv-error").css('display', 'none');
+ $("#payneteasy-card-number-error").css('display', 'none');
+ $("#payneteasy-card-expiry-error").css('display', 'none');
+ $("#payneteasy-card-name-error").css('display', 'none');
+ if( $("#payneteasy-card-address-error").length > 0 ) $("#payneteasy-card-address-error").css('display', 'none');
+ if( $("#payneteasy-card-zip-error").length > 0 ) $("#payneteasy-card-zip-error").css('display', 'none');
+ }
+
+ if (typeof tl == 'function'){
+ tl(function(){
+ window.PaynetEasyCreateCCForm();
+ try {
+ checkout_payment_changed.set('window.PaynetEasyCreateCCForm');
+ } catch (e ) {console.log(e ); }
+ })
+ }
+
+});
\ No newline at end of file
diff --git a/source/payneteasy/js/creditcard.js b/source/payneteasy/js/creditcard.js
new file mode 100644
index 0000000..b070191
--- /dev/null
+++ b/source/payneteasy/js/creditcard.js
@@ -0,0 +1,177 @@
+var PAYNETCARDS = [{
+ name: 'Banescard',
+ bins: /^(603182)[0-9]{10,12}/,
+ codeLength: 3
+ }, {
+ name: 'Maxxvan',
+ bins: /^(603182)[0-9]{10,12}/,
+ codeLength: 3
+ }, {
+ name: 'Cabal',
+ bins: /^(604324|604330|604337|604203|604338)[0-9]{10,12}/,
+ codeLength: 3
+ }, {
+ name: 'GoodCard',
+ bins: /^(606387|605680|605674|603574)[0-9]{10,12}/,
+ codeLength: 3
+ }, {
+ name: 'Elo',
+ bins: /^(401178|401179|431274|438935|451416|457393|457631|457632|504175|627780|636297|636368|(506699|5067[0-6]\d|50677[0-8])|(50900\d|5090[1-9]\d|509[1-9]\d{2})|65003[1-3]|(65003[5-9]|65004\d|65005[0-1])|(65040[5-9]|6504[1-3]\d)|(65048[5-9]|65049\d|6505[0-2]\d|65053[0-8])|(65054[1-9]|6505[5-8]\d|65059[0-8])|(65070\d|65071[0-8])|65072[0-7]|(6509[0-9])|(65165[2-9]|6516[6-7]\d)|(65500\d|65501\d)|(65502[1-9]|6550[3-4]\d|65505[0-8]))[0-9]{10,12}/,
+ codeLength: 3
+ }, {
+ name: 'Diners',
+ bins: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
+ codeLength: 3
+ }, {
+ name: 'Discover',
+ bins: /^6(?:011|5[0-9]{2}|4[4-9][0-9]{1}|(22(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[01][0-9]|92[0-5]$)[0-9]{10}$))[0-9]{12}$/,
+ codeLength: 4
+ }, {
+ name: 'Amex',
+ bins: /^3[47][0-9]{13}$/,
+ codeLength: 4
+ }, {
+ name: 'Aura',
+ bins: /^50[0-9]{14,17}$/,
+ codeLength: 3
+ }, {
+ name: 'Mastercard',
+ bins: /^(603136|603689|608619|606200|603326|605919|608783|607998|603690|604891|603600|603134|608718|603680|608710|604998)|(5[1-5][0-9]{14}|2221[0-9]{12}|222[2-9][0-9]{12}|22[3-9][0-9]{13}|2[3-6][0-9]{14}|27[01][0-9]{13}|2720[0-9]{12})$/,
+ codeLength: 3
+ }, {
+ name: 'Visa',
+ bins: /^4[0-9]{12}(?:[0-9]{3})?$/,
+ codeLength: 3
+ }, {
+ name: 'Hipercard',
+ bins: /^(38[0-9]{17}|60[0-9]{14})$/,
+ codeLength: 3
+ }, {
+ name: 'JCB',
+ bins: /^(?:2131|1800|35\d{3})\d{11}$/,
+ codeLength: 3
+ }];
+
+ var PAYNETMILLENNIUM = 1000;
+ var PAYNET_DEFAULT_CODE_LENGTH = 3;
+
+ PaynetEasyCC = function() {
+ };
+
+ PaynetEasyCC.prototype.getCreditCardNameByNumber = function(number) {
+ return this.findCreditCardObjectByNumber(number).name || 'Credit card is invalid!';
+ };
+
+ PaynetEasyCC.prototype.isSecurityCodeValid = function(creditCardNumber, securityCode) {
+ var numberLength = this.getCreditCardCodeLengthByNumber(creditCardNumber);
+ return new RegExp("^[0-9]{".concat(numberLength, "}$")).test(securityCode);
+ };
+
+ PaynetEasyCC.prototype.isExpirationDateValid = function(month, year) {
+ return this.isValidMonth(month) && this.isValidYear(year) && this.isFutureOrPresentDate(month, year);
+ };
+
+ PaynetEasyCC.prototype.isValid = function(number) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+ var cards = options.cards;
+ var rawNumber = this.removeNonNumbersCaracteres(number);
+ if (this.hasSomeInvalidDigit(number) || !this.hasCorrectLength(rawNumber)) {
+ return false;
+ }
+ var sum = this.sumNumber(rawNumber);
+ return this.checkSum(sum) && this.validateCardsWhenRequired(number, cards);
+ };
+
+ PaynetEasyCC.prototype.validateCardsWhenRequired = function(number, cards) {
+ return !cards || !cards.length || this.validateCards(number, cards);
+ };
+
+ PaynetEasyCC.prototype.validateCards = function(number, cards) {
+ return this.areCardsSupported(cards) && cards.map(function (c) {
+ return c.toLowerCase();
+ }).includes(this.getCreditCardNameByNumber(number).toLowerCase());
+ };
+
+ PaynetEasyCC.prototype.hasCorrectLength = function(number) {
+ return number && number.length <= 19;
+ };
+
+ PaynetEasyCC.prototype.removeNonNumbersCaracteres = function(number) {
+ return number.replace(/\D/g, '');
+ };
+
+ PaynetEasyCC.prototype.hasSomeInvalidDigit = function(creditcardNumber) {
+ var invalidDigits = new RegExp('[^0-9- ]');
+ return invalidDigits.test(creditcardNumber);
+ };
+
+ PaynetEasyCC.prototype.checkSum = function(sum) {
+ return sum > 0 && sum % 10 === 0;
+ };
+
+ PaynetEasyCC.prototype.areCardsSupported = function(passedCards) {
+ var supportedCards = PAYNETCARDS.map(function (c) {
+ return c.name.toLowerCase();
+ });
+ return passedCards.every(function (c) {
+ return supportedCards.includes(c.toLowerCase());
+ });
+ };
+
+ PaynetEasyCC.prototype.findCreditCardObjectByNumber = function(number) {
+ if (!number) return {};
+ var numberOnly = number.replace(/[^\d]/g, '');
+ return PAYNETCARDS.find(function (card) {
+ return card.bins.test(numberOnly) && card;
+ }) || {};
+ };
+
+ PaynetEasyCC.prototype.getCreditCardCodeLengthByNumber = function(number) {
+ return this.findCreditCardObjectByNumber(number).codeLength || PAYNET_DEFAULT_CODE_LENGTH;
+ };
+
+ PaynetEasyCC.prototype.isValidMonth = function(month) {
+ return !isNaN(month) && month >= 1 && month <= 12;
+ };
+
+ PaynetEasyCC.prototype.isValidYear = function(year) {
+ return !isNaN(year) && this.isValidFullYear(this.formatFullYear(year));
+ };
+
+ PaynetEasyCC.prototype.formatFullYear = function(year) {
+ if (year.length === 2) return this.dateRange(year);
+ return year.length === 4 ? year : 0;
+ };
+
+ PaynetEasyCC.prototype.dateRange = function() {
+ var increaseYear = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var year = parseInt(increaseYear);
+ var today = new Date();
+ return Math.floor(today.getFullYear() / PAYNETMILLENNIUM) * PAYNETMILLENNIUM + year;
+ };
+
+ PaynetEasyCC.prototype.isValidFullYear = function(year) {
+ return year >= this.dateRange() && year <= this.dateRange(PAYNETMILLENNIUM);
+ };
+
+ PaynetEasyCC.prototype.isFutureOrPresentDate = function(month, year) {
+ var fullYear = this.formatFullYear(year);
+ var currentDate = new Date();
+ var expirationDate = new Date();
+ currentDate.setFullYear(currentDate.getFullYear(), currentDate.getMonth(), 1);
+ expirationDate.setFullYear(fullYear, month - 1, 1);
+ return currentDate <= expirationDate;
+ };
+
+ PaynetEasyCC.prototype.sumNumber = function(number) {
+ var computed = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
+ var sum = 0;
+ var digit = 0;
+ var i = number.length;
+ var even = true;
+ while (i--) {
+ digit = Number(number[i]);
+ sum += (even = !even) ? computed[digit] : digit;
+ }
+ return sum;
+ };
\ No newline at end of file
diff --git a/source/payneteasy/logo/PaynetLogo.svg b/source/payneteasy/logo/PaynetLogo.svg
new file mode 100644
index 0000000..70af65c
--- /dev/null
+++ b/source/payneteasy/logo/PaynetLogo.svg
@@ -0,0 +1,20 @@
+
\ No newline at end of file