aboutsummaryrefslogtreecommitdiffstats
path: root/public/catalog/controller/extension
diff options
context:
space:
mode:
Diffstat (limited to 'public/catalog/controller/extension')
-rw-r--r--public/catalog/controller/extension/advertise/google.php380
-rw-r--r--public/catalog/controller/extension/analytics/google.php6
-rw-r--r--public/catalog/controller/extension/captcha/basic.php57
-rw-r--r--public/catalog/controller/extension/captcha/google.php38
-rw-r--r--public/catalog/controller/extension/credit_card/sagepay_direct.php273
-rw-r--r--public/catalog/controller/extension/credit_card/sagepay_server.php271
-rw-r--r--public/catalog/controller/extension/credit_card/squareup.php105
-rw-r--r--public/catalog/controller/extension/feed/google_base.php146
-rw-r--r--public/catalog/controller/extension/feed/google_sitemap.php107
-rw-r--r--public/catalog/controller/extension/module/account.php26
-rw-r--r--public/catalog/controller/extension/module/amazon_login.php172
-rw-r--r--public/catalog/controller/extension/module/amazon_pay.php52
-rw-r--r--public/catalog/controller/extension/module/banner.php31
-rw-r--r--public/catalog/controller/extension/module/bestseller.php62
-rw-r--r--public/catalog/controller/extension/module/carousel.php31
-rw-r--r--public/catalog/controller/extension/module/category.php64
-rw-r--r--public/catalog/controller/extension/module/divido_calculator.php53
-rw-r--r--public/catalog/controller/extension/module/ebay_listing.php42
-rw-r--r--public/catalog/controller/extension/module/featured.php72
-rw-r--r--public/catalog/controller/extension/module/filter.php74
-rw-r--r--public/catalog/controller/extension/module/google_hangouts.php14
-rw-r--r--public/catalog/controller/extension/module/html.php11
-rw-r--r--public/catalog/controller/extension/module/information.php22
-rw-r--r--public/catalog/controller/extension/module/klarna_checkout_module.php138
-rw-r--r--public/catalog/controller/extension/module/latest.php69
-rw-r--r--public/catalog/controller/extension/module/laybuy_layout.php38
-rw-r--r--public/catalog/controller/extension/module/pilibaba_button.php16
-rw-r--r--public/catalog/controller/extension/module/pp_braintree_button.php51
-rw-r--r--public/catalog/controller/extension/module/pp_button.php34
-rw-r--r--public/catalog/controller/extension/module/pp_login.php202
-rw-r--r--public/catalog/controller/extension/module/sagepay_direct_cards.php13
-rw-r--r--public/catalog/controller/extension/module/sagepay_server_cards.php13
-rw-r--r--public/catalog/controller/extension/module/slideshow.php31
-rw-r--r--public/catalog/controller/extension/module/special.php69
-rw-r--r--public/catalog/controller/extension/module/store.php40
-rw-r--r--public/catalog/controller/extension/openbay/amazon.php590
-rw-r--r--public/catalog/controller/extension/openbay/amazonus.php591
-rw-r--r--public/catalog/controller/extension/openbay/ebay.php201
-rw-r--r--public/catalog/controller/extension/openbay/etsy.php69
-rw-r--r--public/catalog/controller/extension/openbay/fba.php119
-rw-r--r--public/catalog/controller/extension/openbay/openbay.php12
-rw-r--r--public/catalog/controller/extension/payment/alipay.php76
-rw-r--r--public/catalog/controller/extension/payment/alipay_cross.php87
-rw-r--r--public/catalog/controller/extension/payment/amazon_login_pay.php690
-rw-r--r--public/catalog/controller/extension/payment/authorizenet_aim.php176
-rw-r--r--public/catalog/controller/extension/payment/authorizenet_sim.php141
-rw-r--r--public/catalog/controller/extension/payment/bank_transfer.php31
-rw-r--r--public/catalog/controller/extension/payment/bluepay_hosted.php95
-rw-r--r--public/catalog/controller/extension/payment/bluepay_redirect.php122
-rw-r--r--public/catalog/controller/extension/payment/cardconnect.php347
-rw-r--r--public/catalog/controller/extension/payment/cardinity.php294
-rw-r--r--public/catalog/controller/extension/payment/cheque.php34
-rw-r--r--public/catalog/controller/extension/payment/cod.php21
-rw-r--r--public/catalog/controller/extension/payment/divido.php301
-rw-r--r--public/catalog/controller/extension/payment/eway.php303
-rw-r--r--public/catalog/controller/extension/payment/firstdata.php243
-rw-r--r--public/catalog/controller/extension/payment/firstdata_remote.php138
-rw-r--r--public/catalog/controller/extension/payment/free_checkout.php16
-rw-r--r--public/catalog/controller/extension/payment/g2apay.php189
-rw-r--r--public/catalog/controller/extension/payment/globalpay.php252
-rw-r--r--public/catalog/controller/extension/payment/globalpay_remote.php335
-rw-r--r--public/catalog/controller/extension/payment/klarna_account.php687
-rw-r--r--public/catalog/controller/extension/payment/klarna_checkout.php1963
-rw-r--r--public/catalog/controller/extension/payment/klarna_invoice.php527
-rw-r--r--public/catalog/controller/extension/payment/laybuy.php478
-rw-r--r--public/catalog/controller/extension/payment/liqpay.php46
-rw-r--r--public/catalog/controller/extension/payment/nochex.php125
-rw-r--r--public/catalog/controller/extension/payment/paymate.php105
-rw-r--r--public/catalog/controller/extension/payment/paypoint.php161
-rw-r--r--public/catalog/controller/extension/payment/payza.php31
-rw-r--r--public/catalog/controller/extension/payment/perpetual_payments.php115
-rw-r--r--public/catalog/controller/extension/payment/pilibaba.php416
-rw-r--r--public/catalog/controller/extension/payment/pp_braintree.php1635
-rw-r--r--public/catalog/controller/extension/payment/pp_express.php1963
-rw-r--r--public/catalog/controller/extension/payment/pp_payflow.php191
-rw-r--r--public/catalog/controller/extension/payment/pp_payflow_iframe.php154
-rw-r--r--public/catalog/controller/extension/payment/pp_pro.php182
-rw-r--r--public/catalog/controller/extension/payment/pp_pro_iframe.php302
-rw-r--r--public/catalog/controller/extension/payment/pp_standard.php203
-rw-r--r--public/catalog/controller/extension/payment/realex.php258
-rw-r--r--public/catalog/controller/extension/payment/realex_remote.php349
-rw-r--r--public/catalog/controller/extension/payment/sagepay_direct.php470
-rw-r--r--public/catalog/controller/extension/payment/sagepay_server.php503
-rw-r--r--public/catalog/controller/extension/payment/sagepay_us.php95
-rw-r--r--public/catalog/controller/extension/payment/securetrading_pp.php170
-rw-r--r--public/catalog/controller/extension/payment/securetrading_ws.php359
-rw-r--r--public/catalog/controller/extension/payment/skrill.php106
-rw-r--r--public/catalog/controller/extension/payment/squareup.php251
-rw-r--r--public/catalog/controller/extension/payment/twocheckout.php114
-rw-r--r--public/catalog/controller/extension/payment/web_payment_software.php134
-rw-r--r--public/catalog/controller/extension/payment/wechat_pay.php134
-rw-r--r--public/catalog/controller/extension/payment/worldpay.php201
-rw-r--r--public/catalog/controller/extension/recurring/pp_express.php106
-rw-r--r--public/catalog/controller/extension/recurring/squareup.php170
-rw-r--r--public/catalog/controller/extension/total/coupon.php49
-rw-r--r--public/catalog/controller/extension/total/reward.php73
-rw-r--r--public/catalog/controller/extension/total/shipping.php211
-rw-r--r--public/catalog/controller/extension/total/voucher.php103
98 files changed, 21436 insertions, 0 deletions
diff --git a/public/catalog/controller/extension/advertise/google.php b/public/catalog/controller/extension/advertise/google.php
new file mode 100644
index 0000000..aa42410
--- /dev/null
+++ b/public/catalog/controller/extension/advertise/google.php
@@ -0,0 +1,380 @@
+<?php
+
+use \googleshopping\traits\StoreLoader;
+use \googleshopping\traits\LibraryLoader;
+
+class ControllerExtensionAdvertiseGoogle extends Controller {
+ use StoreLoader;
+ use LibraryLoader;
+
+ private $store_id = 0;
+
+ public function __construct($registry) {
+ parent::__construct($registry);
+
+ if (getenv("ADVERTISE_GOOGLE_STORE_ID")) {
+ $this->store_id = (int)getenv("ADVERTISE_GOOGLE_STORE_ID");
+ } else {
+ $this->store_id = (int)$this->config->get('config_store_id');
+ }
+
+ $this->loadStore($this->store_id);
+ }
+
+ public function google_global_site_tag(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If there is no tracker, do nothing
+ if (!$this->setting->has('advertise_google_conversion_tracker')) {
+ return;
+ }
+
+ $tracker = $this->setting->get('advertise_google_conversion_tracker');
+
+ // Insert the tags before the closing <head> tag
+ $output = str_replace('</head>', $tracker['google_global_site_tag'] . '</head>', $output);
+ }
+
+ public function before_checkout_success(&$route, &$data) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If there is no tracker, do nothing
+ if (!$this->setting->has('advertise_google_conversion_tracker')) {
+ return;
+ }
+
+ // In case there is no order, do nothing
+ if (!isset($this->session->data['order_id'])) {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/advertise/google');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $tracker = $this->setting->get('advertise_google_conversion_tracker');
+ $currency = $order_info['currency_code'];
+
+ $total = $this->googleshopping->convertAndFormat($order_info['total'], $currency);
+
+ $search = array(
+ '{VALUE}',
+ '{CURRENCY}'
+ );
+
+ $replace = array(
+ $total,
+ $currency
+ );
+
+ $snippet = str_replace($search, $replace, $tracker['google_event_snippet']);
+
+ // Store the snippet to display it in the order success view
+ $tax = 0;
+ $shipping = 0;
+ $coupon = $this->model_extension_advertise_google->getCoupon($order_info['order_id']);
+
+ foreach ($this->model_checkout_order->getOrderTotals($order_info['order_id']) as $order_total) {
+ if ($order_total['code'] == 'shipping') {
+ $shipping += $this->googleshopping->convertAndFormat($order_total['value'], $currency);
+ }
+
+ if ($order_total['code'] == 'tax') {
+ $tax += $this->googleshopping->convertAndFormat($order_total['value'], $currency);
+ }
+ }
+
+ $order_products = $this->model_checkout_order->getOrderProducts($order_info['order_id']);
+
+ foreach ($order_products as &$order_product) {
+ $order_product['option'] = $this->model_checkout_order->getOrderOptions($order_info['order_id'], $order_product['order_product_id']);
+ }
+
+ $purchase_data = array(
+ 'transaction_id' => $order_info['order_id'],
+ 'value' => $total,
+ 'currency' => $currency,
+ 'tax' => $tax,
+ 'shipping' => $shipping,
+ 'items' => $this->model_extension_advertise_google->getRemarketingItems($order_products, $order_info['store_id']),
+ 'ecomm_prodid' => $this->model_extension_advertise_google->getRemarketingProductIds($order_products, $order_info['store_id'])
+ );
+
+ if ($coupon !== null) {
+ $purchase_data['coupon'] = $coupon;
+ }
+
+ $this->googleshopping->setEventSnippet($snippet);
+ $this->googleshopping->setPurchaseData($purchase_data);
+ }
+
+ public function google_dynamic_remarketing_purchase(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If the library has not been loaded, or if there is no snippet, do nothing
+ if (!$this->registry->has('googleshopping') || $this->googleshopping->getEventSnippet() === null || $this->googleshopping->getPurchaseData() === null) {
+ return;
+ }
+
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+
+ $purchase_data = $this->googleshopping->getPurchaseData();
+
+ $data['transaction_id'] = $purchase_data['transaction_id'];
+ $data['value'] = $purchase_data['value'];
+ $data['currency'] = $purchase_data['currency'];
+ $data['tax'] = $purchase_data['tax'];
+ $data['shipping'] = $purchase_data['shipping'];
+ $data['items'] = json_encode($purchase_data['items']);
+ $data['ecomm_prodid'] = json_encode($purchase_data['ecomm_prodid']);
+ $data['ecomm_totalvalue'] = $purchase_data['value'];
+
+ $purchase_snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_purchase', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $this->googleshopping->getEventSnippet() . $purchase_snippet . '</body>', $output);
+ }
+
+ public function google_dynamic_remarketing_home(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If we are not on the home page, do nothing
+ if (isset($this->request->get['route']) && $this->request->get['route'] != $this->config->get('action_default')) {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ if (null === $this->googleshopping->getEventSnippetSendTo()) {
+ return;
+ }
+
+ $data = array();
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+
+ $snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_home', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $snippet . '</body>', $output);
+ }
+
+ public function google_dynamic_remarketing_searchresults(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If we are not on the search page, do nothing
+ if (!isset($this->request->get['route']) || $this->request->get['route'] != 'product/search' || !isset($this->request->get['search'])) {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ if (null === $this->googleshopping->getEventSnippetSendTo()) {
+ return;
+ }
+
+ $data = array();
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+ $data['search_term'] = $this->request->get['search'];
+
+ $snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_searchresults', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $snippet . '</body>', $output);
+ }
+
+ public function google_dynamic_remarketing_category(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If we are not on the search page, do nothing
+ if (!isset($this->request->get['route']) || $this->request->get['route'] != 'product/category') {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ if (null === $this->googleshopping->getEventSnippetSendTo()) {
+ return;
+ }
+
+ if (isset($this->request->get['path'])) {
+ $parts = explode('_', $this->request->get['path']);
+ $category_id = (int)end($parts);
+ } else if (isset($this->request->get['category_id'])) {
+ $category_id = (int)$this->request->get['category_id'];
+ } else {
+ $category_id = 0;
+ }
+
+ $this->load->model('extension/advertise/google');
+
+ $data = array();
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+ $data['description'] = str_replace('"', '\\"', $this->model_extension_advertise_google->getHumanReadableOpenCartCategory($category_id));
+
+ $snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_category', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $snippet . '</body>', $output);
+ }
+
+ public function google_dynamic_remarketing_product(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If we do not know the viewed product, do nothing
+ if (!isset($this->request->get['product_id']) || !isset($this->request->get['route']) || $this->request->get['route'] != 'product/product') {
+ return;
+ }
+
+ $this->load->model('catalog/product');
+
+ $product_info = $this->model_catalog_product->getProduct((int)$this->request->get['product_id']);
+
+ // If product does not exist, do nothing
+ if (!$product_info) {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ if (null === $this->googleshopping->getEventSnippetSendTo()) {
+ return;
+ }
+
+ $this->load->model('extension/advertise/google');
+
+ $category_name = $this->model_extension_advertise_google->getHumanReadableCategory($product_info['product_id'], $this->store_id);
+
+ $option_map = $this->model_extension_advertise_google->getSizeAndColorOptionMap($product_info['product_id'], $this->store_id);
+
+ $data = array();
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+ $data['option_map'] = json_encode($option_map);
+ $data['brand'] = $product_info['manufacturer'];
+ $data['name'] = $product_info['name'];
+ $data['category'] = str_replace('"', '\\"', $category_name);
+
+ $snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_product', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $snippet . '</body>', $output);
+ }
+
+ public function google_dynamic_remarketing_cart(&$route, &$data, &$output) {
+ // In case the extension is disabled, do nothing
+ if (!$this->setting->get('advertise_google_status')) {
+ return;
+ }
+
+ // If we are not on the cart page, do nothing
+ if (!isset($this->request->get['route']) || $this->request->get['route'] != 'checkout/cart') {
+ return;
+ }
+
+ if (!$this->registry->has('googleshopping')) {
+ $this->loadLibrary($this->store_id);
+ }
+
+ if (null === $this->googleshopping->getEventSnippetSendTo()) {
+ return;
+ }
+
+ $this->load->model('catalog/product');
+ $this->load->model('extension/advertise/google');
+
+ $data = array();
+ $data['send_to'] = $this->googleshopping->getEventSnippetSendTo();
+ $data['ecomm_totalvalue'] = $this->cart->getTotal();
+ $data['ecomm_prodid'] = json_encode($this->model_extension_advertise_google->getRemarketingProductIds($this->cart->getProducts(), $this->store_id));
+ $data['items'] = json_encode($this->model_extension_advertise_google->getRemarketingItems($this->cart->getProducts(), $this->store_id));
+
+ $snippet = $this->load->view('extension/advertise/google_dynamic_remarketing_cart', $data);
+
+ // Insert the snippet after the output
+ $output = str_replace('</body>', $snippet . '</body>', $output);
+ }
+
+ public function cron($cron_id = null, $code = null, $cycle = null, $date_added = null, $date_modified = null) {
+ $this->loadLibrary($this->store_id);
+
+ if (!$this->validateCRON()) {
+ // In case this is not a CRON task
+ return;
+ }
+
+ $this->load->language('extension/advertise/google');
+
+ // Reset taxes to use the store address and zone
+ $this->tax->setShippingAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ $this->tax->setPaymentAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ $this->googleshopping->cron();
+ }
+
+ protected function validateCRON() {
+ if (!$this->setting->get('advertise_google_status')) {
+ // In case the extension is disabled, do nothing
+ return false;
+ }
+
+ if (!$this->setting->get('advertise_google_gmc_account_selected')) {
+ return false;
+ }
+
+ if (!$this->setting->get('advertise_google_gmc_shipping_taxes_configured')) {
+ return false;
+ }
+
+ try {
+ if (count($this->googleshopping->getTargets($this->store_id)) === 0) {
+ return false;
+ }
+ } catch (\RuntimeException $e) {
+ return false;
+ }
+
+ if (isset($this->request->get['cron_token']) && $this->request->get['cron_token'] == $this->config->get('advertise_google_cron_token')) {
+ return true;
+ }
+
+ if (defined('ADVERTISE_GOOGLE_ROUTE')) {
+ return true;
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/analytics/google.php b/public/catalog/controller/extension/analytics/google.php
new file mode 100644
index 0000000..7bb3ddd
--- /dev/null
+++ b/public/catalog/controller/extension/analytics/google.php
@@ -0,0 +1,6 @@
+<?php
+class ControllerExtensionAnalyticsGoogle extends Controller {
+ public function index() {
+ return html_entity_decode($this->config->get('analytics_google_code'), ENT_QUOTES, 'UTF-8');
+ }
+}
diff --git a/public/catalog/controller/extension/captcha/basic.php b/public/catalog/controller/extension/captcha/basic.php
new file mode 100644
index 0000000..f0f3325
--- /dev/null
+++ b/public/catalog/controller/extension/captcha/basic.php
@@ -0,0 +1,57 @@
+<?php
+class ControllerExtensionCaptchaBasic extends Controller {
+ public function index($error = array()) {
+ $this->load->language('extension/captcha/basic');
+
+ if (isset($error['captcha'])) {
+ $data['error_captcha'] = $error['captcha'];
+ } else {
+ $data['error_captcha'] = '';
+ }
+
+ $data['route'] = $this->request->get['route'];
+
+ return $this->load->view('extension/captcha/basic', $data);
+ }
+
+ public function validate() {
+ $this->load->language('extension/captcha/basic');
+
+ if (empty($this->session->data['captcha']) || ($this->session->data['captcha'] != $this->request->post['captcha'])) {
+ return $this->language->get('error_captcha');
+ }
+ }
+
+ public function captcha() {
+ $this->session->data['captcha'] = substr(sha1(mt_rand()), 17, 6);
+
+ $image = imagecreatetruecolor(150, 35);
+
+ $width = imagesx($image);
+ $height = imagesy($image);
+
+ $black = imagecolorallocate($image, 0, 0, 0);
+ $white = imagecolorallocate($image, 255, 255, 255);
+ $red = imagecolorallocatealpha($image, 255, 0, 0, 75);
+ $green = imagecolorallocatealpha($image, 0, 255, 0, 75);
+ $blue = imagecolorallocatealpha($image, 0, 0, 255, 75);
+
+ imagefilledrectangle($image, 0, 0, $width, $height, $white);
+ imagefilledellipse($image, ceil(rand(5, 145)), ceil(rand(0, 35)), 30, 30, $red);
+ imagefilledellipse($image, ceil(rand(5, 145)), ceil(rand(0, 35)), 30, 30, $green);
+ imagefilledellipse($image, ceil(rand(5, 145)), ceil(rand(0, 35)), 30, 30, $blue);
+ imagefilledrectangle($image, 0, 0, $width, 0, $black);
+ imagefilledrectangle($image, $width - 1, 0, $width - 1, $height - 1, $black);
+ imagefilledrectangle($image, 0, 0, 0, $height - 1, $black);
+ imagefilledrectangle($image, 0, $height - 1, $width, $height - 1, $black);
+
+ imagestring($image, 10, intval(($width - (strlen($this->session->data['captcha']) * 9)) / 2), intval(($height - 15) / 2), $this->session->data['captcha'], $black);
+
+ header('Content-type: image/jpeg');
+
+ imagejpeg($image);
+
+ imagedestroy($image);
+ exit();
+ }
+}
diff --git a/public/catalog/controller/extension/captcha/google.php b/public/catalog/controller/extension/captcha/google.php
new file mode 100644
index 0000000..ee2e60c
--- /dev/null
+++ b/public/catalog/controller/extension/captcha/google.php
@@ -0,0 +1,38 @@
+<?php
+class ControllerExtensionCaptchaGoogle extends Controller {
+ public function index($error = array()) {
+ $this->load->language('extension/captcha/google');
+
+ if (isset($error['captcha'])) {
+ $data['error_captcha'] = $error['captcha'];
+ } else {
+ $data['error_captcha'] = '';
+ }
+
+ $data['site_key'] = $this->config->get('captcha_google_key');
+
+ $data['route'] = $this->request->get['route'];
+
+ return $this->load->view('extension/captcha/google', $data);
+ }
+
+ public function validate() {
+ if (empty($this->session->data['gcapcha'])) {
+ $this->load->language('extension/captcha/google');
+
+ if (!isset($this->request->post['g-recaptcha-response'])) {
+ return $this->language->get('error_captcha');
+ }
+
+ $recaptcha = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($this->config->get('captcha_google_secret')) . '&response=' . $this->request->post['g-recaptcha-response'] . '&remoteip=' . $this->request->server['REMOTE_ADDR']);
+
+ $recaptcha = json_decode($recaptcha, true);
+
+ if ($recaptcha['success']) {
+ $this->session->data['gcapcha'] = true;
+ } else {
+ return $this->language->get('error_captcha');
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/credit_card/sagepay_direct.php b/public/catalog/controller/extension/credit_card/sagepay_direct.php
new file mode 100644
index 0000000..f982148
--- /dev/null
+++ b/public/catalog/controller/extension/credit_card/sagepay_direct.php
@@ -0,0 +1,273 @@
+<?php
+class ControllerExtensionCreditCardSagepayDirect extends Controller {
+ public function index() {
+ if (!$this->customer->isLogged()) {
+ $this->session->data['redirect'] = $this->url->link('account/account', '', true);
+
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+
+ $this->load->language('extension/credit_card/sagepay_direct');
+
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_account'),
+ 'href' => $this->url->link('account/account', '', true)
+ );
+
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ if (isset($this->session->data['error_warning'])) {
+ $data['error_warning'] = $this->session->data['error_warning'];
+ unset($this->session->data['error_warning']);
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ if ($this->config->get('payment_sagepay_direct_card')) {
+ $data['cards'] = $this->model_extension_payment_sagepay_direct->getCards($this->customer->getId());
+ $data['delete'] = $this->url->link('extension/credit_card/sagepay_direct/delete', 'card_id=', true);
+
+ if (isset($this->request->get['page'])) {
+ $page = $this->request->get['page'];
+ } else {
+ $page = 1;
+ }
+
+ $cards_total = count($data['cards']);
+
+ $pagination = new Pagination();
+ $pagination->total = $cards_total;
+ $pagination->page = $page;
+ $pagination->limit = 10;
+ $pagination->url = $this->url->link('extension/credit_card/sagepay_direct', 'page={page}', true);
+
+ $data['pagination'] = $pagination->render();
+
+ $data['results'] = sprintf($this->language->get('text_pagination'), ($cards_total) ? (($page - 1) * 10) + 1 : 0, ((($page - 1) * 10) > ($cards_total - 10)) ? $cards_total : ((($page - 1) * 10) + 10), $cards_total, ceil($cards_total / 10));
+ } else {
+ $data['cards'] = false;
+ $data['pagination'] = false;
+ $data['results'] = false;
+ }
+
+ $data['back'] = $this->url->link('account/account', '', true);
+ $data['add'] = $this->url->link('extension/credit_card/sagepay_direct/add', '', true);
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/credit_card/sagepay_direct_list', $data));
+ }
+
+ public function add() {
+ if (!$this->customer->isLogged()) {
+ $this->session->data['redirect'] = $this->url->link('account/account', '', true);
+
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+
+ $this->load->language('extension/credit_card/sagepay_direct');
+
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_account'),
+ 'href' => $this->url->link('account/account', '', true)
+ );
+
+ $data['add'] = $this->url->link('extension/credit_card/sagepay_direct/addCard', '', true);
+ $data['back'] = $this->url->link('extension/credit_card/sagepay_direct', '', true);
+
+ $data['cards'] = array();
+
+ $data['cards'][] = array(
+ 'text' => 'Visa',
+ 'value' => 'VISA'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'MasterCard',
+ 'value' => 'MC'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Visa Delta/Debit',
+ 'value' => 'DELTA'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Solo',
+ 'value' => 'SOLO'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Maestro',
+ 'value' => 'MAESTRO'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Visa Electron UK Debit',
+ 'value' => 'UKE'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'American Express',
+ 'value' => 'AMEX'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Diners Club',
+ 'value' => 'DC'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Japan Credit Bureau',
+ 'value' => 'JCB'
+ );
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_valid'] = array();
+
+ for ($i = $today['year'] - 10; $i < $today['year'] + 1; $i++) {
+ $data['year_valid'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/credit_card/sagepay_direct_form', $data));
+ }
+
+ public function delete() {
+ $this->load->language('extension/credit_card/sagepay_direct');
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $card = $this->model_extension_payment_sagepay_direct->getCard($this->request->get['card_id'], false);
+
+ if (!empty($card['token'])) {
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/removetoken.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/removetoken.vsp';
+ }
+
+ $payment_data['VPSProtocol'] = '3.00';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $payment_data['TxType'] = 'REMOVETOKEN';
+ $payment_data['Token'] = $card['token'];
+
+ $response_data = $this->model_extension_payment_sagepay_direct->sendCurl($url, $payment_data);
+
+ if ($response_data['Status'] == 'OK') {
+ $this->model_extension_payment_sagepay_direct->deleteCard($this->request->get['card_id']);
+
+ $this->session->data['success'] = $this->language->get('text_success_card');
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('text_fail_card');
+ }
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('text_fail_card');
+ }
+
+ $this->response->redirect($this->url->link('acredit_card/sagepay_direct', '', true));
+ }
+
+ public function addCard() {
+ $this->load->language('extension/credit_card/sagepay_direct');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $payment_data = array();
+
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/directtoken.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/directtoken.vsp';
+ }
+ $payment_data['VPSProtocol'] = '3.00';
+
+ $payment_data['ReferrerID'] = 'E511AF91-E4A0-42DE-80B0-09C981A3FB61';
+ $payment_data['TxType'] = 'TOKEN';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $payment_data['Currency'] = $this->session->data['currency'];
+ $payment_data['CardHolder'] = $this->request->post['cc_owner'];
+ $payment_data['CardNumber'] = $this->request->post['cc_number'];
+ $payment_data['ExpiryDate'] = $this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], 2);
+ $payment_data['CV2'] = $this->request->post['cc_cvv2'];
+ $payment_data['CardType'] = $this->request->post['cc_type'];
+
+ $response_data = $this->model_extension_payment_sagepay_direct->sendCurl($url, $payment_data);
+
+ if ($response_data['Status'] == 'OK') {
+ $card_data = array();
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Token'] = $response_data['Token'];
+ $card_data['Last4Digits'] = substr(str_replace(' ', '', $payment_data['CardNumber']), -4, 4);
+ $card_data['ExpiryDate'] = $this->request->post['cc_expire_date_month'] . '/' . substr($this->request->post['cc_expire_date_year'], 2);
+ $card_data['CardType'] = $payment_data['CardType'];
+ $this->model_extension_payment_sagepay_direct->addCard($card_data);
+ $this->session->data['success'] = $this->language->get('text_success_add_card');
+ } else {
+ $this->session->data['error_warning'] = $response_data['Status'] . ': ' . $response_data['StatusDetail'];
+ $this->model_extension_payment_sagepay_direct->logger('Response data: ', $this->session->data['error_warning']);
+ }
+
+ $this->response->redirect($this->url->link('extension/credit_card/sagepay_direct', '', true));
+ }
+}
diff --git a/public/catalog/controller/extension/credit_card/sagepay_server.php b/public/catalog/controller/extension/credit_card/sagepay_server.php
new file mode 100644
index 0000000..0e9f43a
--- /dev/null
+++ b/public/catalog/controller/extension/credit_card/sagepay_server.php
@@ -0,0 +1,271 @@
+<?php
+class ControllerExtensionCreditCardSagepayServer extends Controller {
+ public function index() {
+ if (!$this->customer->isLogged()) {
+ $this->session->data['redirect'] = $this->url->link('account/account', '', true);
+
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+
+ $this->load->language('extension/credit_card/sagepay_server');
+
+ $this->load->model('extension/payment/sagepay_server');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_account'),
+ 'href' => $this->url->link('account/account', '', true)
+ );
+
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ if (isset($this->session->data['error_warning'])) {
+ $data['error_warning'] = $this->session->data['error_warning'];
+ unset($this->session->data['error_warning']);
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ if ($this->config->get('payment_sagepay_server_card')) {
+ $data['cards'] = $this->model_extension_payment_sagepay_server->getCards($this->customer->getId());
+ $data['delete'] = $this->url->link('extension/credit_card/sagepay_server/delete', 'card_id=', true);
+
+ if (isset($this->request->get['page'])) {
+ $page = $this->request->get['page'];
+ } else {
+ $page = 1;
+ }
+
+ $cards_total = count($data['cards']);
+
+ $pagination = new Pagination();
+ $pagination->total = $cards_total;
+ $pagination->page = $page;
+ $pagination->limit = 10;
+ $pagination->url = $this->url->link('extension/credit_card/sagepay_server', 'page={page}', true);
+
+ $data['pagination'] = $pagination->render();
+
+ $data['results'] = sprintf($this->language->get('text_pagination'), ($cards_total) ? (($page - 1) * 10) + 1 : 0, ((($page - 1) * 10) > ($cards_total - 10)) ? $cards_total : ((($page - 1) * 10) + 10), $cards_total, ceil($cards_total / 10));
+ } else {
+ $data['cards'] = false;
+ $data['pagination'] = false;
+ $data['results'] = false;
+ }
+
+ $data['add'] = $this->url->link('extension/credit_card/sagepay_server/add', '', true);
+ $data['back'] = $this->url->link('account/account', '', true);
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/credit_card/sagepay_server_list', $data));
+ }
+
+ public function delete() {
+ $this->load->language('extension/credit_card/sagepay_server');
+
+ $this->load->model('extension/payment/sagepay_server');
+
+ $card = $this->model_extension_payment_sagepay_server->getCard($this->request->get['card_id'], '');
+
+ if (!empty($card['token'])) {
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/removetoken.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/removetoken.vsp';
+ }
+
+ $payment_data['VPSProtocol'] = '3.00';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $payment_data['TxType'] = 'REMOVETOKEN';
+ $payment_data['Token'] = $card['token'];
+
+ $response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
+
+ if ($response_data['Status'] == 'OK') {
+ $this->model_extension_payment_sagepay_server->deleteCard($this->request->get['card_id']);
+ $this->session->data['success'] = $this->language->get('text_success_card');
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('text_fail_card');
+ }
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('text_fail_card');
+ }
+ $this->response->redirect($this->url->link('extension/credit_card/sagepay_server', '', true));
+ }
+
+ public function addCard() {
+ $this->load->language('extension/payment/sagepay_server');
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_server');
+
+ $payment_data = array();
+
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/token.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/token.vsp';
+ }
+ $payment_data['VPSProtocol'] = '3.00';
+
+ $payment_data['ReferrerID'] = 'E511AF91-E4A0-42DE-80B0-09C981A3FB61';
+ $payment_data['TxType'] = 'TOKEN';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $payment_data['VendorTxCode'] = 'server_card_' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
+ $payment_data['NotificationURL'] = $this->url->link('extension/credit_card/sagepay_server/callback', '', true);
+ $payment_data['Currency'] = $this->session->data['currency'];
+
+ $response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
+
+ $this->model_extension_payment_sagepay_server->logger('Response', $response_data);
+
+ if ($response_data['Status'] == 'OK') {
+ $json['redirect'] = $response_data['NextURL'];
+ $json['Status'] = $response_data['Status'];
+ $json['StatusDetail'] = $response_data['StatusDetail'];
+
+ $order_info['order_id'] = -1;
+ $order_info['VPSTxId'] = substr($response_data['VPSTxId'], 1, -1);
+ $order_info['SecurityKey'] = $response_data['SecurityKey'];
+ $order_info['VendorTxCode'] = $payment_data['VendorTxCode'];
+ $order_info['currency_code'] = $this->session->data['currency'];
+ $order_info['total'] = '';
+ $this->model_extension_payment_sagepay_server->addOrder($order_info);
+ } else {
+ $json['error'] = $response_data['StatusDetail'];
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function callback() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_server');
+
+ $this->model_extension_payment_sagepay_server->logger('Callback data', $this->request->post);
+
+ $success_page = $this->url->link('extension/credit_card/sagepay_server/success', '', true);
+ $error_page = $this->url->link('extension/credit_card/sagepay_server/failure', '', true);
+ $end_ln = chr(13) . chr(10);
+
+ if (isset($this->request->post['VendorTxCode'])) {
+ $vendor_tx_code = $this->request->post['VendorTxCode'];
+ } else {
+ $vendor_tx_code = '';
+ }
+
+ if (isset($this->request->post['Status'])) {
+ $str_status = $this->request->post['Status'];
+ } else {
+ $str_status = '';
+ }
+
+ if (isset($this->request->post['VPSSignature'])) {
+ $str_vps_signature = $this->request->post['VPSSignature'];
+ } else {
+ $str_vps_signature = '';
+ }
+
+ if (isset($this->request->post['VPSTxId'])) {
+ $str_vps_tx_id = $this->request->post['VPSTxId'];
+ } else {
+ $str_vps_tx_id = '';
+ }
+
+ if (isset($this->request->post['ExpiryDate'])) {
+ $str_expiry_date = $this->request->post['ExpiryDate'];
+ } else {
+ $str_expiry_date = '';
+ }
+
+ if (isset($this->request->post['Token'])) {
+ $str_token = $this->request->post['Token'];
+ } else {
+ $str_token = '';
+ }
+
+ $transaction_info = $this->model_extension_payment_sagepay_server->getOrder('', $str_vps_tx_id);
+
+ if (isset($transaction_info['SecurityKey'])) {
+ $str_security_key = $transaction_info['SecurityKey'];
+ } else {
+ $str_security_key = '';
+ }
+ $this->model_extension_payment_sagepay_server->logger('$transaction_info', $transaction_info);
+ $this->model_extension_payment_sagepay_server->logger('$str_vps_tx_id', $str_vps_tx_id);
+ $this->model_extension_payment_sagepay_server->logger('$vendor_tx_code', $vendor_tx_code);
+ $this->model_extension_payment_sagepay_server->logger('$str_status', $str_status);
+ $this->model_extension_payment_sagepay_server->logger('payment_sagepay_server_vendor', $this->config->get('payment_sagepay_server_vendor'));
+ $this->model_extension_payment_sagepay_server->logger('$str_token', $str_token);
+ $this->model_extension_payment_sagepay_server->logger('$str_security_key', $str_security_key);
+
+ $str_message = $str_vps_tx_id . $vendor_tx_code . $str_status . strtolower($this->config->get('payment_sagepay_server_vendor')) . $str_token . $str_security_key;
+
+ $str_my_signature = strtoupper(md5($str_message));
+
+ /** We can now compare our MD5 Hash signature with that from Sage Pay Server * */
+ if ($str_my_signature != $str_vps_signature) {
+
+ echo "Status=INVALID" . $end_ln;
+ echo "StatusDetail= Cannot match the MD5 Hash. Order might be tampered with." . $end_ln;
+ echo "RedirectURL=" . $error_page . $end_ln;
+ $this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Cannot match the MD5 Hash. Order might be tampered with.');
+ exit;
+ }
+
+ if ($str_status != "OK") {
+ echo "Status=INVALID" . $end_ln;
+ echo "StatusDetail= Either status invalid or order info was not found.";
+ echo "RedirectURL=" . $error_page . $end_ln;
+
+ $this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Either status invalid or order info was not found.');
+
+ exit;
+ }
+
+ $card_data['customer_id'] = $transaction_info['customer_id'];
+ $card_data['Token'] = $this->request->post['Token'];
+ $card_data['Last4Digits'] = $this->request->post['Last4Digits'];
+ $card_data['ExpiryDate'] = substr_replace($this->request->post['ExpiryDate'], '/', 2, 0);
+ $card_data['CardType'] = $this->request->post['CardType'];
+ $this->model_extension_payment_sagepay_server->addCard($card_data);
+
+ echo "Status=OK" . $end_ln;
+ echo "RedirectURL=" . $success_page . $end_ln;
+ }
+
+ public function success() {
+ $this->load->model('extension/payment/sagepay_server');
+ $this->model_extension_payment_sagepay_server->logger('Success', '');
+ $this->session->data['success'] = 'Success';
+ $this->response->redirect($this->url->link('extension/credit_card/sagepay_server', '', true));
+ }
+
+ public function failure() {
+ $this->load->model('extension/payment/sagepay_server');
+ $this->model_extension_payment_sagepay_server->logger('Failure', '');
+ $this->session->data['error_warning'] = 'Failure';
+ $this->response->redirect($this->url->link('extension/credit_card/sagepay_server', '', true));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/credit_card/squareup.php b/public/catalog/controller/extension/credit_card/squareup.php
new file mode 100644
index 0000000..7350d74
--- /dev/null
+++ b/public/catalog/controller/extension/credit_card/squareup.php
@@ -0,0 +1,105 @@
+<?php
+
+class ControllerExtensionCreditCardSquareup extends Controller {
+ public function index() {
+ if (!$this->customer->isLogged()) {
+ $this->session->data['redirect'] = $this->url->link('account/account', '', true);
+
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+
+ $this->load->language('extension/credit_card/squareup');
+
+ $this->load->model('extension/credit_card/squareup');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_account'),
+ 'href' => $this->url->link('account/account', '', true)
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('heading_title'),
+ 'href' => $this->url->link('extension/credit_card/squareup', '', true)
+ );
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ if (isset($this->session->data['error'])) {
+ $data['error'] = $this->session->data['error'];
+
+ unset($this->session->data['error']);
+ } else {
+ $data['error'] = '';
+ }
+
+ $data['back'] = $this->url->link('account/account', '', true);
+
+ $data['cards'] = array();
+
+ foreach ($this->model_extension_credit_card_squareup->getCards($this->customer->getId(), $this->config->get('payment_squareup_enable_sandbox')) as $card) {
+ $data['cards'][] = array(
+ 'text' => sprintf($this->language->get('text_card_ends_in'), $card['brand'], $card['ends_in']),
+ 'delete' => $this->url->link('extension/credit_card/squareup/forget', 'squareup_token_id=' . $card['squareup_token_id'], true)
+ );
+ }
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/credit_card/squareup', $data));
+ }
+
+ public function forget() {
+ if (!$this->customer->isLogged()) {
+ $this->session->data['redirect'] = $this->url->link('account/account', '', true);
+
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+
+ $this->load->language('extension/credit_card/squareup');
+
+ $this->load->model('extension/credit_card/squareup');
+
+ $this->load->library('squareup');
+
+ $squareup_token_id = !empty($this->request->get['squareup_token_id']) ?
+ $this->request->get['squareup_token_id'] : 0;
+
+ if ($this->model_extension_credit_card_squareup->verifyCardCustomer($squareup_token_id, $this->customer->getId())) {
+ $card_info = $this->model_extension_credit_card_squareup->getCard($squareup_token_id);
+
+ $customer_info = $this->model_extension_credit_card_squareup->getCustomer($this->customer->getId(), $card_info['sandbox']);
+
+ try {
+ $this->squareup->deleteCard($customer_info['square_customer_id'], $card_info['token']);
+
+ $this->model_extension_credit_card_squareup->deleteCard($squareup_token_id);
+
+ $this->session->data['success'] = $this->language->get('text_success_card_delete');
+ } catch (\Squareup\Exception $e) {
+ $this->session->data['error'] = $e->getMessage();
+ }
+ }
+
+ $this->response->redirect($this->url->link('extension/credit_card/squareup', '', true));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/feed/google_base.php b/public/catalog/controller/extension/feed/google_base.php
new file mode 100644
index 0000000..a6bd427
--- /dev/null
+++ b/public/catalog/controller/extension/feed/google_base.php
@@ -0,0 +1,146 @@
+<?php
+class ControllerExtensionFeedGoogleBase extends Controller {
+ public function index() {
+ if ($this->config->get('feed_google_base_status')) {
+ $output = '<?xml version="1.0" encoding="UTF-8" ?>';
+ $output .= '<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">';
+ $output .= ' <channel>';
+ $output .= ' <title>' . $this->config->get('config_name') . '</title>';
+ $output .= ' <description>' . $this->config->get('config_meta_description') . '</description>';
+ $output .= ' <link>' . $this->config->get('config_url') . '</link>';
+
+ $this->load->model('extension/feed/google_base');
+ $this->load->model('catalog/category');
+ $this->load->model('catalog/product');
+
+ $this->load->model('tool/image');
+
+ $product_data = array();
+
+ $google_base_categories = $this->model_extension_feed_google_base->getCategories();
+
+ foreach ($google_base_categories as $google_base_category) {
+ $filter_data = array(
+ 'filter_category_id' => $google_base_category['category_id'],
+ 'filter_filter' => false
+ );
+
+ $products = $this->model_catalog_product->getProducts($filter_data);
+
+ foreach ($products as $product) {
+ if (!in_array($product['product_id'], $product_data) && $product['description']) {
+
+ $product_data[] = $product['product_id'];
+
+ $output .= '<item>';
+ $output .= '<title><![CDATA[' . $product['name'] . ']]></title>';
+ $output .= '<link>' . $this->url->link('product/product', 'product_id=' . $product['product_id']) . '</link>';
+ $output .= '<description><![CDATA[' . strip_tags(html_entity_decode($product['description'], ENT_QUOTES, 'UTF-8')) . ']]></description>';
+ $output .= '<g:brand><![CDATA[' . html_entity_decode($product['manufacturer'], ENT_QUOTES, 'UTF-8') . ']]></g:brand>';
+ $output .= '<g:condition>new</g:condition>';
+ $output .= '<g:id>' . $product['product_id'] . '</g:id>';
+
+ if ($product['image']) {
+ $output .= ' <g:image_link>' . $this->model_tool_image->resize($product['image'], 500, 500) . '</g:image_link>';
+ } else {
+ $output .= ' <g:image_link></g:image_link>';
+ }
+
+ $output .= ' <g:model_number>' . $product['model'] . '</g:model_number>';
+
+ if ($product['mpn']) {
+ $output .= ' <g:mpn><![CDATA[' . $product['mpn'] . ']]></g:mpn>' ;
+ } else {
+ $output .= ' <g:identifier_exists>false</g:identifier_exists>';
+ }
+
+ if ($product['upc']) {
+ $output .= ' <g:upc>' . $product['upc'] . '</g:upc>';
+ }
+
+ if ($product['ean']) {
+ $output .= ' <g:ean>' . $product['ean'] . '</g:ean>';
+ }
+
+ $currencies = array(
+ 'USD',
+ 'EUR',
+ 'GBP'
+ );
+
+ if (in_array($this->session->data['currency'], $currencies)) {
+ $currency_code = $this->session->data['currency'];
+ $currency_value = $this->currency->getValue($this->session->data['currency']);
+ } else {
+ $currency_code = 'USD';
+ $currency_value = $this->currency->getValue('USD');
+ }
+
+ if ((float)$product['special']) {
+ $output .= ' <g:price>' . $this->currency->format($this->tax->calculate($product['special'], $product['tax_class_id']), $currency_code, $currency_value, false) . '</g:price>';
+ } else {
+ $output .= ' <g:price>' . $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id']), $currency_code, $currency_value, false) . '</g:price>';
+ }
+
+ $output .= ' <g:google_product_category>' . $google_base_category['google_base_category_id'] . '</g:google_product_category>';
+
+ $categories = $this->model_catalog_product->getCategories($product['product_id']);
+
+ foreach ($categories as $category) {
+ $path = $this->getPath($category['category_id']);
+
+ if ($path) {
+ $string = '';
+
+ foreach (explode('_', $path) as $path_id) {
+ $category_info = $this->model_catalog_category->getCategory($path_id);
+
+ if ($category_info) {
+ if (!$string) {
+ $string = $category_info['name'];
+ } else {
+ $string .= ' &gt; ' . $category_info['name'];
+ }
+ }
+ }
+
+ $output .= '<g:product_type><![CDATA[' . $string . ']]></g:product_type>';
+ }
+ }
+
+ $output .= ' <g:quantity>' . $product['quantity'] . '</g:quantity>';
+ $output .= ' <g:weight>' . $this->weight->format($product['weight'], $product['weight_class_id']) . '</g:weight>';
+ $output .= ' <g:availability><![CDATA[' . ($product['quantity'] ? 'in stock' : 'out of stock') . ']]></g:availability>';
+ $output .= '</item>';
+ }
+ }
+ }
+
+ $output .= ' </channel>';
+ $output .= '</rss>';
+
+ $this->response->addHeader('Content-Type: application/rss+xml');
+ $this->response->setOutput($output);
+ }
+ }
+
+ protected function getPath($parent_id, $current_path = '') {
+ $category_info = $this->model_catalog_category->getCategory($parent_id);
+
+ if ($category_info) {
+ if (!$current_path) {
+ $new_path = $category_info['category_id'];
+ } else {
+ $new_path = $category_info['category_id'] . '_' . $current_path;
+ }
+
+ $path = $this->getPath($category_info['parent_id'], $new_path);
+
+ if ($path) {
+ return $path;
+ } else {
+ return $new_path;
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/feed/google_sitemap.php b/public/catalog/controller/extension/feed/google_sitemap.php
new file mode 100644
index 0000000..7cb7d37
--- /dev/null
+++ b/public/catalog/controller/extension/feed/google_sitemap.php
@@ -0,0 +1,107 @@
+<?php
+class ControllerExtensionFeedGoogleSitemap extends Controller {
+ public function index() {
+ if ($this->config->get('feed_google_sitemap_status')) {
+ $output = '<?xml version="1.0" encoding="UTF-8"?>';
+ $output .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">';
+
+ $this->load->model('catalog/product');
+ $this->load->model('tool/image');
+
+ $products = $this->model_catalog_product->getProducts();
+
+ foreach ($products as $product) {
+ if ($product['image']) {
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('product/product', 'product_id=' . $product['product_id']) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <lastmod>' . date('Y-m-d\TH:i:sP', strtotime($product['date_modified'])) . '</lastmod>';
+ $output .= ' <priority>1.0</priority>';
+ $output .= ' <image:image>';
+ $output .= ' <image:loc>' . $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_popup_height')) . '</image:loc>';
+ $output .= ' <image:caption>' . $product['name'] . '</image:caption>';
+ $output .= ' <image:title>' . $product['name'] . '</image:title>';
+ $output .= ' </image:image>';
+ $output .= '</url>';
+ }
+ }
+
+ $this->load->model('catalog/category');
+
+ $output .= $this->getCategories(0);
+
+ $this->load->model('catalog/manufacturer');
+
+ $manufacturers = $this->model_catalog_manufacturer->getManufacturers();
+
+ foreach ($manufacturers as $manufacturer) {
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('product/manufacturer/info', 'manufacturer_id=' . $manufacturer['manufacturer_id']) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <priority>0.7</priority>';
+ $output .= '</url>';
+
+ $products = $this->model_catalog_product->getProducts(array('filter_manufacturer_id' => $manufacturer['manufacturer_id']));
+
+ foreach ($products as $product) {
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('product/product', 'manufacturer_id=' . $manufacturer['manufacturer_id'] . '&product_id=' . $product['product_id']) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <priority>1.0</priority>';
+ $output .= '</url>';
+ }
+ }
+
+ $this->load->model('catalog/information');
+
+ $informations = $this->model_catalog_information->getInformations();
+
+ foreach ($informations as $information) {
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('information/information', 'information_id=' . $information['information_id']) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <priority>0.5</priority>';
+ $output .= '</url>';
+ }
+
+ $output .= '</urlset>';
+
+ $this->response->addHeader('Content-Type: application/xml');
+ $this->response->setOutput($output);
+ }
+ }
+
+ protected function getCategories($parent_id, $current_path = '') {
+ $output = '';
+
+ $results = $this->model_catalog_category->getCategories($parent_id);
+
+ foreach ($results as $result) {
+ if (!$current_path) {
+ $new_path = $result['category_id'];
+ } else {
+ $new_path = $current_path . '_' . $result['category_id'];
+ }
+
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('product/category', 'path=' . $new_path) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <priority>0.7</priority>';
+ $output .= '</url>';
+
+ $products = $this->model_catalog_product->getProducts(array('filter_category_id' => $result['category_id']));
+
+ foreach ($products as $product) {
+ $output .= '<url>';
+ $output .= ' <loc>' . $this->url->link('product/product', 'path=' . $new_path . '&product_id=' . $product['product_id']) . '</loc>';
+ $output .= ' <changefreq>weekly</changefreq>';
+ $output .= ' <priority>1.0</priority>';
+ $output .= '</url>';
+ }
+
+ $output .= $this->getCategories($result['category_id'], $new_path);
+ }
+
+ return $output;
+ }
+}
diff --git a/public/catalog/controller/extension/module/account.php b/public/catalog/controller/extension/module/account.php
new file mode 100644
index 0000000..333b9a1
--- /dev/null
+++ b/public/catalog/controller/extension/module/account.php
@@ -0,0 +1,26 @@
+<?php
+class ControllerExtensionModuleAccount extends Controller {
+ public function index() {
+ $this->load->language('extension/module/account');
+
+ $data['logged'] = $this->customer->isLogged();
+ $data['register'] = $this->url->link('account/register', '', true);
+ $data['login'] = $this->url->link('account/login', '', true);
+ $data['logout'] = $this->url->link('account/logout', '', true);
+ $data['forgotten'] = $this->url->link('account/forgotten', '', true);
+ $data['account'] = $this->url->link('account/account', '', true);
+ $data['edit'] = $this->url->link('account/edit', '', true);
+ $data['password'] = $this->url->link('account/password', '', true);
+ $data['address'] = $this->url->link('account/address', '', true);
+ $data['wishlist'] = $this->url->link('account/wishlist');
+ $data['order'] = $this->url->link('account/order', '', true);
+ $data['download'] = $this->url->link('account/download', '', true);
+ $data['reward'] = $this->url->link('account/reward', '', true);
+ $data['return'] = $this->url->link('account/return', '', true);
+ $data['transaction'] = $this->url->link('account/transaction', '', true);
+ $data['newsletter'] = $this->url->link('account/newsletter', '', true);
+ $data['recurring'] = $this->url->link('account/recurring', '', true);
+
+ return $this->load->view('extension/module/account', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/amazon_login.php b/public/catalog/controller/extension/module/amazon_login.php
new file mode 100644
index 0000000..9b8ae65
--- /dev/null
+++ b/public/catalog/controller/extension/module/amazon_login.php
@@ -0,0 +1,172 @@
+<?php
+
+class ControllerExtensionModuleAmazonLogin extends Controller {
+ public function index() {
+ if ($this->config->get('payment_amazon_login_pay_status') && $this->config->get('module_amazon_login_status') && !$this->customer->isLogged() && !empty($this->request->server['HTTPS'])) {
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ // capital L in Amazon cookie name is required, do not alter for coding standards
+ if (isset($this->request->cookie['amazon_Login_state_cache'])) {
+ setcookie('amazon_Login_state_cache', null, -1, '/');
+ }
+
+ $amazon_payment_js = $this->model_extension_payment_amazon_login_pay->getWidgetJs();
+
+ $this->document->addScript($amazon_payment_js);
+
+ $data['client_id'] = trim($this->config->get('payment_amazon_login_pay_client_id'));
+ $data['merchant_id'] = $this->config->get('payment_amazon_login_pay_merchant_id');
+ $data['return_url'] = html_entity_decode($this->url->link('extension/module/amazon_login/login', '', true), ENT_COMPAT, "UTF-8");
+ $data['button_id'] = 'AmazonLoginButton';
+
+ if ($this->config->get('payment_amazon_login_pay_test') == 'sandbox') {
+ $data['sandbox'] = isset($this->session->data['user_id']); // Require an active admin panel session to show debug messages
+ }
+
+ if ($this->config->get('module_amazon_login_button_type')) {
+ $data['button_type'] = $this->config->get('module_amazon_login_button_type');
+ } else {
+ $data['button_type'] = 'lwa';
+ }
+
+ if ($this->config->get('module_amazon_login_button_colour')) {
+ $data['button_colour'] = $this->config->get('module_amazon_login_button_colour');
+ } else {
+ $data['button_colour'] = 'gold';
+ }
+
+ if ($this->config->get('module_amazon_login_button_size')) {
+ $data['button_size'] = $this->config->get('module_amazon_login_button_size');
+ } else {
+ $data['button_size'] = 'medium';
+ }
+
+ if ($this->config->get('payment_amazon_login_pay_language')) {
+ $data['language'] = $this->config->get('payment_amazon_login_pay_language');
+ } else {
+ $data['language'] = 'en-US';
+ }
+
+ return $this->load->view('extension/module/amazon_login', $data);
+ }
+ }
+
+ public function login() {
+ $this->load->language('extension/payment/amazon_login_pay');
+ $this->load->language('account/login');
+
+ $this->load->model('extension/module/amazon_login');
+
+ $from_amazon_pay = isset($this->request->get['from_amazon_pay']);
+
+ unset($this->session->data['apalwa']);
+
+ try {
+ if (isset($this->request->get['access_token'])) {
+ $access_token = $this->request->get['access_token'];
+
+ $this->session->data['apalwa']['login']['access_token'] = $access_token;
+
+ $this->model_extension_module_amazon_login->verifyAccessToken($access_token);
+
+ $amazon_profile = $this->model_extension_module_amazon_login->fetchProfile($access_token);
+ } else {
+ $this->model_extension_module_amazon_login->debugLog("EXCEPTION", $this->language->get('error_login'));
+
+ throw new \RuntimeException($this->language->get('error_login'));
+ }
+
+ // No issues found, and the Amazon profile has been fetched
+ if ($from_amazon_pay) {
+ unset($this->session->data['guest']);
+ unset($this->session->data['account']);
+
+ if ($this->config->get('payment_amazon_login_pay_checkout') == 'guest') {
+ $this->session->data['account'] = 'guest';
+
+ $this->session->data['guest']['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $this->session->data['guest']['firstname'] = (string)$amazon_profile->first_name;
+ $this->session->data['guest']['lastname'] = (string)$amazon_profile->last_name;
+ $this->session->data['guest']['email'] = (string)$amazon_profile->email;
+ $this->session->data['guest']['telephone'] = '0000000';
+
+ $this->session->data['apalwa']['pay']['profile'] = $this->session->data['guest'];
+ } else {
+ // The payment button must log in a customer
+ $this->session->data['account'] = 'register';
+
+ $profile = $this->model_extension_module_amazon_login->loginProfile($amazon_profile);
+
+ $this->session->data['apalwa']['pay']['profile'] = $profile;
+
+ // If a customer is already logged in, we must overwrite their data with amazon data
+ // Therefore, at the end of the day, we will have a
+ }
+
+ $this->response->redirect($this->url->link('extension/payment/amazon_login_pay/address', '', true));
+ } else {
+ $this->model_extension_module_amazon_login->loginProfile($amazon_profile);
+
+ $this->response->redirect($this->url->link('account/account', '', true));
+ }
+ } catch (\RuntimeException $e) {
+ $this->session->data['apalwa']['login']['error'] = $e->getMessage();
+
+ $this->response->redirect($this->url->link('extension/module/amazon_login/error', '', true));
+ }
+ }
+
+ public function error() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $data = array();
+
+ $continue = $this->url->link('common/home', '', true);
+
+ if (isset($this->session->data['apalwa']['login']['error'])) {
+ $data['error'] = $this->session->data['apalwa']['login']['error'];
+ $data['continue'] = $continue;
+ $data['heading_title'] = $this->language->get('error_login');
+
+ $this->document->setTitle($this->language->get('error_login'));
+
+ unset($this->session->data['apalwa']);
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home', '', true),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => null,
+ 'current' => true,
+ 'text' => $this->language->get('error_login')
+ );
+
+ $data['content_main'] = $this->load->view('extension/module/amazon_login_error', $data);
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/amazon_login_pay_generic', $data));
+ } else {
+ $this->response->redirect($continue);
+ }
+ }
+
+ public function logout() {
+ unset($this->session->data['apalwa']);
+
+ // capital L in Amazon cookie name is required, do not alter for coding standards
+ if (isset($this->request->cookie['amazon_Login_state_cache'])) {
+ //@todo - rework this by triggering the JavaScript logout
+ setcookie('amazon_Login_state_cache', null, -1, '/');
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/amazon_pay.php b/public/catalog/controller/extension/module/amazon_pay.php
new file mode 100644
index 0000000..97bc3c0
--- /dev/null
+++ b/public/catalog/controller/extension/module/amazon_pay.php
@@ -0,0 +1,52 @@
+<?php
+class ControllerExtensionModuleAmazonPay extends Controller {
+ public function index() {
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ if ($this->config->get('payment_amazon_login_pay_status') && $this->config->get('module_amazon_pay_status') && !empty($this->request->server['HTTPS']) && !($this->config->get('payment_amazon_login_pay_minimum_total') > 0 && $this->config->get('payment_amazon_login_pay_minimum_total') > $this->cart->getSubTotal()) && $this->model_extension_payment_amazon_login_pay->isTotalPositive()) {
+
+ // capital L in Amazon cookie name is required, do not alter for coding standards
+ if (!$this->customer->isLogged() && isset($this->request->cookie['amazon_Login_state_cache'])) {
+ setcookie('amazon_Login_state_cache', null, -1, '/');
+ }
+
+ $amazon_payment_js = $this->model_extension_payment_amazon_login_pay->getWidgetJs();
+ $this->document->addScript($amazon_payment_js);
+
+ $data['client_id'] = $this->config->get('payment_amazon_login_pay_client_id');
+ $data['merchant_id'] = $this->config->get('payment_amazon_login_pay_merchant_id');
+ $data['return_url'] = html_entity_decode($this->url->link('extension/module/amazon_login/login', 'from_amazon_pay=1', true), ENT_COMPAT, "UTF-8");
+ $data['button_id'] = 'AmazonPayButton';
+
+ if ($this->config->get('payment_amazon_login_pay_test') == 'sandbox') {
+ $data['sandbox'] = isset($this->session->data['user_id']); // Require an active admin panel session to show debug messages
+ }
+
+ if ($this->config->get('module_amazon_pay_button_type')) {
+ $data['button_type'] = $this->config->get('module_amazon_pay_button_type');
+ } else {
+ $data['button_type'] = 'PwA';
+ }
+
+ if ($this->config->get('module_amazon_pay_button_colour')) {
+ $data['button_colour'] = $this->config->get('module_amazon_pay_button_colour');
+ } else {
+ $data['button_colour'] = 'Gold';
+ }
+
+ if ($this->config->get('module_amazon_pay_button_size')) {
+ $data['button_size'] = $this->config->get('module_amazon_pay_button_size');
+ } else {
+ $data['button_size'] = 'medium';
+ }
+
+ if ($this->config->get('payment_amazon_login_pay_language')) {
+ $data['language'] = $this->config->get('payment_amazon_login_pay_language');
+ } else {
+ $data['language'] = 'en-US';
+ }
+
+ return $this->load->view('extension/module/amazon_login', $data);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/banner.php b/public/catalog/controller/extension/module/banner.php
new file mode 100644
index 0000000..0e90702
--- /dev/null
+++ b/public/catalog/controller/extension/module/banner.php
@@ -0,0 +1,31 @@
+<?php
+class ControllerExtensionModuleBanner extends Controller {
+ public function index($setting) {
+ static $module = 0;
+
+ $this->load->model('design/banner');
+ $this->load->model('tool/image');
+
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/swiper.min.css');
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/opencart.css');
+ $this->document->addScript('catalog/view/javascript/jquery/swiper/js/swiper.jquery.js');
+
+ $data['banners'] = array();
+
+ $results = $this->model_design_banner->getBanner($setting['banner_id']);
+
+ foreach ($results as $result) {
+ if (is_file(DIR_IMAGE . $result['image'])) {
+ $data['banners'][] = array(
+ 'title' => $result['title'],
+ 'link' => $result['link'],
+ 'image' => $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height'])
+ );
+ }
+ }
+
+ $data['module'] = $module++;
+
+ return $this->load->view('extension/module/banner', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/bestseller.php b/public/catalog/controller/extension/module/bestseller.php
new file mode 100644
index 0000000..6b0a239
--- /dev/null
+++ b/public/catalog/controller/extension/module/bestseller.php
@@ -0,0 +1,62 @@
+<?php
+class ControllerExtensionModuleBestSeller extends Controller {
+ public function index($setting) {
+ $this->load->language('extension/module/bestseller');
+
+ $this->load->model('catalog/product');
+
+ $this->load->model('tool/image');
+
+ $data['products'] = array();
+
+ $results = $this->model_catalog_product->getBestSellerProducts($setting['limit']);
+
+ if ($results) {
+ foreach ($results as $result) {
+ if ($result['image']) {
+ $image = $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height']);
+ } else {
+ $image = $this->model_tool_image->resize('placeholder.png', $setting['width'], $setting['height']);
+ }
+
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ if ((float)$result['special']) {
+ $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $special = false;
+ }
+
+ if ($this->config->get('config_tax')) {
+ $tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
+ } else {
+ $tax = false;
+ }
+
+ if ($this->config->get('config_review_status')) {
+ $rating = $result['rating'];
+ } else {
+ $rating = false;
+ }
+
+ $data['products'][] = array(
+ 'product_id' => $result['product_id'],
+ 'thumb' => $image,
+ 'name' => $result['name'],
+ 'description' => utf8_substr(trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8'))), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..',
+ 'price' => $price,
+ 'special' => $special,
+ 'tax' => $tax,
+ 'rating' => $rating,
+ 'href' => $this->url->link('product/product', 'product_id=' . $result['product_id'])
+ );
+ }
+
+ return $this->load->view('extension/module/bestseller', $data);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/carousel.php b/public/catalog/controller/extension/module/carousel.php
new file mode 100644
index 0000000..f273cd1
--- /dev/null
+++ b/public/catalog/controller/extension/module/carousel.php
@@ -0,0 +1,31 @@
+<?php
+class ControllerExtensionModuleCarousel extends Controller {
+ public function index($setting) {
+ static $module = 0;
+
+ $this->load->model('design/banner');
+ $this->load->model('tool/image');
+
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/swiper.min.css');
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/opencart.css');
+ $this->document->addScript('catalog/view/javascript/jquery/swiper/js/swiper.jquery.js');
+
+ $data['banners'] = array();
+
+ $results = $this->model_design_banner->getBanner($setting['banner_id']);
+
+ foreach ($results as $result) {
+ if (is_file(DIR_IMAGE . $result['image'])) {
+ $data['banners'][] = array(
+ 'title' => $result['title'],
+ 'link' => $result['link'],
+ 'image' => $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height'])
+ );
+ }
+ }
+
+ $data['module'] = $module++;
+
+ return $this->load->view('extension/module/carousel', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/category.php b/public/catalog/controller/extension/module/category.php
new file mode 100644
index 0000000..e29ed4b
--- /dev/null
+++ b/public/catalog/controller/extension/module/category.php
@@ -0,0 +1,64 @@
+<?php
+class ControllerExtensionModuleCategory extends Controller {
+ public function index() {
+ $this->load->language('extension/module/category');
+
+ if (isset($this->request->get['path'])) {
+ $parts = explode('_', (string)$this->request->get['path']);
+ } else {
+ $parts = array();
+ }
+
+ if (isset($parts[0])) {
+ $data['category_id'] = $parts[0];
+ } else {
+ $data['category_id'] = 0;
+ }
+
+ if (isset($parts[1])) {
+ $data['child_id'] = $parts[1];
+ } else {
+ $data['child_id'] = 0;
+ }
+
+ $this->load->model('catalog/category');
+
+ $this->load->model('catalog/product');
+
+ $data['categories'] = array();
+
+ $categories = $this->model_catalog_category->getCategories(0);
+
+ foreach ($categories as $category) {
+ $children_data = array();
+
+ if ($category['category_id'] == $data['category_id']) {
+ $children = $this->model_catalog_category->getCategories($category['category_id']);
+
+ foreach($children as $child) {
+ $filter_data = array('filter_category_id' => $child['category_id'], 'filter_sub_category' => true);
+
+ $children_data[] = array(
+ 'category_id' => $child['category_id'],
+ 'name' => $child['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
+ 'href' => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])
+ );
+ }
+ }
+
+ $filter_data = array(
+ 'filter_category_id' => $category['category_id'],
+ 'filter_sub_category' => true
+ );
+
+ $data['categories'][] = array(
+ 'category_id' => $category['category_id'],
+ 'name' => $category['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : ''),
+ 'children' => $children_data,
+ 'href' => $this->url->link('product/category', 'path=' . $category['category_id'])
+ );
+ }
+
+ return $this->load->view('extension/module/category', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/divido_calculator.php b/public/catalog/controller/extension/module/divido_calculator.php
new file mode 100644
index 0000000..40a7b3e
--- /dev/null
+++ b/public/catalog/controller/extension/module/divido_calculator.php
@@ -0,0 +1,53 @@
+<?php
+class ControllerExtensionModuleDividoCalculator extends Controller {
+ public function index() {
+ $this->load->language('extension/module/divido_calculator');
+ $this->load->model('extension/payment/divido');
+ $this->load->model('catalog/product');
+
+ $product_selection = $this->config->get('payment_divido_productselection');
+ $product_threshold = $this->config->get('payment_divido_price_threshold');
+
+ if (!isset($this->request->get['product_id']) || !$this->config->get('payment_divido_status') || !$this->config->get('module_divido_calculator_status')) {
+ return false;
+ }
+
+ $product_info = $this->model_catalog_product->getProduct($this->request->get['product_id']);
+
+ $price = 0;
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $base_price = !empty($product_info['special']) ? $product_info['special'] : $product_info['price'];
+ $price = $this->tax->calculate($base_price, $product_info['tax_class_id'], $this->config->get('config_tax'));
+ }
+
+ if ($product_selection == 'threshold' && $product_threshold > $price) {
+ return false;
+ }
+
+ $api_key = $this->config->get('payment_divido_api_key');
+ $key_parts = explode('.', $api_key);
+ $js_key = strtolower(array_shift($key_parts));
+
+ $this->model_extension_payment_divido->setMerchant($api_key);
+ $plans = $this->model_extension_payment_divido->getProductPlans($this->request->get['product_id']);
+
+ if (!$plans) {
+ return false;
+ }
+
+ $plans_ids = array_map(function ($plan) {
+ return $plan->id;
+ }, $plans);
+ $plans_ids = array_unique($plans_ids);
+ $plans_list = implode(',', $plans_ids);
+
+ $data = array(
+ 'merchant_script' => "//cdn.divido.com/calculator/{$js_key}.js",
+ 'product_price' => $price,
+ 'plan_list' => $plans_list,
+ 'generic_credit_req_error' => 'Credit request could not be initiated',
+ );
+
+ return $this->load->view('extension/module/divido_calculator', $data);
+ }
+}
diff --git a/public/catalog/controller/extension/module/ebay_listing.php b/public/catalog/controller/extension/module/ebay_listing.php
new file mode 100644
index 0000000..0e763e7
--- /dev/null
+++ b/public/catalog/controller/extension/module/ebay_listing.php
@@ -0,0 +1,42 @@
+<?php
+class ControllerExtensionModuleEbayListing extends Controller {
+ public function index() {
+ if ($this->config->get('ebay_status') == 1) {
+ $this->load->language('extension/module/ebay');
+
+ $this->load->model('tool/image');
+ $this->load->model('extension/openbay/ebay_product');
+
+ $data['heading_title'] = $this->language->get('heading_title');
+
+ $data['products'] = array();
+
+ $products = $this->cache->get('ebay_listing.' . md5(serialize($products)));
+
+ if (!$products) {
+ $products = $this->model_extension_openbay_ebay_product->getDisplayProducts();
+
+ $this->cache->set('ebay_listing.' . md5(serialize($products)), $products);
+ }
+
+ foreach($products['products'] as $product) {
+ if (isset($product['pictures'][0])) {
+ $image = $this->model_extension_openbay_ebay_product->resize($product['pictures'][0], $this->config->get('ebay_listing_width'), $this->config->get('ebay_listing_height'));
+ } else {
+ $image = $this->model_tool_image->resize('placeholder.png', $this->config->get('ebay_listing_width'), $this->config->get('ebay_listing_height'));
+ }
+
+ $data['products'][] = array(
+ 'thumb' => $image,
+ 'name' => base64_decode($product['Title']),
+ 'price' => $this->currency->format($product['priceGross'], $this->session->data['currency']),
+ 'href' => (string)$product['link']
+ );
+ }
+
+ $data['tracking_pixel'] = $products['tracking_pixel'];
+
+ return $this->load->view('extension/module/ebay', $data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/featured.php b/public/catalog/controller/extension/module/featured.php
new file mode 100644
index 0000000..b3b14c5
--- /dev/null
+++ b/public/catalog/controller/extension/module/featured.php
@@ -0,0 +1,72 @@
+<?php
+class ControllerExtensionModuleFeatured extends Controller {
+ public function index($setting) {
+ $this->load->language('extension/module/featured');
+
+ $this->load->model('catalog/product');
+
+ $this->load->model('tool/image');
+
+ $data['products'] = array();
+
+ if (!$setting['limit']) {
+ $setting['limit'] = 4;
+ }
+
+ if (!empty($setting['product'])) {
+ $products = array_slice($setting['product'], 0, (int)$setting['limit']);
+
+ foreach ($products as $product_id) {
+ $product_info = $this->model_catalog_product->getProduct($product_id);
+
+ if ($product_info) {
+ if ($product_info['image']) {
+ $image = $this->model_tool_image->resize($product_info['image'], $setting['width'], $setting['height']);
+ } else {
+ $image = $this->model_tool_image->resize('placeholder.png', $setting['width'], $setting['height']);
+ }
+
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($product_info['price'], $product_info['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ if ((float)$product_info['special']) {
+ $special = $this->currency->format($this->tax->calculate($product_info['special'], $product_info['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $special = false;
+ }
+
+ if ($this->config->get('config_tax')) {
+ $tax = $this->currency->format((float)$product_info['special'] ? $product_info['special'] : $product_info['price'], $this->session->data['currency']);
+ } else {
+ $tax = false;
+ }
+
+ if ($this->config->get('config_review_status')) {
+ $rating = $product_info['rating'];
+ } else {
+ $rating = false;
+ }
+
+ $data['products'][] = array(
+ 'product_id' => $product_info['product_id'],
+ 'thumb' => $image,
+ 'name' => $product_info['name'],
+ 'description' => utf8_substr(strip_tags(html_entity_decode($product_info['description'], ENT_QUOTES, 'UTF-8')), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..',
+ 'price' => $price,
+ 'special' => $special,
+ 'tax' => $tax,
+ 'rating' => $rating,
+ 'href' => $this->url->link('product/product', 'product_id=' . $product_info['product_id'])
+ );
+ }
+ }
+ }
+
+ if ($data['products']) {
+ return $this->load->view('extension/module/featured', $data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/filter.php b/public/catalog/controller/extension/module/filter.php
new file mode 100644
index 0000000..36bedce
--- /dev/null
+++ b/public/catalog/controller/extension/module/filter.php
@@ -0,0 +1,74 @@
+<?php
+class ControllerExtensionModuleFilter extends Controller {
+ public function index() {
+ if (isset($this->request->get['path'])) {
+ $parts = explode('_', (string)$this->request->get['path']);
+ } else {
+ $parts = array();
+ }
+
+ $category_id = end($parts);
+
+ $this->load->model('catalog/category');
+
+ $category_info = $this->model_catalog_category->getCategory($category_id);
+
+ if ($category_info) {
+ $this->load->language('extension/module/filter');
+
+ $url = '';
+
+ if (isset($this->request->get['sort'])) {
+ $url .= '&sort=' . $this->request->get['sort'];
+ }
+
+ if (isset($this->request->get['order'])) {
+ $url .= '&order=' . $this->request->get['order'];
+ }
+
+ if (isset($this->request->get['limit'])) {
+ $url .= '&limit=' . $this->request->get['limit'];
+ }
+
+ $data['action'] = str_replace('&amp;', '&', $this->url->link('product/category', 'path=' . $this->request->get['path'] . $url));
+
+ if (isset($this->request->get['filter'])) {
+ $data['filter_category'] = explode(',', $this->request->get['filter']);
+ } else {
+ $data['filter_category'] = array();
+ }
+
+ $this->load->model('catalog/product');
+
+ $data['filter_groups'] = array();
+
+ $filter_groups = $this->model_catalog_category->getCategoryFilters($category_id);
+
+ if ($filter_groups) {
+ foreach ($filter_groups as $filter_group) {
+ $childen_data = array();
+
+ foreach ($filter_group['filter'] as $filter) {
+ $filter_data = array(
+ 'filter_category_id' => $category_id,
+ 'filter_filter' => $filter['filter_id']
+ );
+
+ $childen_data[] = array(
+ 'filter_id' => $filter['filter_id'],
+ 'name' => $filter['name'] . ($this->config->get('config_product_count') ? ' (' . $this->model_catalog_product->getTotalProducts($filter_data) . ')' : '')
+ );
+ }
+
+ $data['filter_groups'][] = array(
+ 'filter_group_id' => $filter_group['filter_group_id'],
+ 'name' => $filter_group['name'],
+ 'filter' => $childen_data
+ );
+ }
+
+ return $this->load->view('extension/module/filter', $data);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/google_hangouts.php b/public/catalog/controller/extension/module/google_hangouts.php
new file mode 100644
index 0000000..5d61d87
--- /dev/null
+++ b/public/catalog/controller/extension/module/google_hangouts.php
@@ -0,0 +1,14 @@
+<?php
+class ControllerExtensionModuleGoogleHangouts extends Controller {
+ public function index() {
+ $this->load->language('extension/module/google_hangouts');
+
+ if ($this->request->server['HTTPS']) {
+ $data['code'] = str_replace('http', 'https', html_entity_decode($this->config->get('module_google_hangouts_code')));
+ } else {
+ $data['code'] = html_entity_decode($this->config->get('module_google_hangouts_code'));
+ }
+
+ return $this->load->view('extension/module/google_hangouts', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/html.php b/public/catalog/controller/extension/module/html.php
new file mode 100644
index 0000000..bf32060
--- /dev/null
+++ b/public/catalog/controller/extension/module/html.php
@@ -0,0 +1,11 @@
+<?php
+class ControllerExtensionModuleHTML extends Controller {
+ public function index($setting) {
+ if (isset($setting['module_description'][$this->config->get('config_language_id')])) {
+ $data['heading_title'] = html_entity_decode($setting['module_description'][$this->config->get('config_language_id')]['title'], ENT_QUOTES, 'UTF-8');
+ $data['html'] = html_entity_decode($setting['module_description'][$this->config->get('config_language_id')]['description'], ENT_QUOTES, 'UTF-8');
+
+ return $this->load->view('extension/module/html', $data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/information.php b/public/catalog/controller/extension/module/information.php
new file mode 100644
index 0000000..15badd3
--- /dev/null
+++ b/public/catalog/controller/extension/module/information.php
@@ -0,0 +1,22 @@
+<?php
+class ControllerExtensionModuleInformation extends Controller {
+ public function index() {
+ $this->load->language('extension/module/information');
+
+ $this->load->model('catalog/information');
+
+ $data['informations'] = array();
+
+ foreach ($this->model_catalog_information->getInformations() as $result) {
+ $data['informations'][] = array(
+ 'title' => $result['title'],
+ 'href' => $this->url->link('information/information', 'information_id=' . $result['information_id'])
+ );
+ }
+
+ $data['contact'] = $this->url->link('information/contact');
+ $data['sitemap'] = $this->url->link('information/sitemap');
+
+ return $this->load->view('extension/module/information', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/klarna_checkout_module.php b/public/catalog/controller/extension/module/klarna_checkout_module.php
new file mode 100644
index 0000000..079207f
--- /dev/null
+++ b/public/catalog/controller/extension/module/klarna_checkout_module.php
@@ -0,0 +1,138 @@
+<?php
+class ControllerExtensionModuleKlarnaCheckoutModule extends Controller {
+ public function index() {
+ $this->load->model('extension/payment/klarna_checkout');
+
+ // If Payment Method or Module is disabled
+ if (!$this->config->get('module_klarna_checkout_status') || !$this->config->get('klarna_checkout_status')) {
+ $this->model_extension_payment_klarna_checkout->log('Not shown due to Payment Method or Module being disabled');
+ return false;
+ }
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->model_extension_payment_klarna_checkout->log('Not shown due to empty cart');
+ return false;
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $this->model_extension_payment_klarna_checkout->log('Not shown due to cart not meeting minimum quantity reqs.');
+ return false;
+ }
+ }
+
+ // Validate cart has recurring products
+ if ($this->cart->hasRecurringProducts()) {
+ $this->model_extension_payment_klarna_checkout->log('Not shown due to cart having recurring products.');
+ return false;
+ }
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ if ($this->config->get('klarna_checkout_total') > 0 && $this->config->get('klarna_checkout_total') > $total) {
+ return false;
+ }
+
+ if ($this->model_extension_payment_klarna_checkout->checkForPaymentTaxes($products)) {
+ $this->model_extension_payment_klarna_checkout->log('Payment Address based taxes used.');
+ return false;
+ }
+
+ $this->setShipping();
+
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
+
+ if (!$klarna_account || !$connector) {
+ $this->model_extension_payment_klarna_checkout->log('Couldn\'t secure connection to Klarna API.');
+ return false;
+ }
+
+ $data['klarna_checkout'] = $this->url->link('extension/payment/klarna_checkout', '', true);
+
+ return $this->load->view('extension/module/klarna_checkout_module', $data);
+ }
+
+ private function setShipping() {
+ $this->load->model('account/address');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ if (isset($this->session->data['shipping_address']) && !empty($this->session->data['shipping_address'])) {
+ $this->session->data['shipping_address'] = $this->session->data['shipping_address'];
+ } elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
+ $this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ } else {
+ $country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
+
+ $zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
+
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => $zone_info['zone_id'],
+ 'zone' => $zone_info['name'],
+ 'zone_code' => $zone_info['code'],
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => null,
+ );
+ }
+
+ if (isset($this->session->data['shipping_address'])) {
+ // Shipping Methods
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $method_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $this->session->data['shipping_methods'] = $method_data;
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/latest.php b/public/catalog/controller/extension/module/latest.php
new file mode 100644
index 0000000..44285de
--- /dev/null
+++ b/public/catalog/controller/extension/module/latest.php
@@ -0,0 +1,69 @@
+<?php
+class ControllerExtensionModuleLatest extends Controller {
+ public function index($setting) {
+ $this->load->language('extension/module/latest');
+
+ $this->load->model('catalog/product');
+
+ $this->load->model('tool/image');
+
+ $data['products'] = array();
+
+ $filter_data = array(
+ 'sort' => 'p.date_added',
+ 'order' => 'DESC',
+ 'start' => 0,
+ 'limit' => $setting['limit']
+ );
+
+ $results = $this->model_catalog_product->getProducts($filter_data);
+
+ if ($results) {
+ foreach ($results as $result) {
+ if ($result['image']) {
+ $image = $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height']);
+ } else {
+ $image = $this->model_tool_image->resize('placeholder.png', $setting['width'], $setting['height']);
+ }
+
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ if ((float)$result['special']) {
+ $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $special = false;
+ }
+
+ if ($this->config->get('config_tax')) {
+ $tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
+ } else {
+ $tax = false;
+ }
+
+ if ($this->config->get('config_review_status')) {
+ $rating = $result['rating'];
+ } else {
+ $rating = false;
+ }
+
+ $data['products'][] = array(
+ 'product_id' => $result['product_id'],
+ 'thumb' => $image,
+ 'name' => $result['name'],
+ 'description' => utf8_substr(trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8'))), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..',
+ 'price' => $price,
+ 'special' => $special,
+ 'tax' => $tax,
+ 'rating' => $rating,
+ 'href' => $this->url->link('product/product', 'product_id=' . $result['product_id'])
+ );
+ }
+
+ return $this->load->view('extension/module/latest', $data);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/laybuy_layout.php b/public/catalog/controller/extension/module/laybuy_layout.php
new file mode 100644
index 0000000..a586167
--- /dev/null
+++ b/public/catalog/controller/extension/module/laybuy_layout.php
@@ -0,0 +1,38 @@
+<?php
+class ControllerExtensionModuleLaybuyLayout extends Controller {
+ public function index() {
+ $this->load->model('extension/module/laybuy_layout');
+
+ $status = $this->config->get('module_laybuy_layout_status');
+
+ if ($status && $this->config->get('payment_laybuy_status')) {
+ if ($this->customer->isLogged()) {
+ if (isset($this->request->get['order_id'])) {
+ $order_id = $this->request->get['order_id'];
+
+ if ($this->model_extension_module_laybuy_layout->isLayBuyOrder($order_id)) {
+ $this->load->language('extension/module/laybuy_layout');
+
+ $transaction_info = $this->model_extension_module_laybuy_layout->getTransactionByOrderId($order_id);
+
+ $data['transaction'] = array(
+ 'laybuy_ref_no' => $transaction_info['laybuy_ref_no'],
+ 'paypal_profile_id' => $transaction_info['paypal_profile_id'],
+ 'status' => $this->model_extension_module_laybuy_layout->getStatusLabel($transaction_info['status']),
+ 'amount' => $this->currency->format($transaction_info['amount'], $transaction_info['currency']),
+ 'downpayment' => $transaction_info['downpayment'],
+ 'months' => $transaction_info['months'],
+ 'downpayment_amount' => $this->currency->format($transaction_info['downpayment_amount'], $transaction_info['currency']),
+ 'payment_amounts' => $this->currency->format($transaction_info['payment_amounts'], $transaction_info['currency']),
+ 'first_payment_due' => date($this->language->get('date_format_short'), strtotime($transaction_info['first_payment_due'])),
+ 'last_payment_due' => date($this->language->get('date_format_short'), strtotime($transaction_info['last_payment_due'])),
+ 'report' => json_decode($transaction_info['report'], true)
+ );
+
+ return $this->load->view('extension/module/laybuy_layout', $data);
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/pilibaba_button.php b/public/catalog/controller/extension/module/pilibaba_button.php
new file mode 100644
index 0000000..bd7271a
--- /dev/null
+++ b/public/catalog/controller/extension/module/pilibaba_button.php
@@ -0,0 +1,16 @@
+<?php
+class ControllerExtensionModulePilibabaButton extends Controller {
+ public function index() {
+ $status = true;
+
+ if (!$this->cart->hasProducts() || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $status = false;
+ }
+
+ if ($status) {
+ $data['payment_url'] = $this->url->link('extension/payment/pilibaba/express', '', true);
+
+ return $this->load->view('extension/module/pilibaba_button', $data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/pp_braintree_button.php b/public/catalog/controller/extension/module/pp_braintree_button.php
new file mode 100644
index 0000000..32f38d8
--- /dev/null
+++ b/public/catalog/controller/extension/module/pp_braintree_button.php
@@ -0,0 +1,51 @@
+<?php
+class ControllerExtensionModulePPBraintreeButton extends Controller {
+ private $gateway = null;
+
+ public function index() {
+ if ($this->config->get('payment_pp_braintree_status') == 1) {
+ $this->initialise();
+
+ $status = true;
+
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout')) || (!$this->customer->isLogged() && ($this->cart->hasRecurringProducts() || $this->cart->hasDownload()))) {
+ $status = false;
+ }
+
+ if ($status) {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pp_braintree');
+
+ $create_token = array();
+
+ $data['client_token'] = $this->model_extension_payment_pp_braintree->generateToken($this->gateway, $create_token);
+
+ $data['payment_pp_braintree_settlement_immediate'] = $this->config->get('payment_pp_braintree_settlement_immediate');
+ $data['payment_pp_braintree_paypal_button_colour'] = $this->config->get('payment_pp_braintree_paypal_button_colour');
+ $data['payment_pp_braintree_paypal_button_size'] = $this->config->get('payment_pp_braintree_paypal_button_size');
+ $data['payment_pp_braintree_paypal_button_shape'] = $this->config->get('payment_pp_braintree_paypal_button_shape');
+
+ /*
+ * The auth total is just a guess as to what the end total will be since the user has not
+ * selected a shipping option yet. The user does not see this amount during checkout but the figure
+ * may be too low if buying a low value item and shipping is more than 50% of the item value.
+ */
+ $data['auth_total'] = $this->cart->getTotal() * 1.5;
+ $data['currency_code'] = $this->session->data['currency'];
+ $data['action'] = $this->url->link('extension/payment/pp_braintree/expressConfirm', '', true);
+
+ return $this->load->view('extension/module/pp_braintree_button', $data);
+ }
+ }
+ }
+
+ private function initialise() {
+ $this->load->model('extension/payment/pp_braintree');
+
+ if ($this->config->get('payment_pp_braintree_access_token') != '') {
+ $this->gateway = $this->model_extension_payment_pp_braintree->setGateway($this->config->get('payment_pp_braintree_access_token'));
+ } else {
+ $this->model_extension_payment_pp_braintree->setCredentials();
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/pp_button.php b/public/catalog/controller/extension/module/pp_button.php
new file mode 100644
index 0000000..a217245
--- /dev/null
+++ b/public/catalog/controller/extension/module/pp_button.php
@@ -0,0 +1,34 @@
+<?php
+class ControllerExtensionModulePPButton extends Controller {
+ public function index() {
+ if ($this->config->get('payment_pp_express_status') == 1) {
+ $status = true;
+
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout')) || (!$this->customer->isLogged() && ($this->cart->hasRecurringProducts() || $this->cart->hasDownload()))) {
+ $status = false;
+ }
+
+ if ($status) {
+ $this->load->model('extension/payment/pp_express');
+
+ if (preg_match('/Mobile|Android|BlackBerry|iPhone|Windows Phone/', $this->request->server['HTTP_USER_AGENT'])) {
+ $data['mobile'] = true;
+ } else {
+ $data['mobile'] = false;
+ }
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $data['paypal_username'] = $this->config->get('payment_pp_express_sandbox_username');
+ $data['paypal_environment'] = 'sandbox';
+ } else {
+ $data['paypal_username'] = $this->config->get('payment_pp_express_username');
+ $data['paypal_environment'] = 'production';
+ }
+
+ $data['payment_url'] = $this->url->link('extension/payment/pp_express/express', '', true);
+
+ return $this->load->view('extension/module/pp_button', $data);
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/module/pp_login.php b/public/catalog/controller/extension/module/pp_login.php
new file mode 100644
index 0000000..dc581ab
--- /dev/null
+++ b/public/catalog/controller/extension/module/pp_login.php
@@ -0,0 +1,202 @@
+<?php
+class ControllerExtensionModulePPLogin extends Controller {
+ private $error = array();
+
+ public function index() {
+ if (!$this->customer->isLogged()) {
+ $data['client_id'] = $this->config->get('module_pp_login_client_id');
+ $data['return_url'] = $this->url->link('extension/module/pp_login/login', '', true);
+
+ if ($this->config->get('module_pp_login_sandbox')) {
+ $data['sandbox'] = 'sandbox';
+ } else {
+ $data['sandbox'] = '';
+ }
+
+ if ($this->config->get('module_pp_login_button_colour') == 'grey') {
+ $data['button_colour'] = 'neutral';
+ } else {
+ $data['button_colour'] = '';
+ }
+
+ $locale = $this->config->get('module_pp_login_locale');
+
+ $this->load->model('localisation/language');
+
+ $languages = $this->model_localisation_language->getLanguages();
+
+ foreach ($languages as $language) {
+ if ($language['status'] && ($language['code'] == $this->session->data['language']) && isset($locale[$language['language_id']])) {
+ $data['locale'] = $locale[$language['language_id']];
+ }
+ }
+
+ if (!isset($data['locale'])) {
+ $data['locale'] = 'en-gb';
+ }
+
+ $scopes = array(
+ 'profile',
+ 'email',
+ 'address',
+ 'phone'
+ );
+
+ if ($this->config->get('module_pp_login_seamless')) {
+ $scopes[] = 'https://uri.paypal.com/services/expresscheckout';
+ }
+
+ $data['scopes'] = implode(' ', $scopes);
+
+ return $this->load->view('extension/module/pp_login', $data);
+ }
+ }
+
+ public function login() {
+ $this->load->model('extension/module/pp_login');
+ $this->load->model('account/customer');
+ $this->load->model('account/customer_group');
+
+ if ($this->customer->isLogged()) {
+ echo '<script type="text/javascript">window.opener.location = "' . $this->url->link('account/account', '', true) . '"; window.close();</script>';
+ }
+
+ if (!isset($this->request->get['code'])) {
+ if (isset($this->request->get['error']) && isset($this->request->get['error_description'])) {
+ $this->model_extension_module_pp_login->log('No code returned. Error: ' . $this->request->get['error'] . ', Error Description: ' . $this->request->get['error_description']);
+ }
+
+ echo '<script type="text/javascript">window.opener.location = "' . $this->url->link('account/login', '', true) . '"; window.close();</script>';
+ } else {
+ $tokens = $this->model_extension_module_pp_login->getTokens($this->request->get['code']);
+ }
+
+ if (isset($tokens->access_token) && !isset($tokens->error)) {
+ $user = $this->model_extension_module_pp_login->getUserInfo($tokens->access_token);
+ }
+
+ if (isset($user)) {
+ $customer_info = $this->model_account_customer->getCustomerByEmail($user->email);
+
+ if ($customer_info) {
+ if ($this->validate($user->email)) {
+ $this->completeLogin($customer_info['customer_id'], $customer_info['email'], $tokens->access_token);
+ } else {
+ $this->model_extension_module_pp_login->log('Could not login to - ID: ' . $customer_info['customer_id'] . ', Email: ' . $customer_info['email']);
+ echo '<script type="text/javascript">window.opener.location = "' . $this->url->link('account/login', '', true) . '"; window.close();</script>';
+ }
+ } else {
+ $country = $this->db->query("SELECT `country_id` FROM `" . DB_PREFIX . "country` WHERE iso_code_2 = '" . $this->db->escape($user->address->country) . "'");
+
+ if ($country->num_rows) {
+ $country_id = $country->row['country_id'];
+
+ $zone = $this->db->query("SELECT `zone_id` FROM `" . DB_PREFIX . "zone` WHERE country_id = '" . (int)$country_id . "' AND name = '" . $this->db->escape($user->address->region) . "'");
+
+ if ($zone->num_rows) {
+ $zone_id = $zone->row['zone_id'];
+ } else {
+ $zone_id = 0;
+ }
+ } else {
+ $country_id = 0;
+ $zone_id = 0;
+ }
+
+ if ($this->config->get('module_pp_login_customer_group_id')) {
+ $customer_group_id = $this->config->get('module_pp_login_customer_group_id');
+ } else {
+ $customer_group_id = $this->config->get('config_customer_group_id');
+ }
+
+ $data = array(
+ 'customer_group_id' => (int)$customer_group_id,
+ 'firstname' => $user->given_name,
+ 'lastname' => $user->family_name,
+ 'email' => $user->email,
+ 'telephone' => $user->phone_number,
+ 'password' => uniqid(rand(), true),
+ 'company' => '',
+ 'address_1' => $user->address->street_address,
+ 'address_2' => '',
+ 'city' => $user->address->locality,
+ 'postcode' => $user->address->postal_code,
+ 'country_id' => (int)$country_id,
+ 'zone_id' => (int)$zone_id,
+ );
+
+ $customer_id = $this->model_account_customer->addCustomer($data);
+
+ $this->model_extension_module_pp_login->log('Customer ID date_added: ' . $customer_id);
+
+ if ($this->validate($user->email)) {
+ $this->completeLogin($customer_id, $user->email, $tokens->access_token);
+ } else {
+ $this->model_extension_module_pp_login->log('Could not login to - ID: ' . $customer_id . ', Email: ' . $user->email);
+ echo '<script type="text/javascript">window.opener.location = "' . $this->url->link('account/login', '', true) . '"; window.close();</script>';
+ }
+ }
+ }
+ }
+
+ public function logout() {
+ if (isset($this->session->data['pp_login'])) {
+ unset($this->session->data['pp_login']);
+ }
+ }
+
+ protected function completeLogin($customer_id, $email, $access_token) {
+ unset($this->session->data['guest']);
+
+ // Default Shipping Address
+ $this->load->model('account/address');
+
+ if ($this->config->get('config_tax_customer') == 'payment') {
+ $this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ }
+
+ if ($this->config->get('config_tax_customer') == 'shipping') {
+ $this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ }
+
+ if ($this->config->get('module_pp_login_seamless')) {
+ $this->session->data['pp_login']['seamless']['customer_id'] = $this->customer->getId();
+ $this->session->data['pp_login']['seamless']['access_token'] = $access_token;
+ } else {
+ if (isset($this->session->data['pp_login']['seamless'])) {
+ unset($this->session->data['pp_login']['seamless']);
+ }
+ }
+
+ $this->model_extension_module_pp_login->log('Customer logged in - ID: ' . $customer_id . ', Email: ' . $email);
+ echo '<script type="text/javascript">window.opener.location = "' . $this->url->link('account/account', '', true) . '"; window.close();</script>';
+ }
+
+ protected function validate($email) {
+ // Check how many login attempts have been made.
+ $login_info = $this->model_account_customer->getLoginAttempts($email);
+
+ if ($login_info && ($login_info['total'] >= $this->config->get('config_login_attempts')) && strtotime('-1 hour') < strtotime($login_info['date_modified'])) {
+ $this->error['warning'] = $this->language->get('error_attempts');
+ }
+
+ // Check if customer has been approved.
+ $customer_info = $this->model_account_customer->getCustomerByEmail($email);
+
+ if ($customer_info && !$customer_info['status']) {
+ $this->error['warning'] = $this->language->get('error_approved');
+ }
+
+ if (!$this->error) {
+ if (!$this->customer->login($email, '', true)) {
+ $this->error['warning'] = $this->language->get('error_login');
+
+ $this->model_account_customer->addLoginAttempt($email);
+ } else {
+ $this->model_account_customer->deleteLoginAttempts($email);
+ }
+ }
+
+ return !$this->error;
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/sagepay_direct_cards.php b/public/catalog/controller/extension/module/sagepay_direct_cards.php
new file mode 100644
index 0000000..0d4dce1
--- /dev/null
+++ b/public/catalog/controller/extension/module/sagepay_direct_cards.php
@@ -0,0 +1,13 @@
+<?php
+class ControllerExtensionModuleSagepayDirectCards extends Controller {
+ public function index() {
+ if ($this->config->get('module_sagepay_direct_cards_status') && $this->config->get('payment_sagepay_direct_status') && $this->customer->isLogged()) {
+ $this->load->language('account/sagepay_direct_cards');
+
+ $data['card'] = $this->url->link('account/sagepay_direct_cards', '', true);
+
+ return $this->load->view('extension/module/sagepay_direct_cards', $data);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/sagepay_server_cards.php b/public/catalog/controller/extension/module/sagepay_server_cards.php
new file mode 100644
index 0000000..f4cc007
--- /dev/null
+++ b/public/catalog/controller/extension/module/sagepay_server_cards.php
@@ -0,0 +1,13 @@
+<?php
+class ControllerExtensionModuleSagepayServerCards extends Controller {
+ public function index() {
+ if ($this->config->get('module_sagepay_server_cards_status') && $this->config->get('payment_sagepay_server_status') && $this->customer->isLogged()) {
+ $this->load->language('account/sagepay_server_cards');
+
+ $data['card'] = $this->url->link('account/sagepay_server_cards', '', true);
+
+ return $this->load->view('extension/module/sagepay_server_cards', $data);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/slideshow.php b/public/catalog/controller/extension/module/slideshow.php
new file mode 100644
index 0000000..80265d7
--- /dev/null
+++ b/public/catalog/controller/extension/module/slideshow.php
@@ -0,0 +1,31 @@
+<?php
+class ControllerExtensionModuleSlideshow extends Controller {
+ public function index($setting) {
+ static $module = 0;
+
+ $this->load->model('design/banner');
+ $this->load->model('tool/image');
+
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/swiper.min.css');
+ $this->document->addStyle('catalog/view/javascript/jquery/swiper/css/opencart.css');
+ $this->document->addScript('catalog/view/javascript/jquery/swiper/js/swiper.jquery.js');
+
+ $data['banners'] = array();
+
+ $results = $this->model_design_banner->getBanner($setting['banner_id']);
+
+ foreach ($results as $result) {
+ if (is_file(DIR_IMAGE . $result['image'])) {
+ $data['banners'][] = array(
+ 'title' => $result['title'],
+ 'link' => $result['link'],
+ 'image' => $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height'])
+ );
+ }
+ }
+
+ $data['module'] = $module++;
+
+ return $this->load->view('extension/module/slideshow', $data);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/special.php b/public/catalog/controller/extension/module/special.php
new file mode 100644
index 0000000..6f13eed
--- /dev/null
+++ b/public/catalog/controller/extension/module/special.php
@@ -0,0 +1,69 @@
+<?php
+class ControllerExtensionModuleSpecial extends Controller {
+ public function index($setting) {
+ $this->load->language('extension/module/special');
+
+ $this->load->model('catalog/product');
+
+ $this->load->model('tool/image');
+
+ $data['products'] = array();
+
+ $filter_data = array(
+ 'sort' => 'pd.name',
+ 'order' => 'ASC',
+ 'start' => 0,
+ 'limit' => $setting['limit']
+ );
+
+ $results = $this->model_catalog_product->getProductSpecials($filter_data);
+
+ if ($results) {
+ foreach ($results as $result) {
+ if ($result['image']) {
+ $image = $this->model_tool_image->resize($result['image'], $setting['width'], $setting['height']);
+ } else {
+ $image = $this->model_tool_image->resize('placeholder.png', $setting['width'], $setting['height']);
+ }
+
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ if ((float)$result['special']) {
+ $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $special = false;
+ }
+
+ if ($this->config->get('config_tax')) {
+ $tax = $this->currency->format((float)$result['special'] ? $result['special'] : $result['price'], $this->session->data['currency']);
+ } else {
+ $tax = false;
+ }
+
+ if ($this->config->get('config_review_status')) {
+ $rating = $result['rating'];
+ } else {
+ $rating = false;
+ }
+
+ $data['products'][] = array(
+ 'product_id' => $result['product_id'],
+ 'thumb' => $image,
+ 'name' => $result['name'],
+ 'description' => utf8_substr(trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8'))), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..',
+ 'price' => $price,
+ 'special' => $special,
+ 'tax' => $tax,
+ 'rating' => $rating,
+ 'href' => $this->url->link('product/product', 'product_id=' . $result['product_id'])
+ );
+ }
+
+ return $this->load->view('extension/module/special', $data);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/module/store.php b/public/catalog/controller/extension/module/store.php
new file mode 100644
index 0000000..40a0dd4
--- /dev/null
+++ b/public/catalog/controller/extension/module/store.php
@@ -0,0 +1,40 @@
+<?php
+class ControllerExtensionModuleStore extends Controller {
+ public function index() {
+ $status = true;
+
+ if ($this->config->get('module_store_admin')) {
+ $this->user = new Cart\User($this->registry);
+
+ $status = $this->user->isLogged();
+ }
+
+ if ($status) {
+ $this->load->language('extension/module/store');
+
+ $data['store_id'] = $this->config->get('config_store_id');
+
+ $data['stores'] = array();
+
+ $data['stores'][] = array(
+ 'store_id' => 0,
+ 'name' => $this->language->get('text_default'),
+ 'url' => HTTP_SERVER . 'index.php?route=common/home&session_id=' . $this->session->getId()
+ );
+
+ $this->load->model('setting/store');
+
+ $results = $this->model_setting_store->getStores();
+
+ foreach ($results as $result) {
+ $data['stores'][] = array(
+ 'store_id' => $result['store_id'],
+ 'name' => $result['name'],
+ 'url' => $result['url'] . 'index.php?route=common/home&session_id=' . $this->session->getId()
+ );
+ }
+
+ return $this->load->view('extension/module/store', $data);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/openbay/amazon.php b/public/catalog/controller/extension/openbay/amazon.php
new file mode 100644
index 0000000..3df7054
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/amazon.php
@@ -0,0 +1,590 @@
+<?php
+class ControllerExtensionOpenbayAmazon extends Controller {
+ public function order() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ return;
+ }
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/openbay/amazon_order');
+ $this->load->language('extension/openbay/amazon_order');
+
+ $logger = new Log('amazon.log');
+ $logger->write('amazon/order - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazon_token'), $incoming_token)) {
+ $logger->write('amazon/order - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazon/order Failed to decrypt data');
+ return;
+ }
+
+ $order_xml = simplexml_load_string($decrypted);
+
+ $amazon_order_status = trim(strtolower((string)$order_xml->Status));
+
+ $amazon_order_id = (string)$order_xml->AmazonOrderId;
+ $order_status = $this->model_extension_openbay_amazon_order->getMappedStatus((string)$order_xml->Status);
+
+ $logger->write('Received order ' . $amazon_order_id);
+
+ $order_id = $this->model_extension_openbay_amazon_order->getOrderId($amazon_order_id);
+
+ // If the order already exists on opencart, ignore it.
+ if ($order_id) {
+ $logger->write("Duplicate order $amazon_order_id. Terminating.");
+ $this->response->setOutput('Ok');
+ return;
+ }
+
+ /* Check if order comes from subscribed marketplace */
+
+ $currency_to = $this->config->get('config_currency');
+ $order_currency = (string)$order_xml->Payment->CurrencyCode;
+
+ $products = array();
+
+ $products_total = 0;
+ $products_shipping = 0;
+ $products_tax = 0;
+ $products_shipping_tax = 0;
+ $gift_wrap = 0;
+ $gift_wrap_tax = 0;
+
+ $product_count = 0;
+
+ $amazon_order_id = (string)$order_xml->AmazonOrderId;
+
+ /* SKU => ORDER_ITEM_ID */
+ $product_mapping = array();
+ $product_gift_messages = array();
+
+ foreach ($order_xml->Items->Item as $item) {
+
+ $total_price = $this->currency->convert((double)$item->Totals->Price, $order_currency, $currency_to);
+ $tax_total = (double)$item->Totals->Tax;
+
+ if ($tax_total == 0 && $this->config->get('openbay_amazon_order_tax') > 0) {
+ $tax_total = (double)$item->Totals->Price * ($this->config->get('openbay_amazon_order_tax') / 100) / (1 + $this->config->get('openbay_amazon_order_tax') / 100);
+ }
+
+ $tax_total = $this->currency->convert($tax_total, $order_currency, $currency_to);
+
+ $products_total += $total_price;
+ $products_tax += $tax_total;
+
+ $products_shipping += $this->currency->convert((double)$item->Totals->Shipping, $order_currency, $currency_to);
+
+ $shipping_tax = (double)$item->Totals->ShippingTax;
+
+ if ($shipping_tax == 0 && $this->config->get('openbay_amazon_order_tax') > 0) {
+ $shipping_tax = (double)$item->Totals->Shipping * ($this->config->get('openbay_amazon_order_tax') / 100) / (1 + $this->config->get('openbay_amazon_order_tax') / 100);
+ }
+
+ $products_shipping_tax += $this->currency->convert($shipping_tax, $order_currency, $currency_to);
+
+ $gift_wrap += $this->currency->convert((double)$item->Totals->GiftWrap, $order_currency, $currency_to);
+
+ $item_gift_wrap_tax = (double)$item->Totals->GiftWrapTax;
+
+ if ($item_gift_wrap_tax == 0 && $this->config->get('openbay_amazon_order_tax') > 0) {
+ $item_gift_wrap_tax = (double)$item->Totals->GiftWrap * ($this->config->get('openbay_amazon_order_tax') / 100) / (1 + $this->config->get('openbay_amazon_order_tax') / 100);
+ }
+
+ $gift_wrap_tax += $this->currency->convert($item_gift_wrap_tax, $order_currency, $currency_to);
+
+ $product_count += (int)$item->Ordered;
+
+ if ((int)$item->Ordered == 0) {
+ continue;
+ }
+
+ $product_id = $this->model_extension_openbay_amazon_order->getProductId((string)$item->Sku);
+ $product_var = $this->model_extension_openbay_amazon_order->getProductVar((string)$item->Sku);
+
+ $products[] = array(
+ 'product_id' => $product_id,
+ 'var' => $product_var,
+ 'sku' => (string)$item->Sku,
+ 'asin' => (string)$item->Asin,
+ 'order_item_id' => (string)$item->OrderItemId,
+ 'name' => (string)$item->Title,
+ 'model' => (string)$item->Sku,
+ 'quantity' => (int)$item->Ordered,
+ 'price' => sprintf('%.4f', ($total_price - $tax_total) / (int)$item->Ordered),
+ 'total' => sprintf('%.4f', $total_price - $tax_total),
+ 'tax' => $tax_total / (int)$item->Ordered,
+ 'reward' => '0',
+ 'option' => $this->model_extension_openbay_amazon_order->getProductOptionsByVar($product_var),
+ 'download' => array(),
+ );
+
+ $product_mapping[(string)$item->Sku] = (string)$item->OrderItemId;
+
+ if ($item->GiftMessage != '') {
+ $product_gift_messages[] = (string)$item->Title . ' : ' . (string)$item->GiftMessage;
+ }
+ }
+
+ $order_comment = '';
+ if (count($product_gift_messages) > 0) {
+ $order_comment = $this->language->get('text_gift_message') . '<br />' . implode('<br />', $product_gift_messages);
+ }
+
+ $total = sprintf('%.4f', $this->currency->convert((double)$order_xml->Payment->Amount, $order_currency, $currency_to));
+
+ $address_line_2 = (string)$order_xml->Shipping->AddressLine2;
+ if ((string)$order_xml->Shipping->AddressLine3 != '') {
+ $address_line_2 .= ', ' . (string)$order_xml->Shipping->AddressLine3;
+ }
+
+ $customer_info = $this->db->query("SELECT `customer_id` FROM " . DB_PREFIX . "customer WHERE email = '" . $this->db->escape((string)$order_xml->Payment->Email) . "'")->row;
+ $customer_id = '0';
+
+ if(isset($customer_info['customer_id'])) {
+ $customer_id = $customer_info['customer_id'];
+ } else {
+ /* Add a new customer */
+ $customer_data = array(
+ 'firstname' => (string)$order_xml->Shipping->Name,
+ 'lastname' => '',
+ 'email' => (string)$order_xml->Payment->Email,
+ 'telephone' => (string)$order_xml->Shipping->Phone,
+ 'newsletter' => '0',
+ 'customer_group_id' => $this->config->get('openbay_amazon_order_customer_group'),
+ 'password' => '',
+ 'status' => '0',
+ );
+
+ $this->db->query("
+ INSERT INTO " . DB_PREFIX . "customer
+ SET firstname = '" . $this->db->escape($customer_data['firstname']) . "',
+ lastname = '" . $this->db->escape($customer_data['lastname']) . "',
+ email = '" . $this->db->escape($customer_data['email']) . "',
+ telephone = '" . $this->db->escape($customer_data['telephone']) . "',
+ newsletter = '" . (int)$customer_data['newsletter'] . "',
+ customer_group_id = '" . (int)$customer_data['customer_group_id'] . "',
+ password = '',
+ status = '" . (int)$customer_data['status'] . "',
+ date_added = NOW()");
+
+ $customer_id = $this->db->getLastId();
+ }
+
+ $shipping_first_name = (string)$order_xml->Shipping->FirstName;
+ $shipping_last_name = (string)$order_xml->Shipping->LastName;
+
+ if (empty($shipping_first_name) || empty($shipping_last_name)) {
+ $shipping_first_name = (string)$order_xml->Shipping->Name;
+ $shipping_last_name = '';
+ }
+
+ $order = array(
+ 'invoice_prefix' => $this->config->get('config_invoice_prefix'),
+ 'store_id' => $this->config->get('config_store_id'),
+ 'store_name' => $this->config->get('config_name') . ' / Amazon',
+ 'store_url' => $this->config->get('config_url'),
+ 'customer_id' => (int)$customer_id,
+ 'customer_group_id' => $this->config->get('openbay_amazon_order_customer_group'),
+ 'firstname' => $shipping_first_name,
+ 'lastname' => $shipping_last_name,
+ 'email' => (string)$order_xml->Payment->Email,
+ 'telephone' => (string)$order_xml->Shipping->Phone,
+ 'fax' => '',
+ 'shipping_firstname' => $shipping_first_name,
+ 'shipping_lastname' => $shipping_last_name,
+ 'shipping_company' => '',
+ 'shipping_address_1' => (string)$order_xml->Shipping->AddressLine1,
+ 'shipping_address_2' => $address_line_2,
+ 'shipping_city' => (string)$order_xml->Shipping->City,
+ 'shipping_postcode' => (string)$order_xml->Shipping->PostCode,
+ 'shipping_country' => $this->model_extension_openbay_amazon_order->getCountryName((string)$order_xml->Shipping->CountryCode),
+ 'shipping_country_id' => $this->model_extension_openbay_amazon_order->getCountryId((string)$order_xml->Shipping->CountryCode),
+ 'shipping_zone' => (string)$order_xml->Shipping->State,
+ 'shipping_zone_id' => $this->model_extension_openbay_amazon_order->getZoneId((string)$order_xml->Shipping->State),
+ 'shipping_address_format' => '',
+ 'shipping_method' => (string)$order_xml->Shipping->Type,
+ 'shipping_code' => 'amazon.' . (string)$order_xml->Shipping->Type,
+ 'payment_firstname' => $shipping_first_name,
+ 'payment_lastname' => $shipping_last_name,
+ 'payment_company' => '',
+ 'payment_address_1' => (string)$order_xml->Shipping->AddressLine1,
+ 'payment_address_2' => $address_line_2,
+ 'payment_city' => (string)$order_xml->Shipping->City,
+ 'payment_postcode' => (string)$order_xml->Shipping->PostCode,
+ 'payment_country' => $this->model_extension_openbay_amazon_order->getCountryName((string)$order_xml->Shipping->CountryCode),
+ 'payment_country_id' => $this->model_extension_openbay_amazon_order->getCountryId((string)$order_xml->Shipping->CountryCode),
+ 'payment_zone' => (string)$order_xml->Shipping->State,
+ 'payment_zone_id' => $this->model_extension_openbay_amazon_order->getZoneId((string)$order_xml->Shipping->State),
+ 'payment_address_format' => '',
+ 'payment_method' => $this->language->get('text_paid_amazon'),
+ 'payment_code' => 'amazon.amazon',
+ 'payment_company_id' => 0,
+ 'payment_tax_id' => 0,
+ 'comment' => $order_comment,
+ 'total' => $total,
+ 'affiliate_id' => '0',
+ 'commission' => '0.00',
+ 'language_id' => (int)$this->config->get('config_language_id'),
+ 'currency_id' => $this->currency->getId($order_currency),
+ 'currency_code' => (string)$order_currency,
+ 'currency_value' => $this->currency->getValue($order_currency),
+ 'ip' => '',
+ 'forwarded_ip' => '',
+ 'user_agent' => 'OpenBay Pro for Amazon',
+ 'accept_language' => '',
+ 'products' => $products,
+ 'vouchers' => array(),
+ 'marketing_id' => 0,
+ 'tracking' => 0,
+ 'totals' => array(
+ array(
+ 'code' => 'sub_total',
+ 'title' => $this->language->get('text_total_sub'),
+ 'value' => sprintf('%.4f', $products_total),
+ 'sort_order' => '1',
+ ),
+ array(
+ 'code' => 'shipping',
+ 'title' => $this->language->get('text_total_shipping'),
+ 'value' => sprintf('%.4f', $products_shipping),
+ 'sort_order' => '3',
+ ),
+ array(
+ 'code' => 'tax',
+ 'title' => $this->language->get('text_tax'),
+ 'value' => sprintf('%.4f', $products_tax),
+ 'sort_order' => '4',
+ ),
+ array(
+ 'code' => 'shipping_tax',
+ 'title' => $this->language->get('text_total_shipping_tax'),
+ 'value' => sprintf('%.4f', $products_shipping_tax),
+ 'sort_order' => '6',
+ ),
+ array(
+ 'code' => 'gift_wrap',
+ 'title' => $this->language->get('text_total_giftwrap'),
+ 'value' => sprintf('%.4f', $gift_wrap),
+ 'sort_order' => '2',
+ ),
+ array(
+ 'code' => 'gift_wrap_tax',
+ 'title' => $this->language->get('text_total_giftwrap_tax'),
+ 'value' => sprintf('%.4f', $gift_wrap_tax),
+ 'sort_order' => '5',
+ ),
+ array(
+ 'code' => 'total',
+ 'title' => $this->language->get('text_total'),
+ 'value' => sprintf('%.4f', $total),
+ 'sort_order' => '7',
+ ),
+ ),
+ );
+
+ $order_id = $this->model_checkout_order->addOrder($order);
+
+ $this->model_extension_openbay_amazon_order->updateOrderStatus($order_id, $order_status);
+ $this->model_extension_openbay_amazon_order->addAmazonOrder($order_id, $amazon_order_id);
+ $this->model_extension_openbay_amazon_order->addAmazonOrderProducts($order_id, $product_mapping);
+
+ foreach($products as $product) {
+ if($product['product_id'] != 0) {
+ $this->model_extension_openbay_amazon_order->decreaseProductQuantity($product['product_id'], $product['quantity'], $product['var']);
+ }
+ }
+
+ $logger->write('Order ' . $amazon_order_id . ' was added to the database (ID: ' . $order_id . ')');
+ $logger->write("Finished processing the order");
+
+ $this->model_extension_openbay_amazon_order->acknowledgeOrder($order_id);
+
+ if($this->config->get('openbay_amazon_notify_admin') == 1){
+ $this->openbay->newOrderAdminNotify($order_id, $order_status);
+ }
+
+ $this->event->trigger('model/checkout/order/addOrderHistory/after', array('model/checkout/order/addOrderHistory/after', array($order_id, $order_status)));
+
+ $logger->write("Ok");
+ $this->response->setOutput('Ok');
+ }
+
+ public function listing() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazon_listing');
+ $this->load->model('extension/openbay/amazon_product');
+
+ $logger = new Log('amazon_listing.log');
+ $logger->write('amazon/listing - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazon_token'), $incoming_token)) {
+ $logger->write('amazon/listing - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazon/order Failed to decrypt data');
+ return;
+ }
+
+ $data = json_decode($decrypted, 1);
+
+ $logger->write("Received data: " . print_r($data, 1));
+
+ if ($data['status']) {
+ $logger->write("Updating " . $data['product_id'] . ' from ' . $data['marketplace'] . ' as successful');
+ $this->model_extension_openbay_amazon_listing->listingSuccessful($data['product_id'], $data['marketplace']);
+ $this->model_extension_openbay_amazon_product->linkProduct($data['sku'], $data['product_id']);
+ $logger->write("Updated successfully");
+ } else {
+ $logger->write("Updating " . $data['product_id'] . ' from ' . $data['marketplace'] . ' as failed');
+ $this->model_extension_openbay_amazon_listing->listingFailed($data['product_id'], $data['marketplace'], $data['messages']);
+ $logger->write("Updated successfully");
+ }
+ }
+
+ public function listingReport() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazon_product');
+
+ $logger = new Log('amazon.log');
+ $logger->write('amazon/listing_reports - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazon_token'), $incoming_token)) {
+ $logger->write('amazon/listing_reports - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazon/listing_reports - Failed to decrypt data');
+ return;
+ }
+
+ $logger->write('Received Listing Report: ' . $decrypted);
+
+ $request = json_decode($decrypted, 1);
+
+ $data = array();
+
+ foreach ($request['products'] as $product) {
+ $data[] = array(
+ 'marketplace' => $request['marketplace'],
+ 'sku' => $product['sku'],
+ 'quantity' => $product['quantity'],
+ 'asin' => $product['asin'],
+ 'price' => $product['price'],
+ );
+ }
+
+ if ($data) {
+ $this->model_extension_openbay_amazon_product->addListingReport($data);
+ }
+
+ $this->model_extension_openbay_amazon_product->removeListingReportLock($request['marketplace']);
+
+ $logger->write('amazon/listing_reports - Finished');
+ }
+
+ public function product() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ $this->response->setOutput("disabled");
+ return;
+ }
+
+ ob_start();
+
+ $this->load->model('extension/openbay/amazon_product');
+ $logger = new Log('amazon_product.log');
+
+ $logger->write("AmazonProduct/inbound: incoming data");
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if($incoming_token != $this->config->get('openbay_amazon_token')) {
+ $logger->write("Error - Incorrect token: " . $this->request->post['token']);
+ ob_get_clean();
+ $this->response->setOutput("tokens did not match");
+
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if(!$decrypted) {
+ $logger->write("Error - Failed to decrypt received data.");
+ ob_get_clean();
+ $this->response->setOutput("failed to decrypt");
+
+ return;
+ }
+
+ $decoded_data = (array)json_decode($decrypted);
+ $logger->write("Received data: " . print_r($decoded_data, true));
+ $status = $decoded_data['status'];
+
+ if($status == "submit_error") {
+ $message = 'Product was not submited to amazon properly. Please try again or contact OpenBay.';
+ $this->model_extension_openbay_amazon_product->setSubmitError($decoded_data['insertion_id'], $message);
+ } else {
+ $status = (array)$status;
+ if($status['successful'] == 1) {
+ $this->model_extension_openbay_amazon_product->setStatus($decoded_data['insertion_id'], 'ok');
+ $insertion_product = $this->model_extension_openbay_amazon_product->getProduct($decoded_data['insertion_id']);
+ $this->model_extension_openbay_amazon_product->linkProduct($insertion_product['sku'], $insertion_product['product_id'], $insertion_product['var']);
+ $this->model_extension_openbay_amazon_product->deleteErrors($decoded_data['insertion_id']);
+
+ $quantity_data = array(
+ $insertion_product['sku'] => $this->model_extension_openbay_amazon_product->getProductQuantity($insertion_product['product_id'], $insertion_product['var'])
+ );
+ $logger->write('Updating quantity with data: ' . print_r($quantity_data, true));
+ $logger->write('Response: ' . print_r($this->openbay->amazon->updateQuantities($quantity_data), true));
+ } else {
+ $msg = 'Product was not accepted by amazon. Please try again or contact OpenBay.';
+ $this->model_extension_openbay_amazon_product->setSubmitError($decoded_data['insertion_id'], $msg);
+
+ if(isset($decoded_data['error_details'])) {
+ foreach($decoded_data['error_details'] as $error) {
+ $error = (array)$error;
+ $error_data = array(
+ 'sku' => $error['sku'],
+ 'error_code' => $error['error_code'],
+ 'message' => $error['message'],
+ 'insertion_id' => $decoded_data['insertion_id']
+ );
+ $this->model_extension_openbay_amazon_product->insertError($error_data);
+ }
+ }
+ }
+ }
+
+ $logger->write("Data processed successfully.");
+ ob_get_clean();
+ $this->response->setOutput("ok");
+ }
+
+ public function search() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazon_product');
+
+ $logger = new Log('amazon.log');
+ $logger->write('amazon/search - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazon_token'), $incoming_token)) {
+ $logger->write('amazon/search - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazon/search Failed to decrypt data');
+ return;
+ }
+
+ $logger->write($decrypted);
+
+ $json = json_decode($decrypted, 1);
+
+ $this->model_extension_openbay_amazon_product->updateSearch($json);
+ }
+
+ public function dev() {
+ if ($this->config->get('openbay_amazon_status') != '1') {
+ $this->response->setOutput("error 001");
+ return;
+ }
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if ($incoming_token != $this->config->get('openbay_amazon_token')) {
+ $this->response->setOutput("error 002");
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazon->getEncryptionKey(), $this->openbay->amazon->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $this->response->setOutput("error 003");
+ return;
+ }
+
+ $data_xml = simplexml_load_string(base64_decode($decrypted));
+
+ if(!isset($data_xml->action)) {
+ $this->response->setOutput("error 004");
+ return;
+ }
+
+ $action = trim((string)$data_xml->action);
+
+ if ($action === "get_amazon_product") {
+ if(!isset($data_xml->product_id)) {
+ $this->response->setOutput("error 005");
+ return;
+ }
+
+ $product_id = trim((string)$data_xml->product_id);
+
+ if ($product_id === "all") {
+ $all_rows = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_product`")->rows;
+
+ $response = array();
+ foreach ($all_rows as $row) {
+ unset($row['data']);
+ $response[] = $row;
+ }
+
+ $this->response->setOutput(print_r($response, true));
+ return;
+ } else {
+ $response = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazon_product` WHERE `product_id` = '" . (int)$product_id . "'")->rows;
+
+ $this->response->setOutput(print_r($response, true));
+ return;
+ }
+ } else {
+ $this->response->setOutput("error 999");
+ return;
+ }
+ }
+
+ public function eventAddOrderHistory($route, $data) {
+ $logger = new \Log('amazon.log');
+ $logger->write('eventAddOrderHistory Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('extension/openbay/amazon_order');
+
+ $logger->write('Order ID: ' . (int)$data[0]);
+
+ $this->model_extension_openbay_amazon_order->addOrderHistory((int)$data[0]);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/openbay/amazonus.php b/public/catalog/controller/extension/openbay/amazonus.php
new file mode 100644
index 0000000..7bdfb8b
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/amazonus.php
@@ -0,0 +1,591 @@
+<?php
+class ControllerExtensionOpenbayAmazonus extends Controller {
+ public function order() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ return;
+ }
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/openbay/amazonus_order');
+ $this->load->language('extension/openbay/amazonus_order');
+
+ $logger = new Log('amazonus.log');
+ $logger->write('amazonus/order - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazonus_token'), $incoming_token)) {
+ $logger->write('amazon/order - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazonus/order Failed to decrypt data');
+ return;
+ }
+
+ $order_xml = simplexml_load_string($decrypted);
+
+ $amazonus_order_status = trim(strtolower((string)$order_xml->Status));
+
+ $amazonus_order_id = (string)$order_xml->AmazonOrderId;
+ $order_status = $this->model_extension_openbay_amazonus_order->getMappedStatus((string)$order_xml->Status);
+
+ $logger->write('Received order ' . $amazonus_order_id);
+
+ $order_id = $this->model_extension_openbay_amazonus_order->getOrderId($amazonus_order_id);
+
+ // If the order already exists on opencart, ignore it.
+ if ($order_id) {
+ $logger->write("Duplicate order $amazonus_order_id. Terminating.");
+ $this->response->setOutput('Ok');
+ return;
+ }
+
+ /* Check if order comes from subscribed marketplace */
+
+ $currency_to = $this->config->get('config_currency');
+ $order_currency = (string)$order_xml->Payment->CurrencyCode;
+
+ $products = array();
+
+ $products_total = 0;
+ $products_shipping = 0;
+ $products_tax = 0;
+ $products_shipping_tax = 0;
+ $gift_wrap = 0;
+ $gift_wrap_tax = 0;
+
+ $product_count = 0;
+
+ $amazonus_order_id = (string)$order_xml->AmazonOrderId;
+
+ /* SKU => ORDER_ITEM_ID */
+ $product_mapping = array();
+ $product_gift_messages = array();
+
+ foreach ($order_xml->Items->Item as $item) {
+
+ $total_price = $this->currency->convert((double)$item->Totals->Price, $order_currency, $currency_to);
+ $tax_total = (double)$item->Totals->Tax;
+
+ if ($tax_total == 0 && $this->config->get('openbay_amazonus_order_tax') > 0) {
+ $tax_total = (double)$item->Totals->Price * ($this->config->get('openbay_amazonus_order_tax') / 100) / (1 + $this->config->get('openbay_amazonus_order_tax') / 100);
+ }
+
+ $tax_total = $this->currency->convert($tax_total, $order_currency, $currency_to);
+
+ $products_total += $total_price;
+ $products_tax += $tax_total;
+
+ $products_shipping += $this->currency->convert((double)$item->Totals->Shipping, $order_currency, $currency_to);
+
+ $shipping_tax = (double)$item->Totals->ShippingTax;
+
+ if ($shipping_tax == 0 && $this->config->get('openbay_amazonus_order_tax') > 0) {
+ $shipping_tax = (double)$item->Totals->Shipping * ($this->config->get('openbay_amazonus_order_tax') / 100) / (1 + $this->config->get('openbay_amazonus_order_tax') / 100);
+ }
+
+ $products_shipping_tax += $this->currency->convert($shipping_tax, $order_currency, $currency_to);
+
+ $gift_wrap += $this->currency->convert((double)$item->Totals->GiftWrap, $order_currency, $currency_to);
+
+ $item_gift_wrap_tax = (double)$item->Totals->GiftWrapTax;
+
+ if ($item_gift_wrap_tax == 0 && $this->config->get('openbay_amazonus_order_tax') > 0) {
+ $item_gift_wrap_tax = (double)$item->Totals->GiftWrap * ($this->config->get('openbay_amazonus_order_tax') / 100) / (1 + $this->config->get('openbay_amazonus_order_tax') / 100);
+ }
+
+ $gift_wrap_tax += $this->currency->convert($item_gift_wrap_tax, $order_currency, $currency_to);
+
+ $product_count += (int)$item->Ordered;
+
+ if ((int)$item->Ordered == 0) {
+ continue;
+ }
+
+ $product_id = $this->model_extension_openbay_amazonus_order->getProductId((string)$item->Sku);
+ $product_var = $this->model_extension_openbay_amazonus_order->getProductVar((string)$item->Sku);
+
+ $products[] = array(
+ 'product_id' => $product_id,
+ 'var' => $product_var,
+ 'sku' => (string)$item->Sku,
+ 'asin' => (string)$item->Asin,
+ 'order_item_id' => (string)$item->OrderItemId,
+ 'name' => (string)$item->Title,
+ 'model' => (string)$item->Sku,
+ 'quantity' => (int)$item->Ordered,
+ 'price' => sprintf('%.4f', ($total_price - $tax_total) / (int)$item->Ordered),
+ 'total' => sprintf('%.4f', $total_price - $tax_total),
+ 'tax' => $tax_total / (int)$item->Ordered,
+ 'reward' => '0',
+ 'option' => $this->model_extension_openbay_amazonus_order->getProductOptionsByVar($product_var),
+ 'download' => array(),
+ );
+
+ $product_mapping[(string)$item->Sku] = (string)$item->OrderItemId;
+
+ if ($item->GiftMessage != '') {
+ $product_gift_messages[] = (string)$item->Title . ' : ' . (string)$item->GiftMessage;
+ }
+ }
+
+ $order_comment = '';
+ if (count($product_gift_messages) > 0) {
+ $order_comment = $this->language->get('text_gift_message') . '<br />' . implode('<br />', $product_gift_messages);
+ }
+
+ $total = sprintf('%.4f', $this->currency->convert((double)$order_xml->Payment->Amount, $order_currency, $currency_to));
+
+ $address_line_2 = (string)$order_xml->Shipping->AddressLine2;
+ if ((string)$order_xml->Shipping->AddressLine3 != '') {
+ $address_line_2 .= ', ' . (string)$order_xml->Shipping->AddressLine3;
+ }
+
+ $customer_info = $this->db->query("SELECT `customer_id` FROM " . DB_PREFIX . "customer WHERE email = '" . $this->db->escape((string)$order_xml->Payment->Email) . "'")->row;
+ $customer_id = '0';
+
+ if(isset($customer_info['customer_id'])) {
+ $customer_id = $customer_info['customer_id'];
+ } else {
+ /* Add a new customer */
+ $customer_data = array(
+ 'firstname' => (string)$order_xml->Shipping->Name,
+ 'lastname' => '',
+ 'email' => (string)$order_xml->Payment->Email,
+ 'telephone' => (string)$order_xml->Shipping->Phone,
+ 'fax' => '',
+ 'newsletter' => '0',
+ 'customer_group_id' => $this->config->get('openbay_amazonus_order_customer_group'),
+ 'password' => '',
+ 'status' => '0',
+ );
+
+ $this->db->query("
+ INSERT INTO " . DB_PREFIX . "customer
+ SET firstname = '" . $this->db->escape($customer_data['firstname']) . "',
+ lastname = '" . $this->db->escape($customer_data['lastname']) . "',
+ email = '" . $this->db->escape($customer_data['email']) . "',
+ telephone = '" . $this->db->escape($customer_data['telephone']) . "',
+ newsletter = '" . (int)$customer_data['newsletter'] . "',
+ customer_group_id = '" . (int)$customer_data['customer_group_id'] . "',
+ password = '',
+ status = '" . (int)$customer_data['status'] . "',
+ date_added = NOW()");
+
+ $customer_id = $this->db->getLastId();
+ }
+
+ $shipping_first_name = (string)$order_xml->Shipping->FirstName;
+ $shipping_last_name = (string)$order_xml->Shipping->LastName;
+
+ if (empty($shipping_first_name) || empty($shipping_last_name)) {
+ $shipping_first_name = (string)$order_xml->Shipping->Name;
+ $shipping_last_name = '';
+ }
+
+ $order = array(
+ 'invoice_prefix' => $this->config->get('config_invoice_prefix'),
+ 'store_id' => $this->config->get('config_store_id'),
+ 'store_name' => $this->config->get('config_name') . ' / Amazon US',
+ 'store_url' => $this->config->get('config_url'),
+ 'customer_id' => (int)$customer_id,
+ 'customer_group_id' => $this->config->get('openbay_amazonus_order_customer_group'),
+ 'firstname' => $shipping_first_name,
+ 'lastname' => $shipping_last_name,
+ 'email' => (string)$order_xml->Payment->Email,
+ 'telephone' => (string)$order_xml->Shipping->Phone,
+ 'shipping_firstname' => $shipping_first_name,
+ 'shipping_lastname' => $shipping_last_name,
+ 'shipping_company' => '',
+ 'shipping_address_1' => (string)$order_xml->Shipping->AddressLine1,
+ 'shipping_address_2' => $address_line_2,
+ 'shipping_city' => (string)$order_xml->Shipping->City,
+ 'shipping_postcode' => (string)$order_xml->Shipping->PostCode,
+ 'shipping_country' => $this->model_extension_openbay_amazonus_order->getCountryName((string)$order_xml->Shipping->CountryCode),
+ 'shipping_country_id' => $this->model_extension_openbay_amazonus_order->getCountryId((string)$order_xml->Shipping->CountryCode),
+ 'shipping_zone' => (string)$order_xml->Shipping->State,
+ 'shipping_zone_id' => $this->model_extension_openbay_amazonus_order->getZoneId((string)$order_xml->Shipping->State),
+ 'shipping_address_format' => '',
+ 'shipping_method' => (string)$order_xml->Shipping->Type,
+ 'shipping_code' => 'amazonus.' . (string)$order_xml->Shipping->Type,
+ 'payment_firstname' => $shipping_first_name,
+ 'payment_lastname' => $shipping_last_name,
+ 'payment_company' => '',
+ 'payment_address_1' => (string)$order_xml->Shipping->AddressLine1,
+ 'payment_address_2' => $address_line_2,
+ 'payment_city' => (string)$order_xml->Shipping->City,
+ 'payment_postcode' => (string)$order_xml->Shipping->PostCode,
+ 'payment_country' => $this->model_extension_openbay_amazonus_order->getCountryName((string)$order_xml->Shipping->CountryCode),
+ 'payment_country_id' => $this->model_extension_openbay_amazonus_order->getCountryId((string)$order_xml->Shipping->CountryCode),
+ 'payment_zone' => (string)$order_xml->Shipping->State,
+ 'payment_zone_id' => $this->model_extension_openbay_amazonus_order->getZoneId((string)$order_xml->Shipping->State),
+ 'payment_address_format' => '',
+ 'payment_method' => $this->language->get('text_paid_amazon'),
+ 'payment_code' => 'amazonus.amazonus',
+ 'payment_company_id' => 0,
+ 'payment_tax_id' => 0,
+ 'comment' => $order_comment,
+ 'total' => $total,
+ 'affiliate_id' => '0',
+ 'commission' => '0.00',
+ 'language_id' => (int)$this->config->get('config_language_id'),
+ 'currency_id' => $this->currency->getId($order_currency),
+ 'currency_code' => (string)$order_currency,
+ 'currency_value' => $this->currency->getValue($order_currency),
+ 'ip' => '',
+ 'forwarded_ip' => '',
+ 'user_agent' => 'OpenBay Pro for Amazon US',
+ 'accept_language' => '',
+ 'products' => $products,
+ 'vouchers' => array(),
+ 'marketing_id' => 0,
+ 'tracking' => 0,
+ 'totals' => array(
+ array(
+ 'code' => 'sub_total',
+ 'title' => $this->language->get('text_total_sub'),
+ 'value' => sprintf('%.4f', $products_total),
+ 'sort_order' => '1',
+ ),
+ array(
+ 'code' => 'shipping',
+ 'title' => $this->language->get('text_total_shipping'),
+ 'value' => sprintf('%.4f', $products_shipping),
+ 'sort_order' => '3',
+ ),
+ array(
+ 'code' => 'tax',
+ 'title' => $this->language->get('text_tax'),
+ 'value' => sprintf('%.4f', $products_tax),
+ 'sort_order' => '4',
+ ),
+ array(
+ 'code' => 'shipping_tax',
+ 'title' => $this->language->get('text_total_shipping_tax'),
+ 'value' => sprintf('%.4f', $products_shipping_tax),
+ 'sort_order' => '6',
+ ),
+ array(
+ 'code' => 'gift_wrap',
+ 'title' => $this->language->get('text_total_giftwrap'),
+ 'value' => sprintf('%.4f', $gift_wrap),
+ 'sort_order' => '2',
+ ),
+ array(
+ 'code' => 'gift_wrap_tax',
+ 'title' => $this->language->get('text_total_giftwrap_tax'),
+ 'value' => sprintf('%.4f', $gift_wrap_tax),
+ 'sort_order' => '5',
+ ),
+ array(
+ 'code' => 'total',
+ 'title' => $this->language->get('text_total'),
+ 'value' => sprintf('%.4f', $total),
+ 'sort_order' => '7',
+ ),
+ ),
+ );
+
+ $order_id = $this->model_checkout_order->addOrder($order);
+
+ $this->model_extension_openbay_amazonus_order->updateOrderStatus($order_id, $order_status);
+ $this->model_extension_openbay_amazonus_order->addAmazonusOrder($order_id, $amazonus_order_id);
+ $this->model_extension_openbay_amazonus_order->addAmazonusOrderProducts($order_id, $product_mapping);
+
+ foreach($products as $product) {
+ if($product['product_id'] != 0) {
+ $this->model_extension_openbay_amazonus_order->decreaseProductQuantity($product['product_id'], $product['quantity'], $product['var']);
+ }
+ }
+
+ $logger->write('Order ' . $amazonus_order_id . ' was added to the database (ID: ' . $order_id . ')');
+ $logger->write("Finished processing the order");
+
+ $this->model_extension_openbay_amazonus_order->acknowledgeOrder($order_id);
+
+ //send an email to the administrator about the sale
+ if ($this->config->get('openbay_amazonus_notify_admin') == 1){
+ $this->openbay->newOrderAdminNotify($order_id, $order_status);
+ }
+
+ $this->event->trigger('model/checkout/order/addOrderHistory/after', array('model/checkout/order/addOrderHistory/after', array($order_id, $order_status)));
+
+ $logger->write("Ok");
+ $this->response->setOutput('Ok');
+ }
+
+ public function listing() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazonus_listing');
+ $this->load->model('extension/openbay/amazonus_product');
+
+ $logger = new Log('amazonus_listing.log');
+ $logger->write('amazonus/listing - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazonus_token'), $incoming_token)) {
+ $logger->write('amazonus/listing - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazonus/order Failed to decrypt data');
+ return;
+ }
+
+ $data = json_decode($decrypted, 1);
+
+ $logger->write("Received data: " . print_r($data, 1));
+
+ if ($data['status']) {
+ $logger->write("Updating " . $data['product_id'] . ' as successful');
+ $this->model_extension_openbay_amazonus_listing->listingSuccessful($data['product_id']);
+ $this->model_extension_openbay_amazonus_product->linkProduct($data['sku'], $data['product_id']);
+ $logger->write("Updated successfully");
+ } else {
+ $logger->write("Updating " . $data['product_id'] . ' as failed');
+ $this->model_extension_openbay_amazonus_listing->listingFailed($data['product_id'], $data['messages']);
+ $logger->write("Updated successfully");
+ }
+ }
+
+ public function listingReport() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazonus_product');
+
+ $logger = new Log('amazonus.log');
+ $logger->write('amazonus/listing_reports - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazonus_token'), $incoming_token)) {
+ $logger->write('amazonus/listing_reports - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazonus/listing_reports - Failed to decrypt data');
+ return;
+ }
+
+ $logger->write('Received Listing Report: ' . $decrypted);
+
+ $request = json_decode($decrypted, 1);
+
+ $data = array();
+
+ foreach ($request['products'] as $product) {
+ $data[] = array(
+ 'sku' => $product['sku'],
+ 'quantity' => $product['quantity'],
+ 'asin' => $product['asin'],
+ 'price' => $product['price'],
+ );
+ }
+
+ if ($data) {
+ $this->model_extension_openbay_amazonus_product->addListingReport($data);
+ }
+
+ $this->model_extension_openbay_amazonus_product->removeListingReportLock($request['marketplace']);
+
+ $logger->write('amazonus/listing_reports - Finished');
+ }
+
+ public function product() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ $this->response->setOutput("disabled");
+ return;
+ }
+
+ ob_start();
+
+ $this->load->model('extension/openbay/amazonus_product');
+ $logger = new Log('amazonus_product.log');
+
+ $logger->write("AmazonusProduct/inbound: incoming data");
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if($incoming_token != $this->config->get('openbay_amazonus_token')) {
+ $logger->write("Error - Incorrect token: " . $this->request->post['token']);
+ ob_get_clean();
+ $this->response->setOutput("tokens did not match");
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if(!$decrypted) {
+ $logger->write("Error - Failed to decrypt received data.");
+ ob_get_clean();
+ $this->response->setOutput("failed to decrypt");
+ return;
+ }
+
+ $decoded_data = (array)json_decode($decrypted);
+ $logger->write("Received data: " . print_r($decoded_data, true));
+ $status = $decoded_data['status'];
+
+ if($status == "submit_error") {
+ $message = 'Product was not submited to amazonus properly. Please try again or contact OpenBay.';
+ $this->model_extension_openbay_amazonus_product->setSubmitError($decoded_data['insertion_id'], $message);
+ } else {
+ $status = (array)$status;
+ if($status['successful'] == 1) {
+ $this->model_extension_openbay_amazonus_product->setStatus($decoded_data['insertion_id'], 'ok');
+ $insertion_product = $this->model_extension_openbay_amazonus_product->getProduct($decoded_data['insertion_id']);
+ $this->model_extension_openbay_amazonus_product->linkProduct($insertion_product['sku'], $insertion_product['product_id'], $insertion_product['var']);
+ $this->model_extension_openbay_amazonus_product->deleteErrors($decoded_data['insertion_id']);
+
+ $quantity_data = array(
+ $insertion_product['sku'] => $this->model_extension_openbay_amazonus_product->getProductQuantity($insertion_product['product_id'], $insertion_product['var'])
+ );
+ $logger->write('Updating quantity with data: ' . print_r($quantity_data, true));
+ $logger->write('Response: ' . print_r($this->openbay->amazonus->updateQuantities($quantity_data), true));
+ } else {
+ $msg = 'Product was not accepted by amazonus. Please try again or contact OpenBay.';
+ $this->model_extension_openbay_amazonus_product->setSubmitError($decoded_data['insertion_id'], $msg);
+
+ if(isset($decoded_data['error_details'])) {
+ foreach($decoded_data['error_details'] as $error) {
+ $error = (array)$error;
+ $error_data = array(
+ 'sku' => $error['sku'],
+ 'error_code' => $error['error_code'],
+ 'message' => $error['message'],
+ 'insertion_id' => $decoded_data['insertion_id']
+ );
+ $this->model_extension_openbay_amazonus_product->insertError($error_data);
+
+ }
+ }
+ }
+ }
+
+ $logger->write("Data processed successfully.");
+ ob_get_clean();
+ $this->response->setOutput("ok");
+ }
+
+ public function search() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ return;
+ }
+
+ $this->load->model('extension/openbay/amazonus_product');
+
+ $logger = new Log('amazonus.log');
+ $logger->write('amazonus/search - started');
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if (!hash_equals($this->config->get('openbay_amazonus_token'), $incoming_token)) {
+ $logger->write('amazonus/search - Incorrect token: ' . $incoming_token);
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $logger->write('amazonus/search Failed to decrypt data');
+ return;
+ }
+
+ $logger->write($decrypted);
+
+ $json = json_decode($decrypted, 1);
+
+ $this->model_extension_openbay_amazonus_product->updateSearch($json);
+ }
+
+ public function dev() {
+ if ($this->config->get('openbay_amazonus_status') != '1') {
+ $this->response->setOutput("error 001");
+ return;
+ }
+
+ $incoming_token = isset($this->request->post['token']) ? $this->request->post['token'] : '';
+
+ if ($incoming_token != $this->config->get('openbay_amazonus_token')) {
+ $this->response->setOutput("error 002");
+ return;
+ }
+
+ $decrypted = $this->openbay->decrypt($this->request->post['data'], $this->openbay->amazonus->getEncryptionKey(), $this->openbay->amazonus->getEncryptionIv(), false);
+
+ if (!$decrypted) {
+ $this->response->setOutput("error 003");
+ return;
+ }
+
+ $data_xml = simplexml_load_string($decrypted);
+
+ if(!isset($data_xml->action)) {
+ $this->response->setOutput("error 004");
+ return;
+ }
+
+ $action = trim((string)$data_xml->action);
+
+ if ($action === "get_amazonus_product") {
+ if(!isset($data_xml->product_id)) {
+ $this->response->setOutput("error 005");
+ return;
+ }
+
+ $product_id = trim((string)$data_xml->product_id);
+
+ if ($product_id === "all") {
+ $all_rows = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazonus_product`")->rows;
+
+ $response = array();
+
+ foreach ($all_rows as $row) {
+ unset($row['data']);
+ $response[] = $row;
+ }
+
+ $this->response->setOutput(print_r($response, true));
+
+ return;
+ } else {
+ $response = $this->db->query("SELECT * FROM `" . DB_PREFIX . "amazonus_product` WHERE `product_id` = '" . (int)$product_id . "'")->rows;
+
+ $this->response->setOutput(print_r($response, true));
+ return;
+ }
+ } else {
+ $this->response->setOutput("error 999");
+ return;
+ }
+ }
+
+ public function eventAddOrderHistory($route, $data) {
+ $logger = new \Log('amazonus.log');
+ $logger->write('eventAddOrderHistory Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('extension/openbay/amazonus_order');
+
+ $logger->write('Order ID: ' . (int)$data[0]);
+
+ $this->model_extension_openbay_amazonus_order->addOrderHistory((int)$data[0]);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/openbay/ebay.php b/public/catalog/controller/extension/openbay/ebay.php
new file mode 100644
index 0000000..1c4fecc
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/ebay.php
@@ -0,0 +1,201 @@
+<?php
+class ControllerExtensionOpenbayEbay extends Controller {
+ public function inbound() {
+ $post_data = $this->request->post;
+ $secret = $this->config->get('ebay_secret');
+ $active = $this->config->get('ebay_status');
+
+ $this->load->model('extension/openbay/ebay_product');
+ $this->load->model('extension/openbay/ebay_order');
+
+ if(empty($post_data)) {
+ http_response_code(400);
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('error' => 'Bad request')));
+ $this->response->output();
+ exit();
+ } else {
+ $data = $this->openbay->decrypt($post_data['data'], $this->openbay->ebay->getEncryptionKey(), $this->openbay->ebay->getEncryptionIv());
+
+ if(isset($data['secret']) && $secret == $data['secret'] && $active == 1) {
+ if($data['action'] == 'ItemUnsold') {
+ $this->openbay->ebay->log('Action: Unsold Item');
+ $product_id = $this->openbay->ebay->getProductId($data['itemId']);
+
+ if($product_id != false) {
+ $this->openbay->ebay->log('eBay item link found with internal product');
+ $rules = $this->model_extension_openbay_ebay_product->getRelistRule($data['itemId']);
+
+ if(!empty($rules)) {
+ $this->openbay->ebay->log('Item is due to be automatically relisted');
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "ebay_listing_pending` SET `ebay_item_id` = '" . $this->db->escape($data['itemId']) . "', `product_id` = '" . (int)$product_id . "', `key` = '" . $this->db->escape($data['key']) . "'");
+ $this->openbay->ebay->removeItemByItemId($data['itemId']);
+ } else {
+ $this->openbay->ebay->log('No automation rule set');
+ $this->openbay->ebay->removeItemByItemId($data['itemId']);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('msg' => 'ok')));
+ }
+
+ if($data['action'] == 'ItemListed') {
+ $this->openbay->ebay->log('Action: Listed Item');
+
+ $product_id = $this->openbay->ebay->getProductIdFromKey($data['key']);
+
+ if($product_id != false) {
+ $this->openbay->ebay->createLink($product_id, $data['itemId'], '');
+ $this->db->query("DELETE FROM `" . DB_PREFIX . "ebay_listing_pending` WHERE `key` = '" . $this->db->escape($data['key']) . "' LIMIT 1");
+ $this->openbay->ebay->log('A link was found with product id: ' . $product_id . ', item id: ' . $data['itemId'] . ' and key: ' . $data['key']);
+ } else {
+ $this->openbay->ebay->log('No link found to previous item');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('msg' => 'ok')));
+ }
+
+ if($data['action'] == 'newOrder') {
+ $this->openbay->ebay->log('Action: newOrder / Order data from polling');
+ $this->model_extension_openbay_ebay_order->importOrders($data['data2']);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('msg' => 'ok')));
+ }
+
+ if($data['action'] == 'notificationOrder') {
+ $this->openbay->ebay->log('Action: notificationOrder / Order data from notification');
+ $this->model_extension_openbay_ebay_order->importOrders($data['data']);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('msg' => 'ok')));
+ }
+
+ if($data['action'] == 'outputLog') {
+ if (file_exists(DIR_LOGS . "ebaylog.log")) {
+ header('Pragma: public');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+ header('Cache-Control: private', false);
+ header('Content-Type: application/force-download');
+ header('Content-Length: ' . filesize(DIR_LOGS . "ebaylog.log"));
+ header('Content-Disposition: attachment; filename="ebaylog.log"');
+ header('Content-Transfer-Encoding: binary');
+ header('Connection: close');
+ readfile(DIR_LOGS . "ebaylog.log");
+ exit();
+ } else {
+ $this->openbay->ebay->log('Action: outputLog / No log file found');
+
+ http_response_code(404);
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('error' => 'Log file not found')));
+ }
+ }
+
+ if($data['action'] == 'config') {
+ $this->openbay->ebay->log('Action: config / Check store php limits for import options');
+
+ $post_size = ini_get('post_max_size');
+ $post_size = (int)str_replace(array('M','m','Mb','MB'), '', $post_size);
+ $version = (int)$this->config->get('feed_openbaypro_version');
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('msg' => 'ok', 'max_post' => $post_size, 'version' => $version)));
+ }
+ } else {
+ $this->openbay->ebay->log('Secret incorrect or module not active.');
+
+ http_response_code(401);
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode(array('error' => 'Authorisation failed or module inactive')));
+ $this->response->output();
+ exit();
+ }
+ }
+ }
+
+ public function importItems() {
+ set_time_limit(0);
+
+ $data = $this->request->post;
+ $secret = $this->config->get('ebay_secret');
+ $active = $this->config->get('ebay_status');
+
+ $this->response->addHeader('Content-Type: application/json');
+
+ if(isset($data['secret']) && $secret == $data['secret'] && $active == 1 && isset($data['data'])) {
+ $this->load->model('extension/openbay/ebay_order');
+ $this->load->model('extension/openbay/ebay_product');
+ $this->model_extension_openbay_ebay_product->importItems($data);
+ $this->response->setOutput(json_encode(array('msg' => 'ok', 'error' => false)));
+ } else {
+ $this->response->setOutput(json_encode(array('msg' => 'Auth failed', 'error' => true)));
+ }
+ }
+
+ public function setup() {
+ @set_time_limit(0);
+
+ $this->load->model('setting/setting');
+ $settings = $this->model_setting_setting->getSetting('ebay');
+
+ $this->response->addHeader('Cache-Control: no-cache, must-revalidate');
+ $this->response->addHeader('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+ $this->response->addHeader('Content-type: application/json; charset=utf-8');
+
+ if(
+ (isset($settings['ebay_token']) && !empty($settings['ebay_token'])) ||
+ (isset($settings['ebay_secret']) && !empty($settings['ebay_secret'])) ||
+ (isset($settings['ebay_encryption_key']) && !empty($settings['ebay_encryption_key'])) ||
+ (isset($settings['ebay_encryption_iv']) && !empty($settings['ebay_encryption_iv'])) ||
+ !isset($this->request->post['token']) ||
+ !isset($this->request->post['secret']) ||
+ !isset($this->request->post['encryption_key']) ||
+ !isset($this->request->post['encryption_iv'])
+ ) {
+ $this->response->setOutput(json_encode(array('msg' => 'fail', 'reason' => 'Tokens are already setup or data missing')));
+ } else {
+ $settings['ebay_token'] = $this->request->post['token'];
+ $settings['ebay_secret'] = $this->request->post['secret'];
+ $settings['ebay_encryption_key'] = $this->request->post['encryption_key'];
+ $settings['ebay_encryption_iv'] = $this->request->post['encryption_iv'];
+
+ $this->openbay->ebay->editSetting('ebay', $settings);
+
+ $this->response->setOutput(json_encode(array('msg' => 'ok', 'reason' => 'Auto setup has completed','version' => (int)$this->config->get('feed_openbaypro_version'))));
+ }
+ }
+
+ public function sync() {
+ @set_time_limit(0);
+
+ $this->response->addHeader('Content-Type: application/json');
+
+ if($this->request->post['process'] == 'categories') {
+ $this->response->setOutput(json_encode($this->openbay->ebay->updateCategories()));
+ }elseif($this->request->post['process'] == 'settings') {
+ $this->response->setOutput(json_encode($this->openbay->ebay->updateSettings()));
+ }elseif($this->request->post['process'] == 'store') {
+ $this->response->setOutput(json_encode($this->openbay->ebay->updateStore()));
+ }
+ }
+
+ public function eventAddOrder($route, $data) {
+
+ }
+
+ public function eventAddOrderHistory($route, $data) {
+ $this->openbay->ebay->log('eventAddOrderHistory Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('extension/openbay/ebay_order');
+
+ $this->openbay->ebay->log('Order ID: ' . (int)$data[0]);
+
+ $this->model_extension_openbay_ebay_order->addOrderHistory((int)$data[0]);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/openbay/etsy.php b/public/catalog/controller/extension/openbay/etsy.php
new file mode 100644
index 0000000..9ced310
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/etsy.php
@@ -0,0 +1,69 @@
+<?php
+class ControllerExtensionOpenbayEtsy extends Controller {
+ public function inbound() {
+ if ($this->config->get('etsy_status') != '1') {
+ $this->openbay->etsy->log('etsy/inbound - module inactive (503)');
+ http_response_code(503);
+ exit();
+ }
+
+ $body = $this->request->post;
+
+ if (!isset($body['action']) || !isset($body['auth'])) {
+ $this->openbay->etsy->log('etsy/inbound - action or auth data not set (401)');
+ http_response_code(401);
+ exit();
+ }
+
+ $incoming_token = isset($body['auth']['token']) ? $body['auth']['token'] : '';
+
+ if (!hash_equals($this->config->get('etsy_token'), $incoming_token)) {
+ $this->openbay->etsy->log('etsy/inbound - Auth failed (401): ' . $incoming_token);
+ http_response_code(401);
+ exit();
+ }
+
+ $data = array();
+
+ if (isset($body['data']) && !empty($body['data'])) {
+ $decrypted = $this->openbay->decrypt($body['data'], $this->openbay->etsy->getEncryptionKey(), $this->openbay->etsy->getEncryptionIv());
+
+ if (!$decrypted) {
+ $this->openbay->etsy->log('etsy/inbound Failed to decrypt data');
+ http_response_code(400);
+ exit();
+ }
+
+ $data = json_decode($decrypted);
+ }
+
+ switch ($body['action']) {
+ case 'orders':
+ $this->load->model('extension/openbay/etsy_order');
+
+ $this->openbay->etsy->log('Orders action found');
+
+ $this->model_extension_openbay_etsy_order->inbound($data);
+
+ break;
+ case 'products';
+ $this->load->model('extension/openbay/etsy_product');
+
+ $this->model_extension_openbay_etsy_product->inbound($data);
+
+ break;
+ }
+ }
+
+ public function eventAddOrderHistory($route, $data) {
+ $this->openbay->etsy->log('eventAddOrderHistory Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('extension/openbay/etsy_order');
+
+ $this->openbay->etsy->log('Order ID: ' . (int)$data[0]);
+
+ $this->model_extension_openbay_etsy_order->addOrderHistory((int)$data[0]);
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/openbay/fba.php b/public/catalog/controller/extension/openbay/fba.php
new file mode 100644
index 0000000..76b5cd2
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/fba.php
@@ -0,0 +1,119 @@
+<?php
+class ControllerExtensionOpenbayFba extends Controller {
+ public function eventAddOrderHistory($route, $data) {
+ $this->openbay->fba->log('eventAddOrderHistory Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('checkout/order');
+ $this->load->model('account/order');
+ $this->load->model('catalog/product');
+
+ $this->openbay->fba->log('eventAddOrderHistory Event fired for order ID: ' . $data[0]);
+
+ $order = $this->model_checkout_order->getOrder($data[0]);
+
+ if ($order['shipping_method']) {
+ if ($this->config->get('openbay_fba_order_trigger_status') == $order['order_status_id']) {
+ $fba_fulfillment_id = $this->openbay->fba->createFBAFulfillmentID($data[0], 0);
+
+ $order_products = $this->model_account_order->getOrderProducts($data[0]);
+
+ $total_order_products = count($order_products);
+
+ $fulfillment_items = array();
+
+ foreach ($order_products as $order_product) {
+ $product = $this->model_catalog_product->getProduct($order_product['product_id']);
+
+ if ($product['location'] == 'FBA') {
+ $fulfillment_items[] = array(
+ 'seller_sku' => $product['sku'],
+ 'quantity' => $order_product['quantity'],
+ 'seller_fulfillment_order_item_id' => $this->config->get('openbay_fba_order_prefix') . $fba_fulfillment_id . '-' . $order_product['order_product_id'],
+ 'per_unit_declared_value' => array(
+ 'currency_code' => $order['currency_code'],
+ 'value' => number_format($order_product['price'], 2)
+ ),
+ );
+ }
+ }
+
+ $total_fulfillment_items = count($fulfillment_items);
+
+ if (($total_order_products == $total_fulfillment_items) || ($this->config->get('openbay_fba_only_fill_complete') != 1)) {
+ if (!empty($fulfillment_items)) {
+ $request = array();
+
+ $datetime = new DateTime($order['date_added']);
+ $request['displayable_order_datetime'] = $datetime->format(DateTime::ISO8601);
+
+ $request['seller_fulfillment_order_id'] = $this->config->get('openbay_fba_order_prefix') . $data[0] . '-' . $fba_fulfillment_id;
+ $request['displayable_order_id'] = $data[0];
+ $request['displayable_order_comment'] = 'none';
+ $request['shipping_speed_category'] = $this->config->get('openbay_fba_shipping_speed');
+ $request['fulfillment_action'] = ($this->config->get('openbay_fba_send_orders') == 1 ? 'Ship' : 'Hold');
+ $request['fulfillment_policy'] = $this->config->get('openbay_fba_fulfill_policy');
+
+ $request['destination_address'] = array(
+ 'name' => $order['shipping_firstname'] . ' ' . $order['shipping_lastname'],
+ 'line_1' => (!empty($order['shipping_company']) ? $order['shipping_company'] : $order['shipping_address_1']),
+ 'line_2' => (!empty($order['shipping_company']) ? $order['shipping_address_1'] : $order['shipping_address_2']),
+ 'line_3' => (!empty($order['shipping_company']) ? $order['shipping_address_2'] : ''),
+ 'state_or_province_code' => $order['shipping_zone'],
+ 'city' => $order['shipping_city'],
+ 'country_code' => $order['shipping_iso_code_2'],
+ 'postal_code' => $order['shipping_postcode'],
+ );
+
+ $request['items'] = $fulfillment_items;
+
+ $response = $this->openbay->fba->call("v1/fba/fulfillments/", $request, 'POST');
+
+ if ($response['response_http'] != 201) {
+ /**
+ * @todo notify the admin about any errors
+ */
+ $this->openbay->fba->updateFBAOrderStatus($data[0], 1);
+ } else {
+ if ($this->config->get('openbay_fba_send_orders') == 1) {
+ $this->openbay->fba->updateFBAOrderStatus($data[0], 3);
+ } else {
+ $this->openbay->fba->updateFBAOrderStatus($data[0], 2);
+ }
+
+ $this->openbay->fba->updateFBAOrderRef($data[0], $this->config->get('openbay_fba_order_prefix') . $data[0] . '-' . $fba_fulfillment_id);
+ }
+
+ $this->openbay->fba->populateFBAFulfillment(json_encode($request), json_encode($response), $response['response_http'], $fba_fulfillment_id);
+ $this->openbay->fba->updateFBAOrderFulfillmentID($data[0], $fba_fulfillment_id);
+ } else {
+ $this->openbay->fba->log('No FBA items found for this order');
+ }
+ } else {
+ $this->openbay->fba->log('Products:' . $total_order_products . ', Fulfillment products: ' . $total_fulfillment_items . ' - settings do not allow incomplete order fulfillment.');
+ }
+ }
+ }
+
+ // how about notifications? does the merchant want a notification that here is a new fulfillment ready to be checked over?
+ // alert of any missing products that were not in FBA?
+ // any errors returned by FBA?
+ }
+ }
+
+ public function eventAddOrder($route, $data) {
+ $this->openbay->fba->log('eventAddOrder Event fired: ' . $route);
+
+ if (isset($data[0]) && !empty($data[0])) {
+ $this->load->model('checkout/order');
+
+ $this->openbay->fba->log('Order ID: ' . (int)$data[0]);
+
+ $order = $this->model_checkout_order->getOrder((int)$data[0]);
+
+ if ($order['shipping_method']) {
+ $this->openbay->fba->createFBAOrderID((int)$data[0]);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/openbay/openbay.php b/public/catalog/controller/extension/openbay/openbay.php
new file mode 100644
index 0000000..3a5f335
--- /dev/null
+++ b/public/catalog/controller/extension/openbay/openbay.php
@@ -0,0 +1,12 @@
+<?php
+class ControllerExtensionOpenbayOpenbay extends Controller {
+ public function index() {
+ $this->response->addHeader('Cache-Control: no-cache, must-revalidate');
+ $this->response->addHeader('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+ $this->response->addHeader('Content-type: application/json; charset=utf-8');
+ $this->response->addHeader('X-Openbay-Header: hello');
+
+ http_response_code(200);
+ $this->response->setOutput(json_encode(array('reply' => 'hello')));
+ }
+}
diff --git a/public/catalog/controller/extension/payment/alipay.php b/public/catalog/controller/extension/payment/alipay.php
new file mode 100644
index 0000000..51bd26c
--- /dev/null
+++ b/public/catalog/controller/extension/payment/alipay.php
@@ -0,0 +1,76 @@
+<?php
+class ControllerExtensionPaymentAlipay extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $config = array (
+ 'app_id' => $this->config->get('payment_alipay_app_id'),
+ 'merchant_private_key' => $this->config->get('payment_alipay_merchant_private_key'),
+ 'notify_url' => HTTPS_SERVER . "payment_callback/alipay",
+ 'return_url' => $this->url->link('checkout/success'),
+ 'charset' => "UTF-8",
+ 'sign_type' => "RSA2",
+ 'gateway_url' => $this->config->get('payment_alipay_test') == "sandbox" ? "https://openapi.alipaydev.com/gateway.do" : "https://openapi.alipay.com/gateway.do",
+ 'alipay_public_key' => $this->config->get('payment_alipay_alipay_public_key'),
+ );
+ $out_trade_no = trim($order_info['order_id']);
+ $subject = trim($this->config->get('config_name'));
+ $total_amount = trim($this->currency->format($order_info['total'], 'CNY', '', false));
+ $body = '';//trim($_POST['WIDbody']);
+
+ $payRequestBuilder = array(
+ 'body' => $body,
+ 'subject' => $subject,
+ 'total_amount' => $total_amount,
+ 'out_trade_no' => $out_trade_no,
+ 'product_code' => 'FAST_INSTANT_TRADE_PAY'
+ );
+
+ $this->load->model('extension/payment/alipay');
+
+ $response = $this->model_extension_payment_alipay->pagePay($payRequestBuilder,$config);
+ $data['action'] = $config['gateway_url'] . "?charset=" . $this->model_extension_payment_alipay->getPostCharset();
+ $data['form_params'] = $response;
+
+ return $this->load->view('extension/payment/alipay', $data);
+ }
+
+ public function callback() {
+ $this->log->write('alipay pay notify:');
+ $arr = $_POST;
+ $config = array (
+ 'app_id' => $this->config->get('payment_alipay_app_id'),
+ 'merchant_private_key' => $this->config->get('payment_alipay_merchant_private_key'),
+ 'notify_url' => HTTPS_SERVER . "payment_callback/alipay",
+ 'return_url' => $this->url->link('checkout/success'),
+ 'charset' => "UTF-8",
+ 'sign_type' => "RSA2",
+ 'gateway_url' => $this->config->get('payment_alipay_test') == "sandbox" ? "https://openapi.alipaydev.com/gateway.do" : "https://openapi.alipay.com/gateway.do",
+ 'alipay_public_key' => $this->config->get('payment_alipay_alipay_public_key'),
+ );
+ $this->load->model('extension/payment/alipay');
+ $this->log->write('POST' . var_export($_POST,true));
+ $result = $this->model_extension_payment_alipay->check($arr, $config);
+
+ if($result) {//check successed
+ $this->log->write('Alipay check successed');
+ $order_id = $_POST['out_trade_no'];
+ if($_POST['trade_status'] == 'TRADE_FINISHED') {
+ }
+ else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
+ $this->load->model('checkout/order');
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_alipay_order_status_id'));
+ }
+ echo "success"; //Do not modified or deleted
+ }else {
+ $this->log->write('Alipay check failed');
+ //chedk failed
+ echo "fail";
+
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/alipay_cross.php b/public/catalog/controller/extension/payment/alipay_cross.php
new file mode 100644
index 0000000..2acce97
--- /dev/null
+++ b/public/catalog/controller/extension/payment/alipay_cross.php
@@ -0,0 +1,87 @@
+<?php
+class ControllerExtensionPaymentAlipayCross extends Controller {
+ var $alipay_gateway = 'https://mapi.alipay.com/gateway.do?';
+ var $alipay_gateway_test = 'https://openapi.alipaydev.com/gateway.do?';
+
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $out_trade_no = str_pad($order_info['order_id'], 7, "0",STR_PAD_LEFT); // Length must be greater than 7
+ $subject = trim($this->config->get('config_name'));
+ $currency = $this->config->get('payment_alipay_cross_currency');
+ $total_fee = trim($this->currency->format($order_info['total'], $currency, '', false));
+ $total_fee_cny = trim($this->currency->format($order_info['total'], 'CNY', '', false));
+ $body = trim($this->config->get('config_name'));
+
+ $alipay_config = array (
+ 'partner' => $this->config->get('payment_alipay_cross_app_id'),
+ 'key' => $this->config->get('payment_alipay_cross_merchant_private_key'),
+ 'notify_url' => HTTPS_SERVER . "payment_callback/alipay_cross",
+ 'return_url' => $this->url->link('checkout/success'),
+ 'sign_type' => strtoupper('MD5'),
+ 'input_charset' => strtolower('utf-8'),
+ 'cacert' => getcwd().'/cacert.pem',
+ 'transport' => 'https',
+ 'service' => 'create_forex_trade'
+ );
+
+ $parameter = array(
+ "service" => $alipay_config['service'],
+ "partner" => $alipay_config['partner'],
+ "notify_url" => $alipay_config['notify_url'],
+ "return_url" => $alipay_config['return_url'],
+
+ "out_trade_no" => $out_trade_no,
+ "subject" => $subject,
+ "body" => $body,
+ "currency" => $currency,
+ "_input_charset" => trim(strtolower($alipay_config['input_charset']))
+ );
+ if ($this->session->data['currency'] == 'CNY') {
+ $parameter['rmb_fee'] = $total_fee_cny;
+ } else {
+ $parameter['total_fee'] = $total_fee;
+ }
+
+ $this->load->model('extension/payment/alipay_cross');
+ $data['params'] = $this->model_extension_payment_alipay_cross->buildRequestPara($alipay_config, $parameter);
+ $gateway = $this->config->get('payment_alipay_cross_test') == "sandbox" ? $this->alipay_gateway_test : $this->alipay_gateway;
+ $data['action'] = $gateway . "_input_charset=".trim($alipay_config['input_charset']);
+
+ return $this->load->view('extension/payment/alipay_cross', $data);
+ }
+
+ public function callback() {
+ $this->log->write('alipay cross payment notify:');
+ $alipay_config = array (
+ 'partner' => $this->config->get('payment_alipay_cross_app_id'),
+ 'key' => $this->config->get('payment_alipay_cross_merchant_private_key'),
+ 'sign_type' => strtoupper('MD5'),
+ 'input_charset' => strtolower('utf-8'),
+ 'cacert' => getcwd().'/cacert.pem'
+ );
+ $this->load->model('extension/payment/alipay_cross');
+ $this->log->write('config: ' . var_export($alipay_config,true));
+ $verify_result = $this->model_extension_payment_alipay_cross->verifyNotify($alipay_config);
+
+ if($verify_result) {//check successed
+ $this->log->write('Alipay cross check successed');
+ $order_id = $_POST['out_trade_no'];
+ if($_POST['trade_status'] == 'TRADE_FINISHED') {
+ $this->load->model('checkout/order');
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_alipay_cross_order_status_id'));
+ } else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
+ }
+ echo "success"; //Do not modified or deleted
+ } else {
+ $this->log->write('Alipay cross check failed');
+ //chedk failed
+ echo "fail";
+
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/amazon_login_pay.php b/public/catalog/controller/extension/payment/amazon_login_pay.php
new file mode 100644
index 0000000..c76844d
--- /dev/null
+++ b/public/catalog/controller/extension/payment/amazon_login_pay.php
@@ -0,0 +1,690 @@
+<?php
+
+class ControllerExtensionPaymentAmazonLoginPay extends Controller {
+ public function session_expired() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ $this->model_extension_payment_amazon_login_pay->cartRedirect($this->language->get('error_session_expired'));
+ }
+
+ public function address() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ $this->document->setTitle($this->language->get('heading_address'));
+
+ // Verify cart
+ $this->model_extension_payment_amazon_login_pay->verifyCart();
+
+ // Verify login
+ $this->model_extension_payment_amazon_login_pay->verifyLogin();
+
+ // Verify cart total
+ //$this->model_extension_payment_amazon_login_pay->verifyTotal();
+
+ // Cancel an existing order reference
+ unset($this->session->data['order_id']);
+
+ if (!empty($this->session->data['apalwa']['pay']['order_reference_id']) && !$this->model_extension_payment_amazon_login_pay->isOrderInState($this->session->data['apalwa']['pay']['order_reference_id'], array('Canceled', 'Closed', 'Draft'))) {
+ $this->model_extension_payment_amazon_login_pay->cancelOrder($this->session->data['apalwa']['pay']['order_reference_id'], "Shipment widget has been requested, cancelling this order reference.");
+
+ unset($this->session->data['apalwa']['pay']['order_reference_id']);
+ }
+
+ $data['text_cart'] = $this->language->get('text_cart');
+
+ $data['shipping_methods'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/shipping_methods', '', true), ENT_COMPAT, "UTF-8");
+ $data['shipping'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/shipping', '', true), ENT_COMPAT, "UTF-8");
+ $data['cart'] = html_entity_decode($this->url->link('checkout/cart'), ENT_COMPAT, "UTF-8");
+ $data['session_expired'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/session_expired'), ENT_COMPAT, "UTF-8");
+
+ $data['client_id'] = $this->config->get('payment_amazon_login_pay_client_id');
+ $data['merchant_id'] = $this->config->get('payment_amazon_login_pay_merchant_id');
+
+ if ($this->config->get('payment_amazon_login_pay_test') == 'sandbox') {
+ $data['sandbox'] = isset($this->session->data['user_id']); // Require an active admin panel session to show debug messages
+ }
+
+ $amazon_payment_js = $this->model_extension_payment_amazon_login_pay->getWidgetJs();
+ $this->document->addScript($amazon_payment_js);
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home', '', true),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('checkout/cart'),
+ 'text' => $this->language->get('breadcrumb_cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/address'),
+ 'current' => true,
+ 'text' => $this->language->get('breadcrumb_shipping')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => null,
+ 'text' => $this->language->get('breadcrumb_payment')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => null,
+ 'text' => $this->language->get('breadcrumb_summary')
+ );
+
+ $data['content_main'] = $this->load->view('extension/payment/amazon_login_pay_address', $data);
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/amazon_login_pay_generic', $data));
+ }
+
+ public function shipping_methods() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $json = array();
+
+ try {
+ $this->load->model('extension/payment/amazon_login_pay');
+ $this->load->model('setting/extension');
+
+ if (!isset($this->request->get['AmazonOrderReferenceId'])) {
+ throw $this->model_extension_payment_amazon_login_pay->loggedException($this->language->get('error_shipping_methods'), $this->language->get('error_shipping_methods'));
+ }
+
+ $order_reference_id = $this->request->get['AmazonOrderReferenceId'];
+
+ $this->session->data['apalwa']['pay']['order_reference_id'] = $order_reference_id;
+
+ $address = $this->model_extension_payment_amazon_login_pay->getAddress($order_reference_id);
+
+ $quotes = array();
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if (isset($result['code'])) {
+ $code = $result['code'];
+ } else {
+ $code = $result['key'];
+ }
+
+ if ($this->config->get('shipping_' . $code . '_status')) {
+ $this->load->model('extension/shipping/' . $code);
+
+ $quote = $this->{'model_extension_shipping_' . $code}->getQuote($address);
+
+ if ($quote && empty($quote['error'])) {
+ $quotes[$code] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ if (empty($quotes)) {
+ throw new \RuntimeException($this->language->get('error_no_shipping_methods'));
+ }
+
+ $sort_order = array();
+
+ foreach ($quotes as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $quotes);
+
+ $this->session->data['apalwa']['pay']['shipping_methods'] = $quotes;
+ $this->session->data['apalwa']['pay']['address'] = $address;
+
+ $json['quotes'] = $quotes;
+
+ if (!empty($this->session->data['apalwa']['pay']['shipping_method']['code'])) {
+ $json['selected'] = $this->session->data['apalwa']['pay']['shipping_method']['code'];
+ } else {
+ $json['selected'] = '';
+ }
+ } catch (\RuntimeException $e) {
+ $json['error'] = $e->getMessage();
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function shipping() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+ $this->load->model('extension/module/amazon_login');
+
+ $json = array(
+ 'redirect' => null,
+ 'error' => null
+ );
+
+ try {
+ if (!isset($this->request->post['shipping_method'])) {
+ throw $this->model_extension_payment_amazon_login_pay->loggedException("No shipping method provided.", $this->language->get('error_process_order'));
+ }
+
+ $shipping_method = explode('.', $this->request->post['shipping_method']);
+
+ if (!isset($shipping_method[0]) || !isset($shipping_method[1]) || !isset($this->session->data['apalwa']['pay']['shipping_methods'][$shipping_method[0]]['quote'][$shipping_method[1]])) {
+
+ throw $this->model_extension_payment_amazon_login_pay->loggedException("Used shipping method is not allowed.", $this->language->get('error_process_order'));
+ }
+
+ $this->session->data['apalwa']['pay']['shipping_method'] = $this->session->data['apalwa']['pay']['shipping_methods'][$shipping_method[0]]['quote'][$shipping_method[1]];
+ $this->session->data['shipping_method'] = $this->session->data['apalwa']['pay']['shipping_method'];
+ $this->session->data['payment_address'] = $this->session->data['apalwa']['pay']['address'];
+ $this->session->data['shipping_address'] = $this->session->data['apalwa']['pay']['address'];
+ $this->session->data['shipping_country_id'] = $this->session->data['apalwa']['pay']['address']['country_id'];
+ $this->session->data['shipping_zone_id'] = $this->session->data['apalwa']['pay']['address']['zone_id'];
+
+ $this->model_extension_module_amazon_login->persistAddress($this->session->data['apalwa']['pay']['address']);
+
+ $json['redirect'] = $this->url->link('extension/payment/amazon_login_pay/payment', '', true);
+ } catch (\RuntimeException $e) {
+ $json['error'] = $e->getMessage();
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function payment() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ $this->document->setTitle($this->language->get('heading_payment'));
+
+ // Verify cart
+ $this->model_extension_payment_amazon_login_pay->verifyCart();
+
+ // Verify login
+ $this->model_extension_payment_amazon_login_pay->verifyLogin();
+
+ // Verify cart total
+ //$this->model_extension_payment_amazon_login_pay->verifyTotal();
+
+ $data['confirm'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/confirm', '', true), ENT_COMPAT, "UTF-8");
+ $data['back'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/address', '', true), ENT_COMPAT, "UTF-8");
+ $data['session_expired'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/session_expired'), ENT_COMPAT, "UTF-8");
+
+ $data['merchant_id'] = $this->config->get('payment_amazon_login_pay_merchant_id');
+ $data['client_id'] = $this->config->get('payment_amazon_login_pay_client_id');
+
+ $data['order_reference_id'] = !empty($this->session->data['apalwa']['pay']['order_reference_id']) ? $this->session->data['apalwa']['pay']['order_reference_id'] : null;
+
+ if ($this->config->get('payment_amazon_login_pay_test') == 'sandbox') {
+ $data['sandbox'] = isset($this->session->data['user_id']); // Require an active admin panel session to show debug messages
+ }
+
+ $data['error'] = '';
+ if (isset($this->session->data['apalwa']['error'])) {
+ $data['error'] = $this->session->data['apalwa']['error'];
+ unset($this->session->data['apalwa']['error']);
+ }
+
+ $amazon_payment_js = $this->model_extension_payment_amazon_login_pay->getWidgetJs();
+ $this->document->addScript($amazon_payment_js);
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home', '', true),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('checkout/cart'),
+ 'text' => $this->language->get('breadcrumb_cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/address'),
+ 'text' => $this->language->get('breadcrumb_shipping')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/payment'),
+ 'current' => true,
+ 'text' => $this->language->get('breadcrumb_payment')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => null,
+ 'text' => $this->language->get('breadcrumb_summary')
+ );
+
+ $data['content_main'] = $this->load->view('extension/payment/amazon_login_pay_payment', $data);
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/amazon_login_pay_generic', $data));
+ }
+
+ public function persist_comment() {
+ if (isset($this->request->post['comment'])) {
+ $this->session->data['comment'] = strip_tags($this->request->post['comment']);
+
+ $this->session->data['apalwa']['pay']['order']['comment'] = $this->session->data['comment'];
+ }
+ }
+
+ public function coupon_discard() {
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ // Verify reference
+ $this->model_extension_payment_amazon_login_pay->verifyReference();
+
+ if ($this->model_extension_payment_amazon_login_pay->isOrderInState($this->session->data['apalwa']['pay']['order_reference_id'], array('Draft'))) {
+ unset($this->session->data['coupon']);
+ }
+
+ $this->response->redirect($this->url->link('extension/payment/amazon_login_pay/confirm', '', true));
+ }
+
+ public function standard_checkout() {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ // Verify cart
+ $this->model_extension_payment_amazon_login_pay->verifyCart();
+
+ // Verify login
+ $this->model_extension_payment_amazon_login_pay->verifyLogin();
+
+ // Cancel an existing order reference
+ if (!empty($this->session->data['apalwa']['pay']['order_reference_id']) && $this->model_extension_payment_amazon_login_pay->isOrderInState($this->session->data['apalwa']['pay']['order_reference_id'], array('Open'))) {
+ $this->model_extension_payment_amazon_login_pay->cancelOrder($this->session->data['apalwa']['pay']['order_reference_id'], "Shipment widget has been requested, cancelling this order reference.");
+ }
+
+ // Unset all payment data
+ unset($this->session->data['apalwa']['pay']);
+ unset($this->session->data['order_id']);
+
+ // Redirect to the cart
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+
+ public function confirm() {
+ $this->load->language('extension/payment/amazon_login_pay');
+ $this->load->language('checkout/checkout');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ $this->document->setTitle($this->language->get('heading_confirm'));
+
+ // Verify cart
+ $this->model_extension_payment_amazon_login_pay->verifyCart();
+
+ // Verify login
+ $this->model_extension_payment_amazon_login_pay->verifyLogin();
+
+ // Verify cart total
+ // Not needed, as we will display an error message later on...
+
+ // Verify reference
+ $this->model_extension_payment_amazon_login_pay->verifyReference();
+
+ // Verify shipping
+ $this->model_extension_payment_amazon_login_pay->verifyShipping();
+
+ $data['merchant_id'] = $this->config->get('payment_amazon_login_pay_merchant_id');
+ $data['client_id'] = $this->config->get('payment_amazon_login_pay_client_id');
+
+ if ($this->config->get('payment_amazon_login_pay_test') == 'sandbox') {
+ $data['sandbox'] = isset($this->session->data['user_id']); // Require an active admin panel session to show debug messages
+ }
+
+ $amazon_payment_js = $this->model_extension_payment_amazon_login_pay->getWidgetJs();
+ $this->document->addScript($amazon_payment_js);
+
+ try {
+ $order = $this->model_extension_payment_amazon_login_pay->makeOrder();
+
+ $this->session->data['apalwa']['pay']['order'] = $order;
+
+ $data['order_reference_id'] = $this->session->data['apalwa']['pay']['order_reference_id'];
+ $data['order'] = $order;
+ } catch (\RuntimeException $e) {
+ $this->model_extension_payment_amazon_login_pay->cartRedirect($e->getMessage());
+ }
+
+ $data['success'] = '';
+
+ if (!empty($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ }
+
+ if (isset($this->session->data['coupon'])) {
+ $data['coupon'] = $this->session->data['coupon'];
+ } else {
+ $data['coupon'] = '';
+ }
+
+ if (isset($this->session->data['comment'])) {
+ $data['comment'] = $this->session->data['comment'];
+ } else {
+ $data['comment'] = '';
+ }
+
+ $data['is_order_total_positive'] = $this->model_extension_payment_amazon_login_pay->isTotalPositive();
+ $data['standard_checkout'] = $this->url->link('extension/payment/amazon_login_pay/standard_checkout', '', true);
+
+ $zero_total = $this->currency->format(0, $this->session->data['currency']);
+ $data['error_order_total_zero'] = sprintf($this->language->get('error_order_total_zero'), $zero_total);
+
+ $data['process'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/process', '', true), ENT_COMPAT, "UTF-8");
+ $data['back'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/payment', '', true), ENT_COMPAT, "UTF-8");
+ $data['session_expired'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/session_expired'), ENT_COMPAT, "UTF-8");
+ $data['coupon_discard'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/coupon_discard', '', true), ENT_COMPAT, "UTF-8");
+ $data['coupon_apply'] = html_entity_decode($this->url->link('extension/total/coupon/coupon', '', true), ENT_COMPAT, "UTF-8");
+ $data['persist_comment'] = html_entity_decode($this->url->link('extension/payment/amazon_login_pay/persist_comment', '', true), ENT_COMPAT, "UTF-8");
+ $data['is_coupon_change_allowed'] = $this->model_extension_payment_amazon_login_pay->isOrderInState($this->session->data['apalwa']['pay']['order_reference_id'], array('Draft'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home', '', true),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('checkout/cart'),
+ 'text' => $this->language->get('breadcrumb_cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/address'),
+ 'text' => $this->language->get('breadcrumb_shipping')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/payment'),
+ 'text' => $this->language->get('breadcrumb_payment')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/amazon_login_pay/confirm'),
+ 'current' => true,
+ 'text' => $this->language->get('breadcrumb_summary')
+ );
+
+ $location_currency = $this->config->get('payment_amazon_login_pay_payment_region');
+ $rate = round($this->currency->getValue($location_currency) / $this->currency->getValue($order['currency_code']), 8);
+ $amount = $this->currency->format($this->currency->convert($order['total'], $this->config->get('config_currency'), $location_currency), $location_currency, 1, true);
+
+ $data['is_amount_converted'] = $order['currency_code'] != $location_currency;
+ $data['text_amount_converted'] = sprintf($this->language->get('text_amount_converted'), $location_currency, $rate, $amount);
+
+ $data['content_main'] = $this->load->view('extension/payment/amazon_login_pay_confirm', $data);
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/amazon_login_pay_generic', $data));
+ }
+
+ public function process() {
+ $this->load->language('extension/payment/amazon_login_pay');
+ $this->load->language('checkout/checkout');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+ $this->load->model('checkout/order');
+
+ // Verify cart
+ $this->model_extension_payment_amazon_login_pay->verifyCart();
+
+ // Verify login
+ $this->model_extension_payment_amazon_login_pay->verifyLogin();
+
+ // Verify cart total
+ // Not needed, as we will display an error message later on...
+
+ // Verify reference
+ $this->model_extension_payment_amazon_login_pay->verifyReference();
+
+ // Verify shipping
+ $this->model_extension_payment_amazon_login_pay->verifyShipping();
+
+ // Verify order
+ $this->model_extension_payment_amazon_login_pay->verifyOrder();
+
+ try {
+ $order_reference_id = $this->session->data['apalwa']['pay']['order_reference_id'];
+
+ if (empty($this->session->data['order_id'])) {
+ // Up to this point, everything is fine in the session. Save the order and submit it to Amazon.
+ $order_id = $this->model_checkout_order->addOrder($this->session->data['apalwa']['pay']['order']);
+
+ $this->session->data['order_id'] = $order_id;
+
+ $this->model_extension_payment_amazon_login_pay->submitOrderDetails($order_reference_id, $order_id);
+ } else {
+ $order_id = $this->session->data['order_id'];
+ }
+
+ // Check constraints
+ $constraints = $this->model_extension_payment_amazon_login_pay->fetchOrder($order_reference_id)->Constraints;
+
+ if (!empty($constraints->Constraint)) {
+ // We do not expect to fall under the other kinds of constraints. For more information, see: https://pay.amazon.com/us/developer/documentation/apireference/201752890
+ $payment_page_errors = array(
+ 'PaymentPlanNotSet' => $this->language->get('error_constraint_payment_plan_not_set'),
+ 'PaymentMethodNotAllowed' => $this->language->get('error_constraint_payment_method_not_allowed'),
+ 'AmountNotSet' => $this->language->get('error_constraint_amount_not_set')
+ );
+
+ $constraint_id = (string)$constraints->Constraint->ConstraintID;
+
+ if (in_array($constraint_id, array_keys($payment_page_errors))) {
+ $this->session->data['apalwa']['error'] = $payment_page_errors[$constraint_id];
+
+ $this->response->redirect($this->url->link('extension/payment/amazon_login_pay/payment', '', true));
+ } else {
+ throw new \RuntimeException($constraints->Constraint->Description);
+ }
+ }
+
+ // Open the order for authorization
+ $this->model_extension_payment_amazon_login_pay->confirmOrder($order_reference_id);
+
+ $amazon_order = $this->model_extension_payment_amazon_login_pay->fetchOrder($order_reference_id);
+
+ // The order has been opened for authorization. Store it in the database
+ $amazon_login_pay_order_id = $this->model_extension_payment_amazon_login_pay->findOrAddOrder($amazon_order);
+
+ // Authorize the order
+ $authorization = $this->model_extension_payment_amazon_login_pay->authorizeOrder($amazon_order);
+
+ // Log the authorization
+ $this->model_extension_payment_amazon_login_pay->addAuthorization($amazon_login_pay_order_id, $authorization);
+
+ if ($authorization->AuthorizationStatus->State == 'Declined') {
+ $reason_code = (string)$authorization->AuthorizationStatus->ReasonCode;
+
+ switch ($reason_code) {
+ case 'InvalidPaymentMethod' :
+ $this->session->data['apalwa']['error'] = $this->language->get('error_decline_invalid_payment_method');
+
+ $this->response->redirect($this->url->link('extension/payment/amazon_login_pay/payment', '', true));
+ break;
+ default :
+ if ($this->model_extension_payment_amazon_login_pay->isOrderInState($order_reference_id, array('Open'))) {
+ $this->model_extension_payment_amazon_login_pay->cancelOrder($order_reference_id, "Authorization has failed with the state: " . $authorization->AuthorizationStatus->State);
+ }
+
+ $cart_error_messages = array(
+ 'TransactionTimedOut' => $this->language->get('error_decline_transaction_timed_out'),
+ 'AmazonRejected' => $this->language->get('error_decline_amazon_rejected'),
+ 'ProcessingFailure' => $this->language->get('error_decline_processing_failure')
+ );
+
+ if (in_array($reason_code, array_keys($cart_error_messages))) {
+ //@todo - do the logout with amazon.Login.logout(); instead
+ unset($this->session->data['apalwa']);
+
+ // capital L in Amazon cookie name is required, do not alter for coding standards
+ if (isset($this->request->cookie['amazon_Login_state_cache'])) {
+ //@todo - rework this by triggering the JavaScript logout
+ setcookie('amazon_Login_state_cache', null, -1, '/');
+ }
+
+ throw new \RuntimeException($cart_error_messages[$reason_code]);
+ } else {
+ // This should never occur, but just in case...
+ throw $this->model_extension_payment_amazon_login_pay->loggedException("Authorization has failed with code: " . $reason_code, $this->language->get('error_process_order'));
+ }
+ break;
+ }
+ }
+
+ // Amend the billing address based on the Authorize response
+ if (!empty($authorization->AuthorizationBillingAddress)) {
+ $this->model_extension_payment_amazon_login_pay->updatePaymentAddress($order_id, $authorization->AuthorizationBillingAddress);
+ }
+
+ // Clean the session and redirect to the success page
+ unset($this->session->data['apalwa']['pay']);
+
+ // In case a payment has been completed, and the order is not closed, close it.
+ if (isset($authorization->CapturedAmount->Amount) && (float)$authorization->CapturedAmount->Amount && $this->model_extension_payment_amazon_login_pay->isOrderInState($order_reference_id, array('Open', 'Suspended'))) {
+ $this->model_extension_payment_amazon_login_pay->closeOrder($order_reference_id, "A capture has been performed. Closing the order.");
+ }
+
+ // Log any errors triggered by addOrderHistory, but without displaying them
+ set_error_handler(array($this->model_extension_payment_amazon_login_pay, 'logHandler'));
+
+ try {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_amazon_login_pay_pending_status'));
+ } catch (\Exception $e) {
+ if ($this->config->get('error_log')) {
+ $this->log->write($e->getMessage());
+ }
+ }
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } catch (\RuntimeException $e) {
+ $this->model_extension_payment_amazon_login_pay->cartRedirect($e->getMessage());
+ }
+ }
+
+ public function ipn() {
+ $this->load->model('extension/payment/amazon_login_pay');
+
+ try {
+ if (!isset($this->request->get['token'])) {
+ throw new \RuntimeException('GET variable "token" is missing.');
+ }
+
+ if (trim($this->request->get['token']) == '') {
+ throw new \RuntimeException('GET variable "token" set, but is empty.');
+ }
+
+ if (!$this->config->get('payment_amazon_login_pay_ipn_token')) {
+ throw new \RuntimeException('CONFIG variable "payment_amazon_login_pay_ipn_token" is empty.');
+ }
+
+ if (!hash_equals(trim($this->config->get('payment_amazon_login_pay_ipn_token')), trim($this->request->get['token']))) {
+ throw new \RuntimeException('Token values are different.');
+ }
+
+ // Everything is fine. Process the IPN
+ $body = file_get_contents('php://input');
+
+ $this->model_extension_payment_amazon_login_pay->debugLog('IPN BODY', $body);
+
+ if ($body) {
+ $xml = $this->model_extension_payment_amazon_login_pay->parseIpnBody($body);
+
+ switch ($xml->getName()) {
+ case 'AuthorizationNotification':
+ $this->model_extension_payment_amazon_login_pay->authorizationIpn($xml);
+ break;
+ case 'CaptureNotification':
+ $this->model_extension_payment_amazon_login_pay->captureIpn($xml);
+ break;
+ case 'RefundNotification':
+ $this->model_extension_payment_amazon_login_pay->refundIpn($xml);
+ break;
+ }
+ }
+ } catch (\RuntimeException $e) {
+ $this->model_extension_payment_amazon_login_pay->debugLog('IPN ERROR', $e->getMessage());
+ }
+
+ $this->response->addHeader('HTTP/1.1 200 OK');
+ $this->response->addHeader('Content-Type: application/json');
+ }
+
+ public function capture(&$route, &$args, &$output) {
+ $this->load->language('extension/payment/amazon_login_pay');
+
+ $this->load->model('extension/payment/amazon_login_pay');
+ $order_id = $args[0];
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info['order_status_id'] == $this->config->get('payment_amazon_login_pay_capture_status')) {
+ try {
+ $amazon_login_pay_order = $this->model_extension_payment_amazon_login_pay->getOrderByOrderId($order_id);
+
+ $capture_response = $this->model_extension_payment_amazon_login_pay->captureOrder($amazon_login_pay_order['amazon_authorization_id'], $amazon_login_pay_order['total'], $amazon_login_pay_order['currency_code']);
+
+ if (isset($capture_response->CaptureStatus->State) && in_array($capture_response->CaptureStatus->State, array('Completed', 'Pending'))) {
+ $order_reference_id = $amazon_login_pay_order['amazon_order_reference_id'];
+
+ if ($this->model_extension_payment_amazon_login_pay->isOrderInState($order_reference_id, array('Open', 'Suspended'))) {
+ $this->model_extension_payment_amazon_login_pay->closeOrder($order_reference_id, "Captured amount: " . (string)$capture_response->CaptureAmount->Amount . " " . (string)$capture_response->CaptureAmount->CurrencyCode);
+ }
+
+ $transaction = array(
+ 'amazon_login_pay_order_id' => $amazon_login_pay_order['amazon_login_pay_order_id'],
+ 'amazon_authorization_id' => $amazon_login_pay_order['amazon_authorization_id'],
+ 'amazon_capture_id' => $capture_response->AmazonCaptureId,
+ 'amazon_refund_id' => '',
+ 'date_added' => date('Y-m-d H:i:s', strtotime((string)$capture_response->CreationTimestamp)),
+ 'type' => 'capture',
+ 'status' => (string)$capture_response->CaptureStatus->State,
+ 'amount' => (float)$capture_response->CaptureAmount->Amount
+ );
+
+ $this->model_extension_payment_amazon_login_pay->addTransaction($transaction);
+
+ $this->model_extension_payment_amazon_login_pay->updateStatus($amazon_login_pay_order['amazon_authorization_id'], 'authorization', 'Closed');
+
+ $this->model_extension_payment_amazon_login_pay->updateCapturedStatus($amazon_login_pay_order['amazon_login_pay_order_id'], 1);
+ }
+ } catch (\RuntimeException $e) {
+ // Do nothing, as the exception is logged in case of debug logging.
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/authorizenet_aim.php b/public/catalog/controller/extension/payment/authorizenet_aim.php
new file mode 100644
index 0000000..d3355ef
--- /dev/null
+++ b/public/catalog/controller/extension/payment/authorizenet_aim.php
@@ -0,0 +1,176 @@
+<?php
+class ControllerExtensionPaymentAuthorizeNetAim extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/authorizenet_aim');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/authorizenet_aim', $data);
+ }
+
+ public function send() {
+ if ($this->config->get('payment_authorizenet_aim_server') == 'live') {
+ $url = 'https://secure.authorize.net/gateway/transact.dll';
+ } elseif ($this->config->get('payment_authorizenet_aim_server') == 'test') {
+ $url = 'https://test.authorize.net/gateway/transact.dll';
+ }
+
+ //$url = 'https://secure.networkmerchants.com/gateway/transact.dll';
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data = array();
+
+ $data['x_login'] = $this->config->get('payment_authorizenet_aim_login');
+ $data['x_tran_key'] = $this->config->get('payment_authorizenet_aim_key');
+ $data['x_version'] = '3.1';
+ $data['x_delim_data'] = 'true';
+ $data['x_delim_char'] = '|';
+ $data['x_encap_char'] = '"';
+ $data['x_relay_response'] = 'false';
+ $data['x_first_name'] = $order_info['payment_firstname'];
+ $data['x_last_name'] = $order_info['payment_lastname'];
+ $data['x_company'] = $order_info['payment_company'];
+ $data['x_address'] = $order_info['payment_address_1'];
+ $data['x_city'] = $order_info['payment_city'];
+ $data['x_state'] = $order_info['payment_zone'];
+ $data['x_zip'] = $order_info['payment_postcode'];
+ $data['x_country'] = $order_info['payment_country'];
+ $data['x_phone'] = $order_info['telephone'];
+ $data['x_customer_ip'] = $this->request->server['REMOTE_ADDR'];
+ $data['x_email'] = $order_info['email'];
+ $data['x_description'] = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
+ $data['x_amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], 1.00000, false);
+ $data['x_currency_code'] = $this->session->data['currency'];
+ $data['x_method'] = 'CC';
+ $data['x_type'] = ($this->config->get('payment_authorizenet_aim_method') == 'capture') ? 'AUTH_CAPTURE' : 'AUTH_ONLY';
+ $data['x_card_num'] = str_replace(' ', '', $this->request->post['cc_number']);
+ $data['x_exp_date'] = $this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year'];
+ $data['x_card_code'] = $this->request->post['cc_cvv2'];
+ $data['x_invoice_num'] = $this->session->data['order_id'];
+ $data['x_solution_id'] = 'A1000015';
+
+ /* Customer Shipping Address Fields */
+ if ($order_info['shipping_method']) {
+ $data['x_ship_to_first_name'] = $order_info['shipping_firstname'];
+ $data['x_ship_to_last_name'] = $order_info['shipping_lastname'];
+ $data['x_ship_to_company'] = $order_info['shipping_company'];
+ $data['x_ship_to_address'] = $order_info['shipping_address_1'] . ' ' . $order_info['shipping_address_2'];
+ $data['x_ship_to_city'] = $order_info['shipping_city'];
+ $data['x_ship_to_state'] = $order_info['shipping_zone'];
+ $data['x_ship_to_zip'] = $order_info['shipping_postcode'];
+ $data['x_ship_to_country'] = $order_info['shipping_country'];
+ } else {
+ $data['x_ship_to_first_name'] = $order_info['payment_firstname'];
+ $data['x_ship_to_last_name'] = $order_info['payment_lastname'];
+ $data['x_ship_to_company'] = $order_info['payment_company'];
+ $data['x_ship_to_address'] = $order_info['payment_address_1'] . ' ' . $order_info['payment_address_2'];
+ $data['x_ship_to_city'] = $order_info['payment_city'];
+ $data['x_ship_to_state'] = $order_info['payment_zone'];
+ $data['x_ship_to_zip'] = $order_info['payment_postcode'];
+ $data['x_ship_to_country'] = $order_info['payment_country'];
+ }
+
+ if ($this->config->get('payment_authorizenet_aim_mode') == 'test') {
+ $data['x_test_request'] = 'true';
+ }
+
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 10);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data, '', '&'));
+
+ $response = curl_exec($curl);
+
+ $json = array();
+
+ if (curl_error($curl)) {
+ $json['error'] = 'CURL ERROR: ' . curl_errno($curl) . '::' . curl_error($curl);
+
+ $this->log->write('AUTHNET AIM CURL ERROR: ' . curl_errno($curl) . '::' . curl_error($curl));
+ } elseif ($response) {
+ $i = 1;
+
+ $response_info = array();
+
+ $results = explode('|', $response);
+
+ foreach ($results as $result) {
+ $response_info[$i] = trim($result, '"');
+
+ $i++;
+ }
+
+ if ($response_info[1] == '1') {
+ $message = '';
+
+ if (isset($response_info['5'])) {
+ $message .= 'Authorization Code: ' . $response_info['5'] . "\n";
+ }
+
+ if (isset($response_info['6'])) {
+ $message .= 'AVS Response: ' . $response_info['6'] . "\n";
+ }
+
+ if (isset($response_info['7'])) {
+ $message .= 'Transaction ID: ' . $response_info['7'] . "\n";
+ }
+
+ if (isset($response_info['39'])) {
+ $message .= 'Card Code Response: ' . $response_info['39'] . "\n";
+ }
+
+ if (isset($response_info['40'])) {
+ $message .= 'Cardholder Authentication Verification Response: ' . $response_info['40'] . "\n";
+ }
+
+ if (!$this->config->get('payment_authorizenet_aim_hash') || (strtoupper($response_info[38]) == strtoupper(md5($this->config->get('payment_authorizenet_aim_hash') . $this->config->get('payment_authorizenet_aim_login') . $response_info[7] . $this->currency->format($order_info['total'], $order_info['currency_code'], 1.00000, false))))) {
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_authorizenet_aim_order_status_id'), $message, false);
+ } else {
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('config_order_status_id'));
+ }
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ } else {
+ $json['error'] = $response_info[4];
+ }
+ } else {
+ $json['error'] = 'Empty Gateway Response';
+
+ $this->log->write('AUTHNET AIM CURL ERROR: Empty Gateway Response');
+ }
+
+ curl_close($curl);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/authorizenet_sim.php b/public/catalog/controller/extension/payment/authorizenet_sim.php
new file mode 100644
index 0000000..9cf7d87
--- /dev/null
+++ b/public/catalog/controller/extension/payment/authorizenet_sim.php
@@ -0,0 +1,141 @@
+<?php
+class ControllerExtensionPaymentAuthorizeNetSim extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/authorizenet_sim');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['x_login'] = $this->config->get('payment_authorizenet_sim_merchant');
+ $data['x_fp_sequence'] = $this->session->data['order_id'];
+ $data['x_fp_timestamp'] = time();
+ $data['x_amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['x_fp_hash'] = null; // calculated later, once all fields are populated
+ $data['x_show_form'] = 'PAYMENT_FORM';
+ $data['x_test_request'] = $this->config->get('payment_authorizenet_sim_mode');
+ $data['x_type'] = 'AUTH_CAPTURE';
+ $data['x_currency_code'] = $this->session->data['currency'];
+ $data['x_invoice_num'] = $this->session->data['order_id'];
+ $data['x_description'] = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
+ $data['x_first_name'] = $order_info['payment_firstname'];
+ $data['x_last_name'] = $order_info['payment_lastname'];
+ $data['x_company'] = $order_info['payment_company'];
+ $data['x_address'] = $order_info['payment_address_1'] . ' ' . $order_info['payment_address_2'];
+ $data['x_city'] = $order_info['payment_city'];
+ $data['x_state'] = $order_info['payment_zone'];
+ $data['x_zip'] = $order_info['payment_postcode'];
+ $data['x_country'] = $order_info['payment_country'];
+ $data['x_phone'] = $order_info['telephone'];
+ $data['x_ship_to_first_name'] = $order_info['shipping_firstname'];
+ $data['x_ship_to_last_name'] = $order_info['shipping_lastname'];
+ $data['x_ship_to_company'] = $order_info['shipping_company'];
+ $data['x_ship_to_address'] = $order_info['shipping_address_1'] . ' ' . $order_info['shipping_address_2'];
+ $data['x_ship_to_city'] = $order_info['shipping_city'];
+ $data['x_ship_to_state'] = $order_info['shipping_zone'];
+ $data['x_ship_to_zip'] = $order_info['shipping_postcode'];
+ $data['x_ship_to_country'] = $order_info['shipping_country'];
+ $data['x_customer_ip'] = $this->request->server['REMOTE_ADDR'];
+ $data['x_email'] = $order_info['email'];
+ $data['x_relay_response'] = 'true';
+
+ $to_hash = $data['x_login'] . '^' . $data['x_fp_sequence'] . '^' . $data['x_fp_timestamp'] . '^' . $data['x_amount'] . '^' . $data['x_currency_code'];
+ $data['x_fp_hash'] = $this->generateHash($to_hash, $this->config->get('payment_authorizenet_sim_key'));
+
+ return $this->load->view('extension/payment/authorizenet_sim', $data);
+ }
+
+ public function callback() {
+ if (isset($this->request->post['x_SHA2_Hash']) && ($this->request->post['x_SHA2_Hash'] == $this->generateResponseHash($this->request->post, $this->config->get('payment_authorizenet_sim_hash')))) {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->request->post['x_invoice_num']);
+
+ if ($order_info && $this->request->post['x_response_code'] == '1') {
+ $message = '';
+
+ if (isset($this->request->post['x_response_reason_text'])) {
+ $message .= 'Response Text: ' . $this->request->post['x_response_reason_text'] . "\n";
+ }
+
+ if (isset($this->request->post['exact_issname'])) {
+ $message .= 'Issuer: ' . $this->request->post['exact_issname'] . "\n";
+ }
+
+ if (isset($this->request->post['exact_issconf'])) {
+ $message .= 'Confirmation Number: ' . $this->request->post['exact_issconf'];
+ }
+
+ if (isset($this->request->post['exact_ctr'])) {
+ $message .= 'Receipt: ' . $this->request->post['exact_ctr'];
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->request->post['x_invoice_num'], $this->config->get('payment_authorizenet_sim_order_status_id'), $message, true);
+
+ $this->response->redirect($this->url->link('checkout/success'));
+ } else {
+ $this->response->redirect($this->url->link('checkout/failure'));
+ }
+ } else {
+ $this->response->redirect($this->url->link('checkout/failure'));
+ }
+ }
+
+ private function generateHash($to_hash, $key) {
+ if ($to_hash != null && $key != null) {
+ $sig = hash_hmac('sha512', $to_hash, hex2bin($key));
+
+ return strtoupper($sig);
+ } else {
+ return false;
+ }
+ }
+
+ private function generateResponseHash($post_fields, $signature_key) {
+ /**
+ * The following array must not be reordered or elements removed, the hash requires ALL, even if empty/not set
+ */
+ $verify_hash_fields = [
+ 'x_trans_id',
+ 'x_test_request',
+ 'x_response_code',
+ 'x_auth_code',
+ 'x_cvv2_resp_code',
+ 'x_cavv_response',
+ 'x_avs_code',
+ 'x_method',
+ 'x_account_number',
+ 'x_amount',
+ 'x_company',
+ 'x_first_name',
+ 'x_last_name',
+ 'x_address',
+ 'x_city',
+ 'x_state',
+ 'x_zip',
+ 'x_country',
+ 'x_phone',
+ 'x_fax',
+ 'x_email',
+ 'x_ship_to_company',
+ 'x_ship_to_first_name',
+ 'x_ship_to_last_name',
+ 'x_ship_to_address',
+ 'x_ship_to_city',
+ 'x_ship_to_state',
+ 'x_ship_to_zip',
+ 'x_ship_to_country',
+ 'x_invoice_num',
+ ];
+
+ $to_hash = '^';
+
+ foreach ($verify_hash_fields as $hash_field) {
+ $to_hash .= (isset($post_fields[$hash_field]) ? $post_fields[$hash_field] : '') . '^';
+ }
+
+ return $this->generateHash($to_hash, $signature_key);
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/bank_transfer.php b/public/catalog/controller/extension/payment/bank_transfer.php
new file mode 100644
index 0000000..cc385c5
--- /dev/null
+++ b/public/catalog/controller/extension/payment/bank_transfer.php
@@ -0,0 +1,31 @@
+<?php
+class ControllerExtensionPaymentBankTransfer extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/bank_transfer');
+
+ $data['bank'] = nl2br($this->config->get('payment_bank_transfer_bank' . $this->config->get('config_language_id')));
+
+ return $this->load->view('extension/payment/bank_transfer', $data);
+ }
+
+ public function confirm() {
+ $json = array();
+
+ if ($this->session->data['payment_method']['code'] == 'bank_transfer') {
+ $this->load->language('extension/payment/bank_transfer');
+
+ $this->load->model('checkout/order');
+
+ $comment = $this->language->get('text_instruction') . "\n\n";
+ $comment .= $this->config->get('payment_bank_transfer_bank' . $this->config->get('config_language_id')) . "\n\n";
+ $comment .= $this->language->get('text_payment');
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_bank_transfer_order_status_id'), $comment, true);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/bluepay_hosted.php b/public/catalog/controller/extension/payment/bluepay_hosted.php
new file mode 100644
index 0000000..2a218f5
--- /dev/null
+++ b/public/catalog/controller/extension/payment/bluepay_hosted.php
@@ -0,0 +1,95 @@
+<?php
+class ControllerExtensionPaymentBluePayHosted extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/bluepay_hosted');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/bluepay_hosted');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['ORDER_ID'] = $this->session->data['order_id'];
+ $data['NAME1'] = $order_info['payment_firstname'];
+ $data['NAME2'] = $order_info['payment_lastname'];
+ $data['ADDR1'] = $order_info['payment_address_1'];
+ $data['ADDR2'] = $order_info['payment_address_2'];
+ $data['CITY'] = $order_info['payment_city'];
+ $data['STATE'] = $order_info['payment_zone'];
+ $data['ZIPCODE'] = $order_info['payment_postcode'];
+ $data['COUNTRY'] = $order_info['payment_country'];
+ $data['PHONE'] = $order_info['telephone'];
+ $data['EMAIL'] = $order_info['email'];
+
+ $data['SHPF_FORM_ID'] = 'opencart01';
+ $data['DBA'] = $this->config->get('payment_bluepay_hosted_account_name');
+ $data['MERCHANT'] = $this->config->get('payment_bluepay_hosted_account_id');
+ $data['SHPF_ACCOUNT_ID'] = $this->config->get('payment_bluepay_hosted_account_id');
+ $data["TRANSACTION_TYPE"] = $this->config->get('payment_bluepay_hosted_transaction');
+ $data["MODE"] = strtoupper($this->config->get('payment_bluepay_hosted_test'));
+
+ $data['CARD_TYPES'] = 'vi-mc';
+
+ if ($this->config->get('payment_bluepay_hosted_discover') == 1) {
+ $data['CARD_TYPES'] .= '-di';
+ }
+
+ if ($this->config->get('payment_bluepay_hosted_amex') == 1) {
+ $data['CARD_TYPES'] .= '-am';
+ }
+
+ $data["AMOUNT"] = $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $data['APPROVED_URL'] = $this->url->link('extension/payment/bluepay_hosted/callback', '', true);
+ $data['DECLINED_URL'] = $this->url->link('extension/payment/bluepay_hosted/callback', '', true);
+ $data['MISSING_URL'] = $this->url->link('extension/payment/bluepay_hosted/callback', '', true);
+ $data['REDIRECT_URL'] = $this->url->link('extension/payment/bluepay_hosted/callback', '', true);
+
+ $data['TPS_DEF'] = "MERCHANT APPROVED_URL DECLINED_URL MISSING_URL MODE TRANSACTION_TYPE TPS_DEF AMOUNT";
+ $data['TAMPER_PROOF_SEAL'] = md5($this->config->get('payment_bluepay_hosted_secret_key') . $data['MERCHANT'] . $data['APPROVED_URL'] . $data['DECLINED_URL'] . $data['MISSING_URL'] . $data['MODE'] . $data['TRANSACTION_TYPE'] . $data['TPS_DEF'] . $data['AMOUNT']);
+
+ $data['SHPF_TPS_DEF'] = "SHPF_FORM_ID SHPF_ACCOUNT_ID DBA TAMPER_PROOF_SEAL CARD_TYPES TPS_DEF SHPF_TPS_DEF AMOUNT";
+ $data['SHPF_TPS'] = md5($this->config->get('payment_bluepay_hosted_secret_key') . $data['SHPF_FORM_ID'] . $data['SHPF_ACCOUNT_ID'] . $data['DBA'] . $data['TAMPER_PROOF_SEAL'] . $data['CARD_TYPES'] . $data['TPS_DEF'] . $data['SHPF_TPS_DEF'] . $data['AMOUNT']);
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+ $data['text_loading'] = $this->language->get('text_loading');
+
+ return $this->load->view('extension/payment/bluepay_hosted', $data);
+ }
+
+ public function callback() {
+ $this->load->language('extension/payment/bluepay_hosted');
+
+ $this->load->model('checkout/order');
+
+ $this->load->model('extension/payment/bluepay_hosted');
+
+ $response_data = $this->request->get;
+
+ if (isset($this->session->data['order_id'])) {
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($response_data['Result'] == 'APPROVED') {
+ $bluepay_hosted_order_id = $this->model_extension_payment_bluepay_hosted->addOrder($order_info, $response_data);
+
+ if ($this->config->get('payment_bluepay_hosted_transaction') == 'SALE') {
+ $this->model_extension_payment_bluepay_hosted->addTransaction($bluepay_hosted_order_id, 'payment', $order_info);
+ } else {
+ $this->model_extension_payment_bluepay_hosted->addTransaction($bluepay_hosted_order_id, 'auth', $order_info);
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_bluepay_hosted_order_status_id'));
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->session->data['error'] = $response_data['Result'] . ' : ' . $response_data['MESSAGE'];
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+ }
+
+ public function adminCallback() {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($this->request->get));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/bluepay_redirect.php b/public/catalog/controller/extension/payment/bluepay_redirect.php
new file mode 100644
index 0000000..03b1d7e
--- /dev/null
+++ b/public/catalog/controller/extension/payment/bluepay_redirect.php
@@ -0,0 +1,122 @@
+<?php
+class ControllerExtensionPaymentBluePayRedirect extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/bluepay_redirect');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ if ($this->config->get('payment_bluepay_redirect_card') == '1') {
+ $data['bluepay_redirect_card'] = true;
+ } else {
+ $data['bluepay_redirect_card'] = false;
+ }
+
+ $data['existing_cards'] = array();
+ if ($this->customer->isLogged() && $data['bluepay_redirect_card']) {
+ $this->load->model('extension/payment/bluepay_redirect');
+
+ $cards = $this->model_extension_payment_bluepay_redirect->getCards($this->customer->getId());
+
+ $data['existing_cards'] = $cards;
+ }
+
+ return $this->load->view('extension/payment/bluepay_redirect', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/bluepay_redirect');
+
+ $this->load->model('checkout/order');
+
+ $this->load->model('extension/payment/bluepay_redirect');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+ $post_data = $this->request->post;
+
+ $post_data['MERCHANT'] = $this->config->get('payment_bluepay_redirect_account_id');
+ $post_data["TRANSACTION_TYPE"] = $this->config->get('payment_bluepay_redirect_transaction');
+ $post_data["MODE"] = strtoupper($this->config->get('payment_bluepay_redirect_test'));
+ $post_data["AMOUNT"] = $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+
+ if (isset($this->request->post['RRNO'])) {
+ $post_data["RRNO"] = $this->request->post['RRNO'];
+ } else {
+ $post_data["RRNO"] = '';
+ }
+
+ $post_data["NAME"] = substr($order_info['payment_firstname'], 0, 20) . ' ' . substr($order_info['payment_lastname'], 0, 20);
+ $post_data["ADDR1"] = $post_data['BillingAddress1'] = substr($order_info['payment_address_1'], 0, 100);
+ $post_data["CITY"] = $order_info['payment_city'];
+ $post_data['STATE'] = $order_info['payment_zone_code'];
+ $post_data["PHONE"] = substr($order_info['telephone'], 0, 20);
+ $post_data["EMAIL"] = substr($order_info['email'], 0, 255);
+ $post_data["ORDER_ID"] = $this->session->data['order_id'];
+ $post_data['ZIPCODE'] = substr($order_info['payment_postcode'], 0, 10);
+
+ $post_data['APPROVED_URL'] = $this->url->link('extension/payment/bluepay_redirect/callback', '', true);
+ $post_data['DECLINED_URL'] = $this->url->link('extension/payment/bluepay_redirect/callback', '', true);
+ $post_data['MISSING_URL'] = $this->url->link('extension/payment/bluepay_redirect/callback', '', true);
+
+ if (isset($this->request->server["REMOTE_ADDR"])) {
+ $post_data["REMOTE_IP"] = $this->request->server["REMOTE_ADDR"];
+ }
+
+ $tamper_proof_data = $this->config->get('payment_bluepay_redirect_secret_key') . $post_data['MERCHANT'] . $post_data["TRANSACTION_TYPE"] . $post_data['AMOUNT'] . $post_data["RRNO"] . $post_data["MODE"];
+
+ $post_data["TAMPER_PROOF_SEAL"] = md5($tamper_proof_data);
+
+ $response_data = $this->model_extension_payment_bluepay_redirect->sendCurl("https://secure.bluepay.com/interfaces/bp10emu", $post_data);
+
+ if ($response_data['Result'] == 'APPROVED') {
+ $bluepay_redirect_order_id = $this->model_extension_payment_bluepay_redirect->addOrder($order_info, $response_data);
+
+ if ($this->config->get('payment_bluepay_redirect_transaction') == 'SALE') {
+ $this->model_extension_payment_bluepay_redirect->addTransaction($bluepay_redirect_order_id, 'payment', $order_info);
+ } else {
+ $this->model_extension_payment_bluepay_redirect->addTransaction($bluepay_redirect_order_id, 'auth', $order_info);
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_bluepay_redirect_order_status_id'));
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ } else {
+ $json['error'] = $response_data['Result'] . ' : ' . $response_data['MESSAGE'];
+ }
+
+ if (isset($post_data['CreateToken']) && $response_data['Result'] == 'APPROVED') {
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Last4Digits'] = substr(str_replace(' ', '', $post_data['CC_NUM']), -4, 4);
+ $card_data['ExpiryDate'] = $post_data['CC_EXPIRES_MONTH'] . '/' . substr($post_data['CC_EXPIRES_YEAR'], 2);
+ $card_data['CardType'] = $response_data['CARD_TYPE'];
+ $card_data['Token'] = $response_data['RRNO'];
+
+ $this->model_extension_payment_bluepay_redirect->addCard($card_data);
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function callback() {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($this->request->get));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/cardconnect.php b/public/catalog/controller/extension/payment/cardconnect.php
new file mode 100644
index 0000000..c1524d4
--- /dev/null
+++ b/public/catalog/controller/extension/payment/cardconnect.php
@@ -0,0 +1,347 @@
+<?php
+class ControllerExtensionPaymentCardConnect extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/cardconnect');
+
+ $this->load->model('extension/payment/cardconnect');
+
+ $data['card_types'] = $this->model_extension_payment_cardconnect->getCardTypes();
+
+ $data['months'] = $this->model_extension_payment_cardconnect->getMonths();
+
+ $data['years'] = $this->model_extension_payment_cardconnect->getYears();
+
+ if ($this->customer->isLogged() && $this->config->get('cardconnect_store_cards')) {
+ $data['store_cards'] = true;
+
+ $data['cards'] = $this->model_extension_payment_cardconnect->getCards($this->customer->getId());
+ } else {
+ $data['store_cards'] = false;
+
+ $data['cards'] = array();
+ }
+
+ $data['echeck'] = $this->config->get('cardconnect_echeck');
+
+ $data['action'] = $this->url->link('extension/payment/cardconnect/send', '', true);
+
+ return $this->load->view('extension/payment/cardconnect', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/cardconnect');
+
+ $this->load->model('extension/payment/cardconnect');
+
+ $this->model_extension_payment_cardconnect->log('Posting order to CardConnect');
+
+ $json = array();
+
+ $json['error'] = '';
+
+ if ($this->config->get('cardconnect_status')) {
+ if ($this->request->server['REQUEST_METHOD'] == 'POST') {
+ $error = $this->validate();
+
+ if (!$error) {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $this->model_extension_payment_cardconnect->log('Order ID: ' . $order_info['order_id']);
+
+ $accttype = $account = $expiry = $cvv2 = $profile = $capture = $bankaba = '';
+
+ $existing_card = false;
+
+ if (!isset($this->request->post['method']) || $this->request->post['method'] == 'card') {
+ $this->model_extension_payment_cardconnect->log('Method is card');
+
+ if ($this->request->post['card_new'] && isset($this->request->post['card_save']) && $this->config->get('cardconnect_store_cards') && $this->customer->isLogged()) {
+ $profile = 'Y';
+ } else if (!$this->request->post['card_new'] && $this->customer->isLogged()) {
+ $existing_card = $this->model_extension_payment_cardconnect->getCard($this->request->post['card_choice'], $this->customer->getId());
+
+ $profile = $existing_card['profileid'];
+ }
+
+ if ($existing_card) {
+ $accttype = $existing_card['type'];
+
+ $account = $existing_card['token'];
+
+ $expiry = $existing_card['expiry'];
+
+ $cvv2 = '';
+ } else {
+ $accttype = $this->request->post['card_type'];
+
+ $account = $this->request->post['card_number'];
+
+ $expiry = $this->request->post['card_expiry_month'] . $this->request->post['card_expiry_year'];
+
+ $cvv2 = $this->request->post['card_cvv2'];
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Method is Echeck');
+
+ $account = $this->request->post['account_number'];
+
+ $bankaba = $this->request->post['routing_number'];
+ }
+
+ if ($this->config->get('cardconnect_transaction') == 'payment') {
+ $capture = 'Y';
+
+ $type = 'payment';
+
+ $status = 'New';
+
+ $order_status_id = $this->config->get('cardconnect_order_status_id_processing');
+ } else {
+ $capture = 'N';
+
+ $type = 'auth';
+
+ $status = 'New';
+
+ $order_status_id = $this->config->get('cardconnect_order_status_id_pending');
+ }
+
+ $data = array(
+ 'merchid' => $this->config->get('payment_cardconnect_merchant_id'),
+ 'accttype' => $accttype,
+ 'account' => $account,
+ 'expiry' => $expiry,
+ 'cvv2' => $cvv2,
+ 'amount' => round(floatval($order_info['total']), 2, PHP_ROUND_HALF_DOWN),
+ 'currency' => $order_info['currency_code'],
+ 'orderid' => $order_info['order_id'],
+ 'name' => $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'],
+ 'address' => $order_info['payment_address_1'],
+ 'city' => $order_info['payment_city'],
+ 'region' => $order_info['payment_zone'],
+ 'country' => $order_info['payment_iso_code_2'],
+ 'postal' => $order_info['payment_postcode'],
+ 'email' => $order_info['email'],
+ 'phone' => $order_info['telephone'],
+ 'ecomind' => 'E',
+ 'tokenize' => 'Y',
+ 'profile' => $profile,
+ 'capture' => $capture,
+ 'bankaba' => $bankaba,
+ 'userfields' => array('secret_token' => $this->config->get('cardconnect_token')),
+ 'frontendid' => '26'
+ );
+
+ $data_json = json_encode($data);
+
+ $url = 'https://' . $this->config->get('cardconnect_site') . '.cardconnect.com:' . (($this->config->get('cardconnect_environment') == 'live') ? 8443 : 6443) . '/cardconnect/rest/auth';
+
+ $header = array();
+
+ $header[] = 'Content-type: application/json';
+ $header[] = 'Content-length: ' . strlen($data_json);
+ $header[] = 'Authorization: Basic ' . base64_encode($this->config->get('cardconnect_api_username') . ':' . $this->config->get('cardconnect_api_password'));
+
+ $this->model_extension_payment_cardconnect->log('Header: ' . print_r($header, true));
+
+ $this->model_extension_payment_cardconnect->log('Post Data: ' . print_r($data, true));
+
+ $this->model_extension_payment_cardconnect->log('URL: ' . $url);
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $response_data = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_cardconnect->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $response_data = json_decode($response_data, true);
+
+ $this->model_extension_payment_cardconnect->log('Response: ' . print_r($response_data, true));
+
+ if (isset($response_data['respstat']) && $response_data['respstat'] == 'A') {
+ $this->load->model('checkout/order');
+
+ // if a cheque
+ if ($bankaba) {
+ $payment_method = 'echeck';
+
+ $type = 'payment';
+ } else {
+ $payment_method = 'card';
+ }
+
+ $this->model_checkout_order->addOrderHistory($order_info['order_id'], $order_status_id);
+
+ $order_info = array_merge($order_info, $response_data);
+
+ $cardconnect_order_id = $this->model_extension_payment_cardconnect->addOrder($order_info, $payment_method);
+
+ $this->model_extension_payment_cardconnect->addTransaction($cardconnect_order_id, $type, $status, $order_info);
+
+ if (isset($response_data['profileid']) && $this->config->get('cardconnect_store_cards') && $this->customer->isLogged()) {
+ $this->model_extension_payment_cardconnect->log('Saving card');
+
+ $this->model_extension_payment_cardconnect->addCard($cardconnect_order_id, $this->customer->getId(), $response_data['profileid'], $response_data['token'], $this->request->post['card_type'], $response_data['account'], $this->request->post['card_expiry_month'] . $this->request->post['card_expiry_year']);
+ }
+
+ $this->model_extension_payment_cardconnect->log('Success');
+
+ $json['success'] = $this->url->link('checkout/success', '', true);
+ } else {
+ $this->model_extension_payment_cardconnect->log($response_data['resptext']);
+
+ $json['error']['warning'] = $response_data['resptext'];
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('No matching order');
+
+ $json['error']['warning'] = $this->language->get('error_no_order');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Failed validation');
+
+ $json['error'] = $error;
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('No $_POST data');
+
+ $json['error']['warning'] = $this->language->get('error_no_post_data');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Module not enabled');
+
+ $json['error']['warning'] = $this->language->get('error_not_enabled');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function delete() {
+ $this->load->language('extension/payment/cardconnect');
+
+ $this->load->model('extension/payment/cardconnect');
+
+ $this->model_extension_payment_cardconnect->log('Deleting card');
+
+ $json = array();
+
+ if ($this->config->get('cardconnect_status')) {
+ if ($this->customer->isLogged()) {
+ if (isset($this->request->post['card_choice'])) {
+ if ($this->request->post['card_choice']) {
+ $card = $this->model_extension_payment_cardconnect->getCard($this->request->post['card_choice'], $this->customer->getId());
+
+ if ($card) {
+ $this->model_extension_payment_cardconnect->deleteCard($this->request->post['card_choice'], $this->customer->getId());
+ } else {
+ $this->model_extension_payment_cardconnect->log('No such card');
+
+ $json['error'] = $this->language->get('error_no_card');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('No card selected');
+
+ $json['error'] = $this->language->get('error_select_card');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Data missing');
+
+ $json['error'] = $this->language->get('error_data_missing');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Not logged in');
+
+ $json['error'] = $this->language->get('error_not_logged_in');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Module not enabled');
+
+ $json['error']['warning'] = $this->language->get('error_not_enabled');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function cron() {
+ $this->load->model('extension/payment/cardconnect');
+
+ $this->model_extension_payment_cardconnect->log('Running cron');
+
+ if ($this->config->get('cardconnect_status')) {
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('cardconnect_token'), $this->request->get['token'])) {
+ $date = date('md', strtotime('yesterday'));
+
+ $responses = $this->model_extension_payment_cardconnect->getSettlementStatuses($this->config->get('payment_cardconnect_merchant_id'), $date);
+
+ foreach($responses as $response) {
+ foreach($response['txns'] as $transaction) {
+ $this->model_extension_payment_cardconnect->updateTransactionStatusByRetref($transaction['retref'], $transaction['setlstat']);
+ }
+ }
+
+ $this->model_extension_payment_cardconnect->updateCronRunTime();
+ } else {
+ $this->model_extension_payment_cardconnect->log('Token does not match.');
+ }
+ } else {
+ $this->model_extension_payment_cardconnect->log('Module not enabled');
+ }
+ }
+
+ private function validate() {
+ $this->load->language('extension/payment/cardconnect');
+
+ $this->load->model('extension/payment/cardconnect');
+
+ $error = array();
+
+ if (!isset($this->request->post['method']) || $this->request->post['method'] == 'card') {
+ if ($this->request->post['card_new']) {
+ if (!isset($this->request->post['card_number']) || utf8_strlen($this->request->post['card_number']) < 1 || utf8_strlen($this->request->post['card_number']) > 19) {
+ $error['card_number'] = $this->language->get('error_card_number');
+ }
+
+ if (!isset($this->request->post['card_cvv2']) || utf8_strlen($this->request->post['card_cvv2']) < 1 || utf8_strlen($this->request->post['card_cvv2']) > 4) {
+ $error['card_cvv2'] = $this->language->get('error_card_cvv2');
+ }
+ } else {
+ if (isset($this->request->post['card_choice']) && $this->request->post['card_choice']) {
+ $card = $this->model_extension_payment_cardconnect->getCard($this->request->post['card_choice'], $this->customer->getId());
+
+ if (!$card) {
+ $error['card_choice'] = $this->language->get('error_no_card');
+ }
+ } else {
+ $error['card_choice'] = $this->language->get('error_select_card');
+ }
+ }
+ } else {
+ if ($this->config->get('cardconnect_echeck')) {
+ if (!isset($this->request->post['account_number']) || utf8_strlen($this->request->post['account_number']) < 1 || utf8_strlen($this->request->post['account_number']) > 19) {
+ $error['account_number'] = $this->language->get('error_account_number');
+ }
+
+ if (!isset($this->request->post['routing_number']) || utf8_strlen($this->request->post['routing_number']) < 1 || utf8_strlen($this->request->post['routing_number']) > 9) {
+ $error['routing_number'] = $this->language->get('error_routing_number');
+ }
+ } else {
+ $error['method'] = $this->language->get('error_no_echeck');
+ }
+ }
+
+ return $error;
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/cardinity.php b/public/catalog/controller/extension/payment/cardinity.php
new file mode 100644
index 0000000..72cdf6c
--- /dev/null
+++ b/public/catalog/controller/extension/payment/cardinity.php
@@ -0,0 +1,294 @@
+<?php
+class ControllerExtensionPaymentCardinity extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/cardinity');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['years'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['years'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/cardinity', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/cardinity');
+
+ $this->load->language('extension/payment/cardinity');
+
+ $json = array();
+
+ $json['error'] = $json['success'] = $json['3ds'] = '';
+
+ $payment = false;
+
+ $error = $this->validate();
+
+ if (!$error) {
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if (strlen($order_info['order_id']) < 2) {
+ $order_id = '0' . $order_info['order_id'];
+ } else {
+ $order_id = $order_info['order_id'];
+ }
+
+ if (!empty($order_info['payment_iso_code_2'])) {
+ $order_country = $order_info['payment_iso_code_2'];
+ } else {
+ $order_country = $order_info['shipping_iso_code_2'];
+ }
+
+ $payment_data = array(
+ 'amount' => (float)$this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false),
+ 'currency' => $order_info['currency_code'],
+ 'order_id' => $order_id,
+ 'country' => $order_country,
+ 'payment_method' => 'card',
+ 'payment_instrument' => array(
+ 'pan' => preg_replace('!\s+!', '', $this->request->post['pan']),
+ 'exp_year' => (int)$this->request->post['exp_year'],
+ 'exp_month' => (int)$this->request->post['exp_month'],
+ 'cvc' => $this->request->post['cvc'],
+ 'holder' => $this->request->post['holder']
+ ),
+ );
+
+ try {
+ $payment = $this->model_extension_payment_cardinity->createPayment($this->config->get('payment_cardinity_key'), $this->config->get('payment_cardinity_secret'), $payment_data);
+ } catch (Cardinity\Exception\Declined $exception) {
+ $this->failedOrder($this->language->get('error_payment_declined'), $this->language->get('error_payment_declined'));
+
+ $json['redirect'] = $this->url->link('checkout/checkout', '', true);
+ } catch (Exception $exception) {
+ $this->failedOrder();
+
+ $json['redirect'] = $this->url->link('checkout/checkout', '', true);
+ }
+
+ $successful_order_statuses = array(
+ 'approved',
+ 'pending'
+ );
+
+ if ($payment) {
+ if (!in_array($payment->getStatus(), $successful_order_statuses)) {
+ $this->failedOrder($payment->getStatus());
+
+ $json['redirect'] = $this->url->link('checkout/checkout', '', true);
+ } else {
+ $this->model_extension_payment_cardinity->addOrder(array(
+ 'order_id' => $this->session->data['order_id'],
+ 'payment_id' => $payment->getId()
+ ));
+
+ if ($payment->getStatus() == 'pending') {
+ //3ds
+ $authorization_information = $payment->getAuthorizationInformation();
+
+ $encryption_data = array(
+ 'order_id' => $this->session->data['order_id'],
+ 'secret' => $this->config->get('payment_cardinity_secret')
+ );
+
+ $hash = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode($encryption_data));
+
+ $json['3ds'] = array(
+ 'url' => $authorization_information->getUrl(),
+ 'PaReq' => $authorization_information->getData(),
+ 'TermUrl' => $this->url->link('extension/payment/cardinity/threeDSecureCallback', '', true),
+ 'hash' => $hash
+ );
+ } elseif ($payment->getStatus() == 'approved') {
+ $this->finalizeOrder($payment);
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ }
+ }
+ }
+ } else {
+ $json['error'] = $error;
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function threeDSecureForm() {
+ $this->load->model('extension/payment/cardinity');
+
+ $this->load->language('extension/payment/cardinity');
+
+ $success = false;
+ $redirect = false;
+
+ $encryption_data = array(
+ 'order_id' => $this->session->data['order_id'],
+ 'secret' => $this->config->get('payment_cardinity_secret')
+ );
+
+ $hash = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode($encryption_data));
+
+ if (hash_equals($hash, $this->request->post['hash'])) {
+ $success = true;
+
+ $data['url'] = $this->request->post['url'];
+ $data['PaReq'] = $this->request->post['PaReq'];
+ $data['TermUrl'] = $this->request->post['TermUrl'];
+ $data['MD'] = $hash;
+ } else {
+ $this->failedOrder($this->language->get('error_invalid_hash'));
+
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+
+ $data['success'] = $success;
+ $data['redirect'] = $redirect;
+
+ $this->response->setOutput($this->load->view('extension/payment/cardinity_3ds', $data));
+ }
+
+ public function threeDSecureCallback() {
+ $this->load->model('extension/payment/cardinity');
+
+ $this->load->language('extension/payment/cardinity');
+
+ $success = false;
+
+ $error = '';
+
+ $encryption_data = array(
+ 'order_id' => $this->session->data['order_id'],
+ 'secret' => $this->config->get('payment_cardinity_secret')
+ );
+
+ $hash = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode($encryption_data));
+
+ if (hash_equals($hash, $this->request->post['MD'])) {
+ $order = $this->model_extension_payment_cardinity->getOrder($encryption_data['order_id']);
+
+ if ($order && $order['payment_id']) {
+ $payment = $this->model_extension_payment_cardinity->finalizePayment($this->config->get('payment_cardinity_key'), $this->config->get('payment_cardinity_secret'), $order['payment_id'], $this->request->post['PaRes']);
+
+ if ($payment && $payment->getStatus() == 'approved') {
+ $success = true;
+ } else {
+ $error = $this->language->get('error_finalizing_payment');
+ }
+ } else {
+ $error = $this->language->get('error_unknown_order_id');
+ }
+ } else {
+ $error = $this->language->get('error_invalid_hash');
+ }
+
+ if ($success) {
+ $this->finalizeOrder($payment);
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->failedOrder($error);
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ private function finalizeOrder($payment) {
+ $this->load->model('checkout/order');
+
+ $this->load->language('extension/payment/cardinity');
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_cardinity_order_status_id'));
+
+ $this->model_extension_payment_cardinity->log($this->language->get('text_payment_success'));
+ $this->model_extension_payment_cardinity->log($payment);
+ }
+
+ private function failedOrder($log = null, $alert = null) {
+ $this->load->language('extension/payment/cardinity');
+
+ $this->model_extension_payment_cardinity->log($this->language->get('text_payment_failed'));
+
+ if ($log) {
+ $this->model_extension_payment_cardinity->log($log);
+ }
+
+ if ($alert) {
+ $this->session->data['error'] = $alert;
+ } else {
+ $this->session->data['error'] = $this->language->get('error_process_order');
+ }
+ }
+
+ private function validate() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/cardinity');
+
+ $error = array();
+
+ if (!$this->session->data['order_id']) {
+ $error['warning'] = $this->language->get('error_process_order');
+ }
+
+ if (!$error) {
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if (!$order_info) {
+ $error['warning'] = $this->language->get('error_process_order');
+ }
+ }
+
+ if (!in_array($order_info['currency_code'], $this->model_extension_payment_cardinity->getSupportedCurrencies())) {
+ $error['warning'] = $this->language->get('error_invalid_currency');
+ }
+
+ if (!isset($this->request->post['holder']) || utf8_strlen($this->request->post['holder']) < 1 || utf8_strlen($this->request->post['holder']) > 32) {
+ $error['holder'] = true;
+ }
+
+ if (!isset($this->request->post['pan']) || utf8_strlen($this->request->post['pan']) < 1 || utf8_strlen($this->request->post['pan']) > 19) {
+ $error['pan'] = true;
+ }
+
+ if (!isset($this->request->post['pan']) || !is_numeric(preg_replace('!\s+!', '', $this->request->post['pan']))) {
+ $error['pan'] = true;
+ }
+
+ if (!isset($this->request->post['exp_month']) || !isset($this->request->post['exp_year'])) {
+ $error['expiry_date'] = true;
+ } else {
+ $expiry = new DateTime();
+ $expiry->setDate($this->request->post['exp_year'], $this->request->post['exp_month'], '1');
+ $expiry->modify('+1 month');
+ $expiry->modify('-1 day');
+
+ $now = new DateTime();
+
+ if ($expiry < $now) {
+ $error['expiry_date'] = true;
+ }
+ }
+
+ if (!isset($this->request->post['cvc']) || utf8_strlen($this->request->post['cvc']) < 1 || utf8_strlen($this->request->post['cvc']) > 4) {
+ $error['cvc'] = true;
+ }
+
+ return $error;
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/cheque.php b/public/catalog/controller/extension/payment/cheque.php
new file mode 100644
index 0000000..4fbc771
--- /dev/null
+++ b/public/catalog/controller/extension/payment/cheque.php
@@ -0,0 +1,34 @@
+<?php
+class ControllerExtensionPaymentCheque extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/cheque');
+
+ $data['payable'] = $this->config->get('payment_cheque_payable');
+ $data['address'] = nl2br($this->config->get('config_address'));
+
+ return $this->load->view('extension/payment/cheque', $data);
+ }
+
+ public function confirm() {
+ $json = array();
+
+ if ($this->session->data['payment_method']['code'] == 'cheque') {
+ $this->load->language('extension/payment/cheque');
+
+ $this->load->model('checkout/order');
+
+ $comment = $this->language->get('text_payable') . "\n";
+ $comment .= $this->config->get('payment_cheque_payable') . "\n\n";
+ $comment .= $this->language->get('text_address') . "\n";
+ $comment .= $this->config->get('config_address') . "\n\n";
+ $comment .= $this->language->get('text_payment') . "\n";
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_cheque_order_status_id'), $comment, true);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/cod.php b/public/catalog/controller/extension/payment/cod.php
new file mode 100644
index 0000000..4f62182
--- /dev/null
+++ b/public/catalog/controller/extension/payment/cod.php
@@ -0,0 +1,21 @@
+<?php
+class ControllerExtensionPaymentCod extends Controller {
+ public function index() {
+ return $this->load->view('extension/payment/cod');
+ }
+
+ public function confirm() {
+ $json = array();
+
+ if ($this->session->data['payment_method']['code'] == 'cod') {
+ $this->load->model('checkout/order');
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_cod_order_status_id'));
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+}
diff --git a/public/catalog/controller/extension/payment/divido.php b/public/catalog/controller/extension/payment/divido.php
new file mode 100644
index 0000000..ad69ae0
--- /dev/null
+++ b/public/catalog/controller/extension/payment/divido.php
@@ -0,0 +1,301 @@
+<?php
+class ControllerExtensionPaymentDivido extends Controller {
+ const
+ STATUS_ACCEPTED = 'ACCEPTED',
+ STATUS_ACTION_LENDER = 'ACTION-LENDER',
+ STATUS_CANCELED = 'CANCELED',
+ STATUS_COMPLETED = 'COMPLETED',
+ STATUS_DEPOSIT_PAID = 'DEPOSIT-PAID',
+ STATUS_DECLINED = 'DECLINED',
+ STATUS_DEFERRED = 'DEFERRED',
+ STATUS_REFERRED = 'REFERRED',
+ STATUS_FULFILLED = 'FULFILLED',
+ STATUS_SIGNED = 'SIGNED';
+
+ private $status_id = array(
+ self::STATUS_ACCEPTED => 1,
+ self::STATUS_ACTION_LENDER => 2,
+ self::STATUS_CANCELED => 0,
+ self::STATUS_COMPLETED => 2,
+ self::STATUS_DECLINED => 8,
+ self::STATUS_DEFERRED => 1,
+ self::STATUS_REFERRED => 1,
+ self::STATUS_DEPOSIT_PAID => 1,
+ self::STATUS_FULFILLED => 1,
+ self::STATUS_SIGNED => 2,
+ );
+
+ private $history_messages = array(
+ self::STATUS_ACCEPTED => 'Credit request accepted',
+ self::STATUS_ACTION_LENDER => 'Lender notified',
+ self::STATUS_CANCELED => 'Credit request canceled',
+ self::STATUS_COMPLETED => 'Credit application completed',
+ self::STATUS_DECLINED => 'Credit request declined',
+ self::STATUS_DEFERRED => 'Credit request deferred',
+ self::STATUS_REFERRED => 'Credit request referred',
+ self::STATUS_DEPOSIT_PAID => 'Deposit paid',
+ self::STATUS_FULFILLED => 'Credit request fulfilled',
+ self::STATUS_SIGNED => 'Contract signed',
+ );
+
+ public function index() {
+ $this->load->language('extension/payment/divido');
+ $this->load->model('extension/payment/divido');
+ $this->load->model('checkout/order');
+
+ $api_key = $this->config->get('payment_divido_api_key');
+ $key_parts = explode('.', $api_key);
+ $js_key = strtolower(array_shift($key_parts));
+
+ list($total, $totals) = $this->model_extension_payment_divido->getOrderTotals();
+
+ $this->model_extension_payment_divido->setMerchant($this->config->get('payment_divido_api_key'));
+
+ $plans = $this->model_extension_payment_divido->getCartPlans($this->cart);
+ foreach ($plans as $key => $plan) {
+ $planMinTotal = $total - ($total * ($plan->min_deposit / 100));
+ if ($plan->min_amount > $planMinTotal) {
+ unset($plans[$key]);
+ }
+ }
+
+ $plans_ids = array_map(function ($plan) {
+ return $plan->id;
+ }, $plans);
+ $plans_ids = array_unique($plans_ids);
+ $plans_list = implode(',', $plans_ids);
+
+ $data = array(
+ 'button_confirm' => $this->language->get('divido_checkout'),
+ 'merchant_script' => "//cdn.divido.com/calculator/{$js_key}.js",
+ 'grand_total' => $total,
+ 'plan_list' => $plans_list,
+ 'generic_credit_req_error' => 'Credit request could not be initiated',
+ );
+
+ return $this->load->view('extension/payment/divido', $data);
+ }
+
+ public function update() {
+ $this->load->language('extension/payment/divido');
+ $this->load->model('extension/payment/divido');
+ $this->load->model('checkout/order');
+
+ $data = json_decode(file_get_contents('php://input'));
+
+ if (!isset($data->status)) {
+ $this->response->setOutput('');
+ return;
+ }
+
+ $lookup = $this->model_extension_payment_divido->getLookupByOrderId($data->metadata->order_id);
+ if ($lookup->num_rows != 1) {
+ $this->response->setOutput('');
+ return;
+ }
+
+ $hash = $this->model_extension_payment_divido->hashOrderId($data->metadata->order_id, $lookup->row['salt']);
+ if ($hash !== $data->metadata->order_hash) {
+ $this->response->setOutput('');
+ return;
+ }
+
+ $order_id = $data->metadata->order_id;
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+ $status_id = $order_info['order_status_id'];
+ $message = "Status: {$data->status}";
+ if (isset($this->history_messages[$data->status])) {
+ $message = $this->history_messages[$data->status];
+ }
+
+ if ($data->status == self::STATUS_SIGNED) {
+ $status_override = $this->config->get('payment_divido_order_status_id');
+ if (!empty($status_override)) {
+ $this->status_id[self::STATUS_SIGNED] = $status_override;
+ }
+ }
+
+ if (isset($this->status_id[$data->status]) && $this->status_id[$data->status] > $status_id) {
+ $status_id = $this->status_id[$data->status];
+ }
+
+ if ($data->status == self::STATUS_DECLINED && $order_info['order_status_id'] == 0) {
+ $status_id = 0;
+ }
+
+ $this->model_extension_payment_divido->saveLookup($data->metadata->order_id, $lookup->row['salt'], null, $data->application);
+ $this->model_checkout_order->addOrderHistory($order_id, $status_id, $message, false);
+ $this->response->setOutput('ok');
+ }
+
+ public function confirm() {
+ $this->load->language('extension/payment/divido');
+
+ $this->load->model('extension/payment/divido');
+
+ ini_set('html_errors', 0);
+ if (!$this->session->data['payment_method']['code'] == 'divido') {
+ return false;
+ }
+
+ $this->model_extension_payment_divido->setMerchant($this->config->get('payment_divido_api_key'));
+
+ $api_key = $this->config->get('payment_divido_api_key');
+
+ $deposit = $this->request->post['deposit'];
+ $finance = $this->request->post['finance'];
+
+ $address = $this->session->data['payment_address'];
+ if (isset($this->session->data['shipping_address'])) {
+ $address = $this->session->data['shipping_address'];
+ }
+
+ $country = $address['iso_code_2'];
+ $language = strtoupper($this->language->get('code'));
+ $currency = strtoupper($this->session->data['currency']);
+ $order_id = $this->session->data['order_id'];
+
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/customer');
+ $customer_info = $this->model_account_customer->getCustomer($this->customer->getId());
+
+ $firstname = $customer_info['firstname'];
+ $lastname = $customer_info['lastname'];
+ $email = $customer_info['email'];
+ $telephone = $customer_info['telephone'];
+ } elseif (isset($this->session->data['guest'])) {
+ $firstname = $this->session->data['guest']['firstname'];
+ $lastname = $this->session->data['guest']['lastname'];
+ $email = $this->session->data['guest']['email'];
+ $telephone = $this->session->data['guest']['telephone'];
+ }
+
+ $postcode = $address['postcode'];
+
+ $products = array();
+ foreach ($this->cart->getProducts() as $product) {
+ $products[] = array(
+ 'type' => 'product',
+ 'text' => $product['name'],
+ 'quantity' => $product['quantity'],
+ 'value' => $product['price'],
+ );
+ }
+
+ list($total, $totals) = $this->model_extension_payment_divido->getOrderTotals();
+
+ $sub_total = $total;
+ $cart_total = $this->cart->getSubTotal();
+ $shiphandle = $sub_total - $cart_total;
+
+ $products[] = array(
+ 'type' => 'product',
+ 'text' => 'Shipping & Handling',
+ 'quantity' => 1,
+ 'value' => $shiphandle,
+ );
+
+ $deposit_amount = round(($deposit / 100) * $total, 2, PHP_ROUND_HALF_UP);
+
+ $shop_url = $this->config->get('config_url');
+ if (isset($this->request->server['HTTPS']) && (($this->request->server['HTTPS'] == 'on') || ($this->request->server['HTTPS'] == '1'))) {
+ $shop_url = $this->config->get('config_ssl');
+ }
+
+ $callback_url = $this->url->link('extension/payment/divido/update', '', true);
+ $return_url = $this->url->link('checkout/success', '', true);
+ $checkout_url = $this->url->link('checkout/checkout', '', true);
+
+ $salt = uniqid('', true);
+ $hash = $this->model_extension_payment_divido->hashOrderId($order_id, $salt);
+
+ $request_data = array(
+ 'merchant' => $api_key,
+ 'deposit' => $deposit_amount,
+ 'finance' => $finance,
+ 'country' => $country,
+ 'language' => $language,
+ 'currency' => $currency,
+ 'metadata' => array(
+ 'order_id' => $order_id,
+ 'order_hash' => $hash,
+ ),
+ 'customer' => array(
+ 'title' => '',
+ 'first_name' => $firstname,
+ 'middle_name' => '',
+ 'last_name' => $lastname,
+ 'country' => $country,
+ 'postcode' => $postcode,
+ 'email' => $email,
+ 'mobile_number' => '',
+ 'phone_number' => $telephone,
+ ),
+ 'products' => $products,
+ 'response_url' => $callback_url,
+ 'redirect_url' => $return_url,
+ 'checkout_url' => $checkout_url,
+ );
+
+ $response = Divido_CreditRequest::create($request_data);
+
+ if ($response->status == 'ok') {
+
+ $this->model_extension_payment_divido->saveLookup($order_id, $salt, $response->id, null, $deposit_amount);
+
+ $data = array(
+ 'status' => 'ok',
+ 'url' => $response->url,
+ );
+ } else {
+ $data = array(
+ 'status' => 'error',
+ 'message' => $this->language->get($response->error),
+ );
+ }
+
+ $this->response->setOutput(json_encode($data));
+ }
+
+ public function calculator($args) {
+ $this->load->language('extension/payment/divido');
+
+ $this->load->model('extension/payment/divido');
+
+ if (!$this->model_extension_payment_divido->isEnabled()) {
+ return null;
+ }
+
+ $this->model_extension_payment_divido->setMerchant($this->config->get('payment_divido_api_key'));
+
+ $product_selection = $this->config->get('payment_divido_productselection');
+ $price_threshold = $this->config->get('payment_divido_price_threshold');
+ $product_id = $args['product_id'];
+ $product_price = $args['price'];
+ $type = $args['type'];
+
+ if ($product_selection == 'threshold' && $product_price < $price_threshold) {
+ return null;
+ }
+
+ $plans = $this->model_extension_payment_divido->getProductPlans($product_id);
+ if (empty($plans)) {
+ return null;
+ }
+
+ $plans_ids = array_map(function ($plan) {
+ return $plan->id;
+ }, $plans);
+
+ $plan_list = implode(',', $plans_ids);
+
+ $data = array(
+ 'planList' => $plan_list,
+ 'productPrice' => $product_price
+ );
+
+ $filename = ($type == 'full') ? 'extension/payment/divido_calculator' : 'extension/payment/divido_widget';
+
+ return $this->load->view($filename, $data);
+ }
+}
diff --git a/public/catalog/controller/extension/payment/eway.php b/public/catalog/controller/extension/payment/eway.php
new file mode 100644
index 0000000..393d04a
--- /dev/null
+++ b/public/catalog/controller/extension/payment/eway.php
@@ -0,0 +1,303 @@
+<?php
+class ControllerExtensionPaymentEway extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/eway');
+
+ $data['payment_type'] = $this->config->get('payment_eway_payment_type');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => sprintf('%02d', $i),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $amount = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+
+ if ($this->config->get('payment_eway_test')) {
+ $data['text_testing'] = $this->language->get('text_testing');
+ $data['Endpoint'] = 'Sandbox';
+ } else {
+ $data['text_testing'] = '';
+ $data['Endpoint'] = 'Production';
+ }
+
+ $this->load->model('localisation/zone');
+
+ $payment_zone_info = $this->model_localisation_zone->getZone($order_info['payment_zone_id']);
+ $payment_zone_code = isset($payment_zone_info['code']) ? $payment_zone_info['code'] : '';
+
+ $shipping_zone_info = $this->model_localisation_zone->getZone($order_info['shipping_zone_id']);
+ $shipping_zone_code = isset($shipping_zone_info['code']) ? $shipping_zone_info['code'] : '';
+
+ $request = new stdClass();
+
+ $request->Customer = new stdClass();
+ $request->Customer->Title = 'Mr.';
+ $request->Customer->FirstName = (string)substr($order_info['payment_firstname'], 0, 50);
+ $request->Customer->LastName = (string)substr($order_info['payment_lastname'], 0, 50);
+ $request->Customer->CompanyName = (string)substr($order_info['payment_company'], 0, 50);
+ $request->Customer->Street1 = (string)substr($order_info['payment_address_1'], 0, 50);
+ $request->Customer->Street2 = (string)substr($order_info['payment_address_2'], 0, 50);
+ $request->Customer->City = (string)substr($order_info['payment_city'], 0, 50);
+ $request->Customer->State = (string)substr($payment_zone_code, 0, 50);
+ $request->Customer->PostalCode = (string)substr($order_info['payment_postcode'], 0, 30);
+ $request->Customer->Country = strtolower($order_info['payment_iso_code_2']);
+ $request->Customer->Email = $order_info['email'];
+ $request->Customer->Phone = (string)substr($order_info['telephone'], 0, 32);
+
+ $request->ShippingAddress = new stdClass();
+ $request->ShippingAddress->FirstName = (string)substr($order_info['shipping_firstname'], 0, 50);
+ $request->ShippingAddress->LastName = (string)substr($order_info['shipping_lastname'], 0, 50);
+ $request->ShippingAddress->Street1 = (string)substr($order_info['shipping_address_1'], 0, 50);
+ $request->ShippingAddress->Street2 = (string)substr($order_info['shipping_address_2'], 0, 50);
+ $request->ShippingAddress->City = (string)substr($order_info['shipping_city'], 0, 50);
+ $request->ShippingAddress->State = (string)substr($shipping_zone_code, 0, 50);
+ $request->ShippingAddress->PostalCode = (string)substr($order_info['shipping_postcode'], 0, 30);
+ $request->ShippingAddress->Country = strtolower($order_info['shipping_iso_code_2']);
+ $request->ShippingAddress->Email = $order_info['email'];
+ $request->ShippingAddress->Phone = (string)substr($order_info['telephone'], 0, 32);
+ $request->ShippingAddress->ShippingMethod = "Unknown";
+
+ $invoice_desc = '';
+ foreach ($this->cart->getProducts() as $product) {
+ $item_price = $this->currency->format($product['price'], $order_info['currency_code'], false, false);
+ $item_total = $this->currency->format($product['total'], $order_info['currency_code'], false, false);
+ $item = new stdClass();
+ $item->SKU = (string)substr($product['product_id'], 0, 12);
+ $item->Description = (string)substr($product['name'], 0, 26);
+ $item->Quantity = strval($product['quantity']);
+ $item->UnitCost = strval($item_price * 100);
+ $item->Total = $this->lowestDenomination($item_total, $order_info['currency_code']);
+
+ $request->Items[] = $item;
+ $invoice_desc .= $product['name'] . ', ';
+ }
+ $invoice_desc = (string)substr($invoice_desc, 0, -2);
+ if (strlen($invoice_desc) > 64) {
+ $invoice_desc = (string)substr($invoice_desc, 0, 61) . '...';
+ }
+
+ $shipping = $this->currency->format($order_info['total'] - $this->cart->getSubTotal(), $order_info['currency_code'], false, false);
+
+ if ($shipping > 0) {
+ $item = new stdClass();
+ $item->SKU = '';
+ $item->Description = (string)substr($this->language->get('text_shipping'), 0, 26);
+ $item->Quantity = 1;
+ $item->UnitCost = $this->lowestDenomination($shipping, $order_info['currency_code']);
+ $item->Total = $this->lowestDenomination($shipping, $order_info['currency_code']);
+
+ $request->Items[] = $item;
+ }
+
+ $opt1 = new stdClass();
+ $opt1->Value = $order_info['order_id'];
+ $request->Options = array($opt1);
+
+ $request->Payment = new stdClass();
+ $request->Payment->TotalAmount = $this->lowestDenomination($amount, $order_info['currency_code']);
+ $request->Payment->InvoiceNumber = $this->session->data['order_id'];
+ $request->Payment->InvoiceDescription = $invoice_desc;
+ $request->Payment->InvoiceReference = (string)substr($this->config->get('config_name'), 0, 40) . ' - #' . $order_info['order_id'];
+ $request->Payment->CurrencyCode = $order_info['currency_code'];
+
+ $request->RedirectUrl = $this->url->link('extension/payment/eway/callback', '', true);
+ if ($this->config->get('payment_eway_transaction_method') == 'auth') {
+ $request->Method = 'Authorise';
+ } else {
+ $request->Method = 'ProcessPayment';
+ }
+ $request->TransactionType = 'Purchase';
+ $request->DeviceID = 'opencart-' . VERSION . ' eway-trans-2.1.2';
+ $request->CustomerIP = $this->request->server['REMOTE_ADDR'];
+ $request->PartnerID = '0f1bec3642814f89a2ea06e7d2800b7f';
+
+ $this->load->model('extension/payment/eway');
+ $template = 'eway';
+ if ($this->config->get('payment_eway_paymode') == 'iframe') {
+ $request->CancelUrl = 'http://www.example.org';
+ $request->CustomerReadOnly = true;
+ $result = $this->model_extension_payment_eway->getSharedAccessCode($request);
+
+ $template = 'eway_iframe';
+ } else {
+ $result = $this->model_extension_payment_eway->getAccessCode($request);
+ }
+
+ // Check if any error returns
+ if (isset($result->Errors)) {
+ $error_array = explode(",", $result->Errors);
+ $lbl_error = "";
+ foreach ($error_array as $error) {
+ $error = $this->language->get('text_card_message_' . $error);
+ $lbl_error .= $error . "<br />\n";
+ }
+ $this->log->write('eWAY Payment error: ' . $lbl_error);
+ }
+
+ if (isset($lbl_error)) {
+ $data['error'] = $lbl_error;
+ } else {
+ if ($this->config->get('payment_eway_paymode') == 'iframe') {
+ $data['callback'] = $this->url->link('extension/payment/eway/callback', 'AccessCode=' . $result->AccessCode, true);
+ $data['SharedPaymentUrl'] = $result->SharedPaymentUrl;
+ }
+ $data['action'] = $result->FormActionURL;
+ $data['AccessCode'] = $result->AccessCode;
+ }
+
+ return $this->load->view('extension/payment/' . $template, $data);
+ }
+
+ public function lowestDenomination($value, $currency) {
+ $power = $this->currency->getDecimalPlace($currency);
+
+ $value = (float)$value;
+
+ return (int)($value * pow(10, $power));
+ }
+
+ public function ValidateDenomination($value, $currency) {
+ $power = $this->currency->getDecimalPlace($currency);
+
+ $value = (float)$value;
+
+ return (int)($value * pow(10, '-' . $power));
+ }
+
+ public function callback() {
+ $this->load->language('extension/payment/eway');
+
+ if (isset($this->request->get['AccessCode']) || isset($this->request->get['amp;AccessCode'])) {
+
+ $this->load->model('extension/payment/eway');
+
+ if (isset($this->request->get['amp;AccessCode'])) {
+ $access_code = $this->request->get['amp;AccessCode'];
+ } else {
+ $access_code = $this->request->get['AccessCode'];
+ }
+
+ $result = $this->model_extension_payment_eway->getAccessCodeResult($access_code);
+
+ $is_error = false;
+
+ // Check if any error returns
+ if (isset($result->Errors)) {
+ $error_array = explode(",", $result->Errors);
+ $is_error = true;
+ $lbl_error = '';
+ foreach ($error_array as $error) {
+ $error = $this->language->get('text_card_message_' . $error);
+ $lbl_error .= $error . ", ";
+ }
+ $this->log->write('eWAY error: ' . $lbl_error);
+ }
+ if (!$is_error) {
+ $fraud = false;
+ if (!$result->TransactionStatus) {
+ $error_array = explode(", ", $result->ResponseMessage);
+ $is_error = true;
+ $lbl_error = '';
+ $log_error = '';
+ foreach ($error_array as $error) {
+ // Don't show fraud issues to customers
+ if (stripos($error, 'F') === false) {
+ $lbl_error .= $this->language->get('text_card_message_' . $error);
+ } else {
+ $fraud = true;
+ }
+ $log_error .= $this->language->get('text_card_message_' . $error) . ", ";
+ }
+ $log_error = substr($log_error, 0, -2);
+ $this->log->write('eWAY payment failed: ' . $log_error);
+ }
+ }
+
+ $this->load->model('checkout/order');
+
+ if ($is_error) {
+ if ($fraud) {
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ } else {
+ $this->session->data['error'] = $this->language->get('text_transaction_failed');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $order_id = $result->Options[0]->Value;
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $this->load->model('extension/payment/eway');
+ $eway_order_data = array(
+ 'order_id' => $order_id,
+ 'transaction_id' => $result->TransactionID,
+ 'amount' => $this->ValidateDenomination($result->TotalAmount, $order_info['currency_code']),
+ 'currency_code' => $order_info['currency_code'],
+ 'debug_data' => json_encode($result)
+ );
+
+ $error_array = explode(", ", $result->ResponseMessage);
+ $log_error = '';
+ foreach ($error_array as $error) {
+ if (stripos($error, 'F') !== false) {
+ $fraud = true;
+ $log_error .= $this->language->get('text_card_message_' . $error) . ", ";
+ }
+ }
+ $log_error = substr($log_error, 0, -2);
+
+ $eway_order_id = $this->model_extension_payment_eway->addOrder($eway_order_data);
+ $this->model_extension_payment_eway->addTransaction($eway_order_id, $this->config->get('payment_eway_transaction_method'), $result->TransactionID, $order_info);
+
+ if ($fraud) {
+ $message = 'Suspected fraud order: ' . $log_error . "\n";
+ } else {
+ $message = "eWAY Payment accepted\n";
+ }
+ $message .= 'Transaction ID: ' . $result->TransactionID . "\n";
+ $message .= 'Authorisation Code: ' . $result->AuthorisationCode . "\n";
+ $message .= 'Card Response Code: ' . $result->ResponseCode . "\n";
+
+ if ($fraud) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_eway_order_status_fraud_id'), $message);
+ } elseif ($this->config->get('payment_eway_transaction_method') == 'payment') {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_eway_order_status_id'), $message);
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_eway_order_status_auth_id'), $message);
+ }
+
+ if (!empty($result->Customer->TokenCustomerID) && $this->customer->isLogged() && !$this->model_checkout_order->checkToken($result->Customer->TokenCustomerID)) {
+ $card_data = array();
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Token'] = $result->Customer->TokenCustomerID;
+ $card_data['Last4Digits'] = substr(str_replace(' ', '', $result->Customer->CardDetails->Number), -4, 4);
+ $card_data['ExpiryDate'] = $result->Customer->CardDetails->ExpiryMonth . '/' . $result->Customer->CardDetails->ExpiryYear;
+ $card_data['CardType'] = '';
+ $this->model_extension_payment_eway->addFullCard($this->session->data['order_id'], $card_data);
+ }
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/firstdata.php b/public/catalog/controller/extension/payment/firstdata.php
new file mode 100644
index 0000000..a7fde03
--- /dev/null
+++ b/public/catalog/controller/extension/payment/firstdata.php
@@ -0,0 +1,243 @@
+<?php
+class ControllerExtensionPaymentFirstdata extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/firstdata');
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/firstdata');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($this->config->get('payment_firstdata_live_demo') == 1) {
+ $data['action'] = $this->config->get('payment_firstdata_live_url');
+ } else {
+ $data['action'] = $this->config->get('payment_firstdata_demo_url');
+ }
+
+ $data['amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['currency'] = $this->model_extension_payment_firstdata->mapCurrency($order_info['currency_code']);
+ $data['merchant_id'] = $this->config->get('payment_firstdata_merchant_id');
+ $data['timestamp'] = date('Y:m:d-H:i:s');
+ $data['order_id'] = 'CON-' . $this->session->data['order_id'] . 'T' . $data['timestamp'] . mt_rand(1, 999);
+ $data['url_success'] = $this->url->link('checkout/success', '', true);
+ $data['url_fail'] = $this->url->link('extension/payment/firstdata/fail', '', true);
+ $data['url_notify'] = $this->url->link('extension/payment/firstdata/notify', '', true);
+
+ if (preg_match("/Mobile|Android|BlackBerry|iPhone|Windows Phone/", $this->request->server['HTTP_USER_AGENT'])) {
+ $data['mobile'] = true;
+ } else {
+ $data['mobile'] = false;
+ }
+
+ if ($this->config->get('payment_firstdata_auto_settle') == 1) {
+ $data['txntype'] = 'sale';
+ } else {
+ $data['txntype'] = 'preauth';
+ }
+
+ $tmp = $data['merchant_id'] . $data['timestamp'] . $data['amount'] . $data['currency'] . $this->config->get('payment_firstdata_secret');
+ $ascii = bin2hex($tmp);
+ $data['hash'] = sha1($ascii);
+
+ $data['version'] = 'OPENCART-C-' . VERSION;
+
+ $data['bcompany'] = $order_info['payment_company'];
+ $data['bname'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+ $data['baddr1'] = substr($order_info['payment_address_1'], 0, 30);
+ $data['baddr2'] = substr($order_info['payment_address_2'], 0, 30);
+ $data['bcity'] = substr($order_info['payment_city'], 0, 30);
+ $data['bstate'] = substr($order_info['payment_zone'], 0, 30);
+ $data['bcountry'] = $order_info['payment_iso_code_2'];
+ $data['bzip'] = $order_info['payment_postcode'];
+ $data['email'] = $order_info['email'];
+
+ if ($this->cart->hasShipping()) {
+ $data['sname'] = $order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname'];
+ $data['saddr1'] = substr($order_info['shipping_address_1'], 0, 30);
+ $data['saddr2'] = substr($order_info['shipping_address_2'], 0, 30);
+ $data['scity'] = substr($order_info['shipping_city'], 0, 30);
+ $data['sstate'] = substr($order_info['shipping_zone'], 0, 30);
+ $data['scountry'] = $order_info['shipping_iso_code_2'];
+ $data['szip'] = $order_info['shipping_postcode'];
+ } else {
+ $data['sname'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+ $data['saddr1'] = substr($order_info['payment_address_1'], 0, 30);
+ $data['saddr2'] = substr($order_info['payment_address_2'], 0, 30);
+ $data['scity'] = substr($order_info['payment_city'], 0, 30);
+ $data['sstate'] = substr($order_info['payment_zone'], 0, 30);
+ $data['scountry'] = $order_info['payment_iso_code_2'];
+ $data['szip'] = $order_info['payment_postcode'];
+ }
+
+ if ($this->config->get('payment_firstdata_card_storage') == 1 && $this->customer->isLogged()) {
+ $data['card_storage'] = 1;
+ $data['stored_cards'] = $this->model_extension_payment_firstdata->getStoredCards();
+ $data['new_hosted_id'] = sha1($this->customer->getId() . '-' . date("Y-m-d-H-i-s") . rand(10, 500));
+ } else {
+ $data['card_storage'] = 0;
+ $data['stored_cards'] = array();
+ }
+
+ return $this->load->view('extension/payment/firstdata', $data);
+ }
+
+ public function notify() {
+ $this->load->model('extension/payment/firstdata');
+
+ $this->load->model('checkout/order');
+
+ $this->load->language('extension/payment/firstdata');
+
+ $message = '';
+
+ if ($this->config->get('payment_firstdata_debug') == 1) {
+ $this->model_extension_payment_firstdata->logger(print_r($this->request->post, 1));
+ }
+
+ if (isset($this->request->post['txntype']) && isset($this->request->post['notification_hash']) && isset($this->request->post['oid'])) {
+ $local_hash = $this->model_extension_payment_firstdata->responseHash($this->request->post['chargetotal'], $this->request->post['currency'], $this->request->post['txndatetime'], $this->request->post['approval_code']);
+
+ if ($local_hash == $this->request->post['notification_hash']) {
+ $order_id_parts = explode('T', $this->request->post['oid']);
+
+ $order_id = str_replace("CON-","",$order_id_parts[0]);
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($this->request->post['txntype'] == 'preauth' || $this->request->post['txntype'] == 'sale') {
+ if (isset($this->request->post['approval_code'])) {
+ $response_parts = explode(':', $this->request->post['approval_code']);
+
+ $address_codes = array(
+ 'PPX' => $this->language->get('text_address_ppx'),
+ 'YYY' => $this->language->get('text_address_yyy'),
+ 'YNA' => $this->language->get('text_address_yna'),
+ 'NYZ' => $this->language->get('text_address_nyz'),
+ 'NNN' => $this->language->get('text_address_nnn'),
+ 'YPX' => $this->language->get('text_address_ypx'),
+ 'PYX' => $this->language->get('text_address_pyx'),
+ 'XXU' => $this->language->get('text_address_xxu')
+ );
+
+ $cvv_codes = array(
+ 'M' => $this->language->get('text_card_code_m'),
+ 'N' => $this->language->get('text_card_code_n'),
+ 'P' => $this->language->get('text_card_code_p'),
+ 'S' => $this->language->get('text_card_code_s'),
+ 'U' => $this->language->get('text_card_code_u'),
+ 'X' => $this->language->get('text_card_code_x'),
+ 'NONE' => $this->language->get('text_card_code_blank')
+ );
+
+ $card_types = array(
+ 'M' => $this->language->get('text_card_type_m'),
+ 'V' => $this->language->get('text_card_type_v'),
+ 'C' => $this->language->get('text_card_type_c'),
+ 'A' => $this->language->get('text_card_type_a'),
+ 'MA' => $this->language->get('text_card_type_ma'),
+ 'MAESTROUK' => $this->language->get('text_card_type_mauk')
+ );
+
+ if ($response_parts[0] == 'Y') {
+ if (isset($response_parts[3])) {
+ if (strlen($response_parts[3]) == 4) {
+ $address_pass = strtoupper(substr($response_parts[3], 0, 3));
+ $cvv_pass = strtoupper(substr($response_parts[3], -1));
+
+ if (!array_key_exists($cvv_pass, $cvv_codes)) {
+ $cvv_pass = 'NONE';
+ }
+ } else {
+ $address_pass = $response_parts[3];
+ $cvv_pass = 'NONE';
+ }
+
+ $message .= $this->language->get('text_address_response') . $address_codes[$address_pass] . '<br />';
+ $message .= $this->language->get('text_card_code_verify') . $cvv_codes[$cvv_pass] . '<br />';
+ $message .= $this->language->get('text_response_code_full') . $this->request->post['approval_code'] . '<br />';
+ $message .= $this->language->get('text_response_code') . $response_parts[1] . '<br />';
+
+ if (isset($this->request->post['cardnumber'])) {
+ $message .= $this->language->get('text_response_card') . $this->request->post['cardnumber'] . '<br />';
+ }
+
+ if (isset($this->request->post['processor_response_code'])) {
+ $message .= $this->language->get('text_response_proc_code') . $this->request->post['processor_response_code'] . '<br />';
+ }
+
+ if (isset($this->request->post['refnumber'])) {
+ $message .= $this->language->get('text_response_ref') . $this->request->post['refnumber'] . '<br />';
+ }
+
+ if (isset($this->request->post['paymentMethod'])) {
+ $message .= $this->language->get('text_response_card_type') . $card_types[strtoupper($this->request->post['paymentMethod'])] . '<br />';
+ }
+ }
+
+ if (isset($this->request->post['hosteddataid']) && $order_info['customer_id'] != 0) {
+ $this->model_extension_payment_firstdata->storeCard($this->request->post['hosteddataid'], $order_info['customer_id'], $this->request->post['expmonth'], $this->request->post['expyear'], $this->request->post['cardnumber']);
+ }
+
+ $fd_order_id = $this->model_extension_payment_firstdata->addOrder($order_info, $this->request->post['oid'], $this->request->post['tdate']);
+
+ if ($this->config->get('payment_firstdata_auto_settle') == 1) {
+ $this->model_extension_payment_firstdata->addTransaction($fd_order_id, 'payment', $order_info);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_firstdata_order_status_success_settled_id'), $message, false);
+ } else {
+ $this->model_extension_payment_firstdata->addTransaction($fd_order_id, 'auth');
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_firstdata_order_status_success_unsettled_id'), $message, false);
+ }
+ } else {
+ $message = $this->request->post['fail_reason'] . '<br />';
+ $message .= $this->language->get('text_response_code_full') . $this->request->post['approval_code'];
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_firstdata_order_status_decline_id'), $message);
+ }
+ }
+ }
+
+ if ($this->request->post['txntype'] == 'void') {
+ if ($this->request->post['status'] == 'DECLINED') {
+ $fd_order = $this->model_extension_payment_firstdata->getOrder($order_id);
+
+ $this->model_extension_payment_firstdata->updateVoidStatus($order_id, 1);
+
+ $this->model_extension_payment_firstdata->addTransaction($fd_order['firstdata_order_id'], 'void');
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_firstdata_order_status_void_id'), $message, false);
+ }
+ }
+
+ if ($this->request->post['txntype'] == 'postauth') {
+ if ($this->request->post['status'] == 'APPROVED') {
+ $fd_order = $this->model_extension_payment_firstdata->getOrder($order_id);
+
+ $this->model_extension_payment_firstdata->updateCaptureStatus($order_id, 1);
+
+ $this->model_extension_payment_firstdata->addTransaction($fd_order['firstdata_order_id'], 'payment', $order_info);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_firstdata_order_status_success_settled_id'), $message, false);
+ }
+ }
+ } else {
+ $this->model_extension_payment_firstdata->logger('Hash does not match! Received: ' . $this->request->post['notification_hash'] . ', calculated: ' . $local_hash);
+ }
+ } else {
+ $this->model_extension_payment_firstdata->logger('Data is missing from request . ');
+ }
+ }
+
+ public function fail() {
+ $this->load->language('extension/payment/firstdata');
+
+ if (isset($this->request->post['fail_reason']) && !empty($this->request->post['fail_reason'])) {
+ $this->session->data['error'] = $this->request->post['fail_reason'];
+ } else {
+ $this->session->data['error'] = $this->language->get('error_failed');
+ }
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/firstdata_remote.php b/public/catalog/controller/extension/payment/firstdata_remote.php
new file mode 100644
index 0000000..1ad6352
--- /dev/null
+++ b/public/catalog/controller/extension/payment/firstdata_remote.php
@@ -0,0 +1,138 @@
+<?php
+class ControllerExtensionPaymentFirstdataRemote extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/firstdata_remote');
+ $this->load->model('extension/payment/firstdata_remote');
+
+ if ($this->config->get('firstdata_remote_card_storage') == 1 && $this->customer->isLogged()) {
+ $data['card_storage'] = 1;
+ $data['stored_cards'] = $this->model_extension_payment_firstdata_remote->getStoredCards();
+ } else {
+ $data['card_storage'] = 0;
+ $data['stored_cards'] = array();
+ }
+
+ $data['accepted_cards'] = $this->config->get('firstdata_remote_cards_accepted');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/firstdata_remote', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/firstdata_remote');
+ $this->load->language('extension/payment/firstdata_remote');
+
+ $address_codes = array(
+ 'PPX' => $this->language->get('text_address_ppx'),
+ 'YYY' => $this->language->get('text_address_yyy'),
+ 'YNA' => $this->language->get('text_address_yna'),
+ 'NYZ' => $this->language->get('text_address_nyz'),
+ 'NNN' => $this->language->get('text_address_nnn'),
+ 'YPX' => $this->language->get('text_address_ypx'),
+ 'PYX' => $this->language->get('text_address_pyx'),
+ 'XXU' => $this->language->get('text_address_xxu')
+ );
+
+ $cvv_codes = array(
+ 'M' => $this->language->get('text_card_code_m'),
+ 'N' => $this->language->get('text_card_code_n'),
+ 'P' => $this->language->get('text_card_code_p'),
+ 'S' => $this->language->get('text_card_code_s'),
+ 'U' => $this->language->get('text_card_code_u'),
+ 'X' => $this->language->get('text_card_code_x'),
+ 'NONE' => $this->language->get('text_card_code_blank')
+ );
+
+ if (!isset($this->request->post['cc_choice']) || (isset($this->request->post['cc_choice']) && $this->request->post['cc_choice'] == 'new')) {
+ if ($this->request->post['cc_number'] == '') {
+ $json['error'] = $this->language->get('error_card_number');
+ }
+
+ if ($this->request->post['cc_name'] == '') {
+ $json['error'] = $this->language->get('error_card_name');
+ }
+ }
+
+ if (strlen($this->request->post['cc_cvv2']) != 3 && strlen($this->request->post['cc_cvv2']) != 4) {
+ $json['error'] = $this->language->get('error_card_cvv');
+ }
+
+ if (empty($json['error'])) {
+ $order_id = $this->session->data['order_id'];
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $capture_result = $this->model_extension_payment_firstdata_remote->capturePayment($this->request->post, $order_id);
+
+ $message = '';
+
+ if (isset($capture_result['transaction_result']) && strtoupper($capture_result['transaction_result']) == 'APPROVED') {
+ $json['success'] = $this->url->link('checkout/success');
+
+ $message .= $this->language->get('text_result') . $capture_result['transaction_result'] . '<br />';
+ $message .= $this->language->get('text_avs') . $address_codes[$capture_result['avs']] . ' (' . $capture_result['avs'] . ')<br />';
+
+ if (!empty($capture_result['ccv'])) {
+ $message .= $this->language->get('text_card_code_verify') . $cvv_codes[$capture_result['ccv']] . ' (' . $capture_result['ccv'] . ')<br />';
+ }
+
+ $message .= $this->language->get('text_approval_code') . $capture_result['approval_code'] . '<br />';
+ $message .= $this->language->get('text_reference_number') . $capture_result['reference_number'] . '<br />';
+ $message .= $this->language->get('text_card_brand') . $capture_result['brand'] . '<br />';
+ $message .= $this->language->get('text_card_number_ref') . $capture_result['card_number_ref'] . '<br />';
+ $message .= $this->language->get('text_response_code') . $capture_result['response_code'] . '<br />';
+
+ $fd_order_id = $this->model_extension_payment_firstdata_remote->addOrder($order_info, $capture_result);
+
+ if ($this->config->get('firstdata_remote_auto_settle') == 1) {
+ $this->model_extension_payment_firstdata_remote->addTransaction($fd_order_id, 'payment', $order_info);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('firstdata_remote_order_status_success_settled_id'), $message, false);
+ } else {
+ $this->model_extension_payment_firstdata_remote->addTransaction($fd_order_id, 'auth');
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('firstdata_remote_order_status_success_unsettled_id'), $message, false);
+ }
+ } else {
+ if (isset($capture_result['error']) && !empty($capture_result['error'])) {
+ $json['error'] = $capture_result['error'];
+ } else {
+ $json['error'] = $this->language->get('error_failed');
+ }
+
+ if (isset($capture_result['fault']) && !empty($capture_result['fault'])) {
+ $message .= $this->language->get('text_fault') . $capture_result['fault'] . '<br />';
+ }
+
+ $message .= $this->language->get('text_result') . $capture_result['transaction_result'] . '<br />';
+ $message .= $this->language->get('text_error') . $capture_result['error'] . '<br />';
+ $message .= $this->language->get('text_card_brand') . $capture_result['brand'] . '<br />';
+ $message .= $this->language->get('text_card_number_ref') . $capture_result['card_number_ref'] . '<br />';
+
+ $this->model_extension_payment_firstdata_remote->addHistory($order_id, $this->config->get('firstdata_remote_order_status_decline_id'), $message);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/free_checkout.php b/public/catalog/controller/extension/payment/free_checkout.php
new file mode 100644
index 0000000..f4674c4
--- /dev/null
+++ b/public/catalog/controller/extension/payment/free_checkout.php
@@ -0,0 +1,16 @@
+<?php
+class ControllerExtensionPaymentFreeCheckout extends Controller {
+ public function index() {
+ $data['continue'] = $this->url->link('checkout/success');
+
+ return $this->load->view('extension/payment/free_checkout', $data);
+ }
+
+ public function confirm() {
+ if ($this->session->data['payment_method']['code'] == 'free_checkout') {
+ $this->load->model('checkout/order');
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_free_checkout_order_status_id'));
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/g2apay.php b/public/catalog/controller/extension/payment/g2apay.php
new file mode 100644
index 0000000..fe66b9b
--- /dev/null
+++ b/public/catalog/controller/extension/payment/g2apay.php
@@ -0,0 +1,189 @@
+<?php
+class ControllerExtensionPaymentG2APay extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/g2apay');
+
+ $data['action'] = $this->url->link('extension/payment/g2apay/checkout', '', true);
+
+ return $this->load->view('extension/payment/g2apay', $data);
+ }
+
+ public function checkout() {
+ $this->load->model('checkout/order');
+ $this->load->model('account/order');
+ $this->load->model('extension/payment/g2apay');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $order_data = array();
+
+ $this->load->model('setting/extension');
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $i = 0;
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+
+ if (isset($order_data['totals'][$i])) {
+ if (strstr(strtolower($order_data['totals'][$i]['code']), 'total') === false) {
+ $item = new stdClass();
+ $item->sku = $order_data['totals'][$i]['code'];
+ $item->name = $order_data['totals'][$i]['title'];
+ $item->amount = number_format($order_data['totals'][$i]['value'], 2);
+ $item->qty = 1;
+ $item->id = $order_data['totals'][$i]['code'];
+ $item->price = $order_data['totals'][$i]['value'];
+ $item->url = $this->url->link('common/home', '', true);
+ $items[] = $item;
+ }
+
+ $i++;
+ }
+ }
+ }
+
+ $ordered_products = $this->model_account_order->getOrderProducts($this->session->data['order_id']);
+
+ foreach ($ordered_products as $product) {
+ $item = new stdClass();
+ $item->sku = $product['product_id'];
+ $item->name = $product['name'];
+ $item->amount = $product['price'] * $product['quantity'];
+ $item->qty = $product['quantity'];
+ $item->id = $product['product_id'];
+ $item->price = $product['price'];
+ $item->url = $this->url->link('product/product', 'product_id=' . $product['product_id'], true);
+ $items[] = $item;
+ }
+
+ if ($this->config->get('payment_g2apay_environment') == 1) {
+ $url = 'https://checkout.pay.g2a.com/index/createQuote';
+ } else {
+ $url = 'https://checkout.test.pay.g2a.com/index/createQuote';
+ }
+
+ $order_total = number_format($order_info['total'], 2);
+
+ $string = $this->session->data['order_id'] . $order_total . $order_info['currency_code'] . html_entity_decode($this->config->get('payment_g2apay_secret'));
+
+ $fields = array(
+ 'api_hash' => $this->config->get('payment_g2apay_api_hash'),
+ 'hash' => hash('sha256', $string),
+ 'order_id' => $this->session->data['order_id'],
+ 'amount' => $order_total,
+ 'currency' => $order_info['currency_code'],
+ 'email' => $order_info['email'],
+ 'url_failure' => $this->url->link('checkout/failure'),
+ 'url_ok' => $this->url->link('extension/payment/g2apay/success'),
+ 'items' => json_encode($items)
+ );
+
+ $response_data = $this->model_extension_payment_g2apay->sendCurl($url, $fields);
+
+ $this->model_extension_payment_g2apay->logger($order_total);
+ $this->model_extension_payment_g2apay->logger($items);
+ $this->model_extension_payment_g2apay->logger($fields);
+
+ if ($response_data === false) {
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ if (strtolower($response_data->status) != 'ok') {
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ $this->model_extension_payment_g2apay->addG2aOrder($order_info);
+
+ if ($this->config->get('payment_g2apay_environment') == 1) {
+ $this->response->redirect('https://checkout.pay.g2a.com/index/gateway?token=' . $response_data->token);
+ } else {
+ $this->response->redirect('https://checkout.test.pay.g2a.com/index/gateway?token=' . $response_data->token);
+ }
+ }
+
+ public function success() {
+ $order_id = $this->session->data['order_id'];
+
+ if (isset($this->request->post['transaction_id'])) {
+ $g2apay_transaction_id = $this->request->post['transaction_id'];
+ } elseif (isset($this->request->get['transaction_id'])) {
+ $g2apay_transaction_id = $this->request->get['transaction_id'];
+ } else {
+ $g2apay_transaction_id = '';
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $this->load->model('extension/payment/g2apay');
+
+ $g2apay_order_info = $this->model_extension_payment_g2apay->getG2aOrder($order_id);
+
+ $this->model_extension_payment_g2apay->updateOrder($g2apay_order_info['g2apay_order_id'], $g2apay_transaction_id, 'payment', $order_info);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_g2apay_order_status_id'));
+ }
+
+ $this->response->redirect($this->url->link('checkout/success'));
+ }
+
+ public function ipn() {
+ $this->load->model('extension/payment/g2apay');
+ $this->model_extension_payment_g2apay->logger('ipn');
+
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_g2apay_secret_token'), $this->request->get['token'])) {
+ $this->model_extension_payment_g2apay->logger('token success');
+
+ if (isset($this->request->post['userOrderId'])) {
+ $g2apay_order = $this->model_extension_payment_g2apay->getG2aOrder($this->request->post['userOrderId']);
+
+ $string = $g2apay_order['g2apay_transaction_id'] . $g2apay_order['order_id'] . round($g2apay_order['total'], 2) . html_entity_decode($this->config->get('payment_g2apay_secret'));
+ $hash = hash('sha256', $string);
+ if($hash != $this->request->post['hash']){
+ $this->model_extension_payment_g2apay->logger('Hashes do not match, possible tampering!');
+ return;
+ }
+
+ switch ($this->request->post['status']) {
+ case 'complete':
+ $order_status_id = $this->config->get('payment_g2apay_complete_status_id');
+ break;
+ case 'rejected':
+ $order_status_id = $this->config->get('payment_g2apay_rejected_status_id');
+ break;
+ case 'canceled':
+ $order_status_id = $this->config->get('payment_g2apay_cancelled_status_id');
+ break;
+ case 'partial_refunded':
+ $order_status_id = $this->config->get('payment_g2apay_partially_refunded_status_id');
+ break;
+ case 'refunded':
+ $order_status_id = $this->config->get('payment_g2apay_refunded_status_id');
+ break;
+ }
+
+ $this->load->model('checkout/order');
+ $this->model_checkout_order->addOrderHistory($this->request->post['userOrderId'], $order_status_id);
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/globalpay.php b/public/catalog/controller/extension/payment/globalpay.php
new file mode 100644
index 0000000..5e8989c
--- /dev/null
+++ b/public/catalog/controller/extension/payment/globalpay.php
@@ -0,0 +1,252 @@
+<?php
+class ControllerExtensionPaymentGlobalpay extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/globalpay');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($this->config->get('payment_globalpay_live_demo') == 1) {
+ $data['action'] = $this->config->get('payment_globalpay_live_url');
+ } else {
+ $data['action'] = $this->config->get('payment_globalpay_demo_url');
+ }
+
+ if ($this->config->get('payment_globalpay_card_select') == 1) {
+ $card_types = array(
+ 'visa' => $this->language->get('text_card_visa'),
+ 'mc' => $this->language->get('text_card_mc'),
+ 'amex' => $this->language->get('text_card_amex'),
+ 'switch' => $this->language->get('text_card_switch'),
+ 'laser' => $this->language->get('text_card_laser'),
+ 'diners' => $this->language->get('text_card_diners'),
+ );
+
+ $data['cards'] = array();
+
+ $accounts = $this->config->get('payment_globalpay_account');
+
+ foreach ($accounts as $card => $account) {
+ if (isset($account['enabled']) && $account['enabled'] == 1) {
+ $data['cards'][] = array(
+ 'type' => $card_types[$card],
+ 'account' => (isset($account['default']) && $account['default'] == 1 ? $this->config->get('payment_globalpay_merchant_id') : $account['merchant_id']),
+ );
+ }
+ }
+
+ $data['card_select'] = true;
+ } else {
+ $data['card_select'] = false;
+ }
+
+ if ($this->config->get('payment_globalpay_auto_settle') == 0) {
+ $data['settle'] = 0;
+ } elseif ($this->config->get('payment_globalpay_auto_settle') == 1) {
+ $data['settle'] = 1;
+ } elseif ($this->config->get('payment_globalpay_auto_settle') == 2) {
+ $data['settle'] = 'MULTI';
+ }
+
+ $data['tss'] = (int)$this->config->get('payment_globalpay_tss_check');
+ $data['merchant_id'] = $this->config->get('payment_globalpay_merchant_id');
+
+ $data['timestamp'] = strftime("%Y%m%d%H%M%S");
+ $data['order_id'] = $this->session->data['order_id'] . 'T' . $data['timestamp'] . mt_rand(1, 999);
+
+ $data['amount'] = round($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false)*100);
+ $data['currency'] = $order_info['currency_code'];
+
+ $tmp = $data['timestamp'] . '.' . $data['merchant_id'] . '.' . $data['order_id'] . '.' . $data['amount'] . '.' . $data['currency'];
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $this->config->get('payment_globalpay_secret');
+ $data['hash'] = sha1($tmp);
+
+ $data['billing_code'] = filter_var(str_replace('-', '', $order_info['payment_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['payment_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['payment_country'] = $order_info['payment_iso_code_2'];
+
+ if ($this->cart->hasShipping()) {
+ $data['shipping_code'] = filter_var(str_replace('-', '', $order_info['shipping_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['shipping_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['shipping_country'] = $order_info['shipping_iso_code_2'];
+ } else {
+ $data['shipping_code'] = filter_var(str_replace('-', '', $order_info['payment_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['payment_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['shipping_country'] = $order_info['payment_iso_code_2'];
+ }
+
+ $data['response_url'] = HTTPS_SERVER . 'index.php?route=extension/payment/globalpay/notify';
+
+ return $this->load->view('extension/payment/globalpay', $data);
+ }
+
+ public function notify() {
+ $this->load->model('extension/payment/globalpay');
+
+ $this->model_extension_payment_globalpay->logger(print_r($this->request->post, 1));
+
+ $this->load->language('extension/payment/globalpay');
+
+ $hash = sha1($this->request->post['TIMESTAMP'] . '.' . $this->config->get('payment_globalpay_merchant_id') . '.' . $this->request->post['ORDER_ID'] . '.' . $this->request->post['RESULT'] . '.' . $this->request->post['MESSAGE'] . '.' . $this->request->post['PASREF'] . '.' . $this->request->post['AUTHCODE']);
+ $tmp = $hash . '.' . $this->config->get('payment_globalpay_secret');
+ $hash = sha1($tmp);
+
+ //Check to see if hashes match or not
+ if ($hash != $this->request->post['SHA1HASH']) {
+ $data['text_response'] = $this->language->get('text_hash_failed');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->load->model('checkout/order');
+
+ $order_id_parts = explode('T', $this->request->post['ORDER_ID']);
+ $order_id = (int)$order_id_parts[0];
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $auto_settle = (int)$this->config->get('payment_globalpay_auto_settle');
+ $tss = (int)$this->config->get('payment_globalpay_tss_check');
+
+ $message = '<strong>' . $this->language->get('text_result') . ':</strong> ' . $this->request->post['RESULT'];
+ $message .= '<br /><strong>' . $this->language->get('text_message') . ':</strong> ' . $this->request->post['MESSAGE'];
+
+ if (isset($this->request->post['ORDER_ID'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_order_ref') . ':</strong> ' . $this->request->post['ORDER_ID'];
+ }
+
+ if (isset($this->request->post['CVNRESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_cvn_result') . ':</strong> ' . $this->request->post['CVNRESULT'];
+ }
+
+ if (isset($this->request->post['AVSPOSTCODERESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_avs_postcode') . ':</strong> ' . $this->request->post['AVSPOSTCODERESULT'];
+ }
+
+ if (isset($this->request->post['AVSADDRESSRESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_avs_address') . ':</strong> ' . $this->request->post['AVSADDRESSRESULT'];
+ }
+
+ //3D Secure message
+ if (isset($this->request->post['ECI']) && isset($this->request->post['CAVV']) && isset($this->request->post['XID'])) {
+ $eci = $this->request->post['ECI'];
+
+ if (($this->request->post['ECI'] == 6 || $this->request->post['ECI'] == 1) && empty($this->request->post['CAVV']) && empty($this->request->post['XID'])) {
+ $scenario_id = 1;
+ }
+
+ if (($this->request->post['ECI'] == 5 || $this->request->post['ECI'] == 0) && !empty($this->request->post['CAVV']) && !empty($this->request->post['XID'])) {
+ $scenario_id = 5;
+ }
+
+ if (($this->request->post['ECI'] == 6 || $this->request->post['ECI'] == 1) && !empty($this->request->post['CAVV']) && !empty($this->request->post['XID'])) {
+ $scenario_id = 6;
+ }
+
+ if (isset($scenario_id)) {
+ $scenario_message = $this->language->get('text_3d_s' . $scenario_id);
+ } else {
+ if (isset($this->request->post['CARDTYPE'])) {
+ if ($this->request->post['CARDTYPE'] == 'VISA') {
+ $eci = 7;
+ } else {
+ $eci = 2;
+ }
+ }
+
+ $scenario_message = $this->language->get('text_3d_liability');
+ }
+
+ $message .= '<br /><strong>' . $this->language->get('text_eci') . ':</strong> (' . $eci . ') ' . $scenario_message;
+ }
+
+ if ($tss == 1 && isset($this->request->post['TSS'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_tss') . ':</strong> ' . $this->request->post['TSS'];
+ }
+
+ if (isset($this->request->post['TIMESTAMP'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_timestamp') . ':</strong> ' . $this->request->post['TIMESTAMP'];
+ }
+
+ if (isset($this->request->post['CARDDIGITS'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_digits') . ':</strong> ' . $this->request->post['CARDDIGITS'];
+ }
+
+ if (isset($this->request->post['CARDTYPE'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_type') . ':</strong> ' . $this->request->post['CARDTYPE'];
+ }
+
+ if (isset($this->request->post['EXPDATE'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_exp') . ':</strong> ' . $this->request->post['EXPDATE'];
+ }
+
+ if (isset($this->request->post['CARDNAME'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_name') . ':</strong> ' . $this->request->post['CARDNAME'];
+ }
+
+ if (isset($this->request->post['DCCAUTHCARDHOLDERAMOUNT']) && isset($this->request->post['DCCAUTHRATE'])) {
+ $message .= '<br /><strong>DCCAUTHCARDHOLDERAMOUNT:</strong> ' . $this->request->post['DCCAUTHCARDHOLDERAMOUNT'];
+ $message .= '<br /><strong>DCCAUTHRATE:</strong> ' . $this->request->post['DCCAUTHRATE'];
+ $message .= '<br /><strong>DCCAUTHCARDHOLDERCURRENCY:</strong> ' . $this->request->post['DCCAUTHCARDHOLDERCURRENCY'];
+ $message .= '<br /><strong>DCCAUTHMERCHANTCURRENCY:</strong> ' . $this->request->post['DCCAUTHMERCHANTCURRENCY'];
+ $message .= '<br /><strong>DCCAUTHMERCHANTAMOUNT:</strong> ' . $this->request->post['DCCAUTHMERCHANTAMOUNT'];
+ $message .= '<br /><strong>DCCCCP:</strong> ' . $this->request->post['DCCCCP'];
+ $message .= '<br /><strong>DCCRATE:</strong> ' . $this->request->post['DCCRATE'];
+ $message .= '<br /><strong>DCCMARGINRATEPERCENTAGE:</strong> ' . $this->request->post['DCCMARGINRATEPERCENTAGE'];
+ $message .= '<br /><strong>DCCEXCHANGERATESOURCENAME:</strong> ' . $this->request->post['DCCEXCHANGERATESOURCENAME'];
+ $message .= '<br /><strong>DCCCOMMISSIONPERCENTAGE:</strong> ' . $this->request->post['DCCCOMMISSIONPERCENTAGE'];
+ $message .= '<br /><strong>DCCEXCHANGERATESOURCETIMESTAMP:</strong> ' . $this->request->post['DCCEXCHANGERATESOURCETIMESTAMP'];
+ $message .= '<br /><strong>DCCCHOICE:</strong> ' . $this->request->post['DCCCHOICE'];
+ }
+
+ if ($this->request->post['RESULT'] == "00") {
+ $globalpay_order_id = $this->model_extension_payment_globalpay->addOrder($order_info, $this->request->post['PASREF'], $this->request->post['AUTHCODE'], $this->request->post['ACCOUNT'], $this->request->post['ORDER_ID']);
+
+ if ($auto_settle == 1) {
+ $this->model_extension_payment_globalpay->addTransaction($globalpay_order_id, 'payment', $order_info);
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('globalpay_order_status_success_settled_id'), $message, false);
+ } else {
+ $this->model_extension_payment_globalpay->addTransaction($globalpay_order_id, 'auth', 0.00);
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_globalpay_order_status_success_unsettled_id'), $message, false);
+ }
+
+ $data['text_response'] = $this->language->get('text_success');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/success', '', true));
+ } elseif ($this->request->post['RESULT'] == "101") {
+ // Decline
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "102") {
+ // Referal B
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_pending_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "103") {
+ // Referal A
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_stolen_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "200") {
+ // Error Connecting to Bank
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "204") {
+ // Error Connecting to Bank
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "205") {
+ // Comms Error
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } else {
+ // Other error
+ $this->model_extension_payment_globalpay->addHistory($order_id, $this->config->get('payment_globalpay_order_status_decline_id'), $message);
+ $data['text_response'] = $this->language->get('text_generic_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ $this->response->setOutput($this->load->view('extension/payment/globalpay_response', $data));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/globalpay_remote.php b/public/catalog/controller/extension/payment/globalpay_remote.php
new file mode 100644
index 0000000..fb0afb7
--- /dev/null
+++ b/public/catalog/controller/extension/payment/globalpay_remote.php
@@ -0,0 +1,335 @@
+<?php
+class ControllerExtensionPaymentGlobalpayRemote extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/globalpay_remote');
+
+ $accounts = $this->config->get('payment_globalpay_remote_account');
+
+ $card_types = array(
+ 'visa' => $this->language->get('text_card_visa'),
+ 'mc' => $this->language->get('text_card_mc'),
+ 'amex' => $this->language->get('text_card_amex'),
+ 'switch' => $this->language->get('text_card_switch'),
+ 'laser' => $this->language->get('text_card_laser'),
+ 'diners' => $this->language->get('text_card_diners'),
+ );
+
+ $data['cards'] = array();
+
+ foreach ($accounts as $card => $account) {
+ if (isset($account['enabled']) && $account['enabled'] == 1) {
+ $data['cards'][] = array(
+ 'code' => $card,
+ 'text' => $card_types[$card],
+ );
+ }
+ }
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/globalpay_remote', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/globalpay_remote');
+
+ $this->load->language('extension/payment/globalpay_remote');
+
+ if ($this->request->post['cc_number'] == '') {
+ $json['error'] = $this->language->get('error_card_number');
+ }
+
+ if ($this->request->post['cc_name'] == '') {
+ $json['error'] = $this->language->get('error_card_name');
+ }
+
+ if (strlen($this->request->post['cc_cvv2']) != 3 && strlen($this->request->post['cc_cvv2']) != 4) {
+ $json['error'] = $this->language->get('error_card_cvv');
+ }
+
+ if (isset($json['error'])) {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ die();
+ }
+
+ $order_id = $this->session->data['order_id'];
+
+ $order_ref = $order_id . 'T' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $amount = round($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) * 100);
+ $currency = $order_info['currency_code'];
+
+ $accounts = $this->config->get('payment_globalpay_remote_account');
+
+ if (isset($accounts[$this->request->post['cc_type']]['default']) && $accounts[$this->request->post['cc_type']]['default'] == 1) {
+ $account = $this->config->get('payment_globalpay_remote_merchant_id');
+ } else {
+ $account = $accounts[$this->request->post['cc_type']]['merchant_id'];
+ }
+
+ $eci_ref = '';
+ $eci = '';
+ $cavv = '';
+ $xid = '';
+
+ if ($this->config->get('payment_globalpay_remote_3d') == 1) {
+ if ($this->request->post['cc_type'] == 'visa' || $this->request->post['cc_type'] == 'mc' || $this->request->post['cc_type'] == 'amex') {
+ $verify_3ds = $this->model_extension_payment_globalpay_remote->checkEnrollment($account, $amount, $currency, $order_ref);
+
+ $this->model_extension_payment_globalpay_remote->logger('Verify 3DS result:\r\n' . print_r($verify_3ds, 1));
+
+ // Proceed to 3D secure
+ if (isset($verify_3ds->result) && $verify_3ds->result == '00') {
+ $enc_data = array(
+ 'account' => $account,
+ 'amount' => $amount,
+ 'currency' => $currency,
+ 'order_id' => $order_id,
+ 'order_ref' => $order_ref,
+ 'cc_number' => $this->request->post['cc_number'],
+ 'cc_expire' => $this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year'],
+ 'cc_name' => $this->request->post['cc_name'],
+ 'cc_type' => $this->request->post['cc_type'],
+ 'cc_cvv2' => $this->request->post['cc_cvv2'],
+ 'cc_issue' => $this->request->post['cc_issue']
+ );
+
+ $md = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode($enc_data));
+
+ $json = array();
+ $json['ACSURL'] = (string)$verify_3ds->url;
+ $json['MD'] = $md;
+ $json['PaReq'] = (string)$verify_3ds->pareq;
+ $json['TermUrl'] = $this->url->link('extension/payment/globalpay_remote/acsReturn', '', true);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ }
+
+ // Cardholder Not Enrolled. Shift in liability. ECI = 6
+ if (isset($verify_3ds->result) && $verify_3ds->result == '110' && isset($verify_3ds->enrolled) && $verify_3ds->enrolled == 'N') {
+ $eci_ref = 1;
+ $xid = '';
+ $cavv = '';
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 1;
+ } else {
+ $eci = 6;
+ }
+ }
+
+ // Unable to Verify Enrollment. No shift in liability. ECI = 7
+ if (isset($verify_3ds->result) && $verify_3ds->result == '110' && isset($verify_3ds->enrolled) && $verify_3ds->enrolled == 'U') {
+ if ($this->config->get('payment_globalpay_remote_liability') != 1) {
+ $this->load->language('extension/payment/globalpay_remote');
+
+ $json['error'] = $this->language->get('error_3d_unable');
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ } else {
+ $eci_ref = 2;
+ $xid = '';
+ $cavv = '';
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+ }
+ }
+
+ // Invalid response from Enrollment Server. No shift in liability. ECI = 7
+ if (isset($verify_3ds->result) && $verify_3ds->result >= 500 && $verify_3ds->result < 600) {
+ if ($this->config->get('payment_globalpay_remote_liability') != 1) {
+ $this->load->language('extension/payment/globalpay_remote');
+
+ $json['error'] = (string)$verify_3ds->message;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ } else {
+ $eci_ref = 3;
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+ }
+ }
+ }
+ }
+
+ $capture_result = $this->model_extension_payment_globalpay_remote->capturePayment(
+ $account,
+ $amount,
+ $currency,
+ $order_id,
+ $order_ref,
+ $this->request->post['cc_number'],
+ $this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year'],
+ $this->request->post['cc_name'],
+ $this->request->post['cc_type'],
+ $this->request->post['cc_cvv2'],
+ $this->request->post['cc_issue'],
+ $eci_ref,
+ $eci,
+ $cavv,
+ $xid
+ );
+
+ $this->model_extension_payment_globalpay_remote->logger('Capture result:\r\n' . print_r($capture_result, 1));
+
+ if ($capture_result->result != '00') {
+ $json['error'] = (string)$capture_result->message . ' (' . (int)$capture_result->result . ')';
+ } else {
+ $json['success'] = $this->url->link('checkout/success');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function acsReturn() {
+ if (isset($this->session->data['order_id'])) {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/globalpay_remote');
+
+ $post = $this->request->post;
+
+ $md = json_decode($this->encryption->decrypt($this->config->get('config_encryption'), $post['MD']), true);
+
+ $signature_result = $this->model_extension_payment_globalpay_remote->enrollmentSignature($md['account'], $md['amount'], $md['currency'], $md['order_ref'], $md['cc_number'], $md['cc_expire'], $md['cc_type'], $md['cc_name'], $post['PaRes']);
+
+ $this->model_extension_payment_globalpay_remote->logger('Signature result:\r\n' . print_r($signature_result, 1));
+
+ if ($signature_result->result == '00' && (strtoupper($signature_result->threedsecure->status) == 'Y' || strtoupper($signature_result->threedsecure->status) == 'A')) {
+ if (strtoupper($signature_result->threedsecure->status) == 'Y') {
+ $eci_ref = 5;
+ } else {
+ $eci_ref = 6;
+ }
+
+ $eci = (string)$signature_result->threedsecure->eci;
+ $cavv = (string)$signature_result->threedsecure->cavv;
+ $xid = (string)$signature_result->threedsecure->xid;
+ } else {
+ if ($md['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+
+ // Enrolled but invalid response from ACS. No shift in liability. ECI = 7
+ if ($signature_result->result == '110' && strtoupper($signature_result->threedsecure->status) == 'Y') {
+ $eci_ref = 4;
+ $cavv = (string)$signature_result->threedsecure->cavv;
+ $xid = (string)$signature_result->threedsecure->xid;
+ }
+
+ // Incorrect password entered. No shift in liability. ECI = 7
+ if ($signature_result->result == '00' && strtoupper($signature_result->threedsecure->status) == 'N') {
+ $eci_ref = 7;
+ $xid = (string)$signature_result->threedsecure->xid;
+ $cavv = '';
+ }
+
+ // Authentication Unavailable. No shift in liability. ECI = 7
+ if ($signature_result->result == '00' && strtoupper($signature_result->threedsecure->status) == 'U') {
+ $eci_ref = 8;
+ $xid = (string)$signature_result->threedsecure->xid;
+ $cavv = '';
+ }
+
+ // Invalid response from ACS. No shift in liability. ECI = 7
+ if (isset($signature_result->result) && $signature_result->result >= 500 && $signature_result->result < 600) {
+ $eci_ref = 9;
+ $xid = '';
+ $cavv = '';
+ }
+
+ if ($this->config->get('payment_globalpay_remote_liability') != 1) {
+ // this is the check for liability shift - if the merchant does not want to accept, redirect to checkout with message
+ $this->load->language('extension/payment/globalpay_remote');
+
+ $message = $this->language->get('error_3d_unsuccessful');
+ $message .= '<br /><strong>' . $this->language->get('text_eci') . ':</strong> (' . $eci . ') ' . $this->language->get('text_3d_s' . (int)$eci_ref);
+ $message .= '<br /><strong>' . $this->language->get('text_timestamp') . ':</strong> ' . (string)strftime("%Y%m%d%H%M%S");
+ $message .= '<br /><strong>' . $this->language->get('text_order_ref') . ':</strong> ' . (string)$md['order_ref'];
+
+ if ($this->config->get('payment_globalpay_remote_card_data_status') == 1) {
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_type') . ':</strong> ' . (string)$md['cc_type'];
+ $message .= '<br /><strong>' . $this->language->get('text_last_digits') . ':</strong> ' . (string)substr($md['cc_number'], -4);
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_expire_date') . ':</strong> ' . (string)$md['cc_expire'];
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_name') . ':</strong> ' . (string)$md['cc_name'];
+ }
+
+ $this->model_extension_payment_globalpay_remote->addHistory($md['order_id'], $this->config->get('payment_globalpay_remote_order_status_decline_id'), $message);
+
+ $this->session->data['error'] = $this->language->get('error_3d_unsuccessful');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ die();
+ }
+ }
+
+ $capture_result = $this->model_extension_payment_globalpay_remote->capturePayment(
+ $md['account'],
+ $md['amount'],
+ $md['currency'],
+ $md['order_id'],
+ $md['order_ref'],
+ $md['cc_number'],
+ $md['cc_expire'],
+ $md['cc_name'],
+ $md['cc_type'],
+ $md['cc_cvv2'],
+ $md['cc_issue'],
+ $eci_ref,
+ $eci,
+ $cavv,
+ $xid
+ );
+
+ $this->model_extension_payment_globalpay_remote->logger('Capture result:\r\n' . print_r($capture_result, 1));
+
+ if ($capture_result->result != '00') {
+ $this->session->data['error'] = (string)$capture_result->message . ' (' . (int)$capture_result->result . ')';
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->response->redirect($this->url->link('checkout/success'));
+ }
+ } else {
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/klarna_account.php b/public/catalog/controller/extension/payment/klarna_account.php
new file mode 100644
index 0000000..f6400ac
--- /dev/null
+++ b/public/catalog/controller/extension/payment/klarna_account.php
@@ -0,0 +1,687 @@
+<?php
+class ControllerExtensionPaymentKlarnaAccount extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $this->load->language('extension/payment/klarna_account');
+
+ $data['days'] = array();
+
+ for ($i = 1; $i <= 31; $i++) {
+ $data['days'][] = array(
+ 'text' => sprintf('%02d', $i),
+ 'value' => $i
+ );
+ }
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => sprintf('%02d', $i),
+ 'value' => $i
+ );
+ }
+
+ $data['years'] = array();
+
+ for ($i = date('Y'); $i >= 1900; $i--) {
+ $data['years'][] = array(
+ 'text' => $i,
+ 'value' => $i
+ );
+ }
+
+ // Store Taxes to send to Klarna
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ $klarna_tax = array();
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ $taxes = array();
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+
+ $amount = 0;
+
+ foreach ($taxes as $tax_id => $value) {
+ $amount += $value;
+ }
+
+ $klarna_tax[$result['code']] = $amount;
+ }
+ }
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+
+ if (isset($klarna_tax[$value['code']])) {
+ if ($klarna_tax[$value['code']]) {
+ $totals[$key]['tax_rate'] = abs($klarna_tax[$value['code']] / $value['value'] * 100);
+ } else {
+ $totals[$key]['tax_rate'] = 0;
+ }
+ } else {
+ $totals[$key]['tax_rate'] = '0';
+ }
+ }
+
+ $this->session->data['klarna'][$this->session->data['order_id']] = $totals;
+
+ // Order must have identical shipping and billing address or have no shipping address at all
+ if ($this->cart->hasShipping() && !($order_info['payment_firstname'] == $order_info['shipping_firstname'] && $order_info['payment_lastname'] == $order_info['shipping_lastname'] && $order_info['payment_address_1'] == $order_info['shipping_address_1'] && $order_info['payment_address_2'] == $order_info['shipping_address_2'] && $order_info['payment_postcode'] == $order_info['shipping_postcode'] && $order_info['payment_city'] == $order_info['shipping_city'] && $order_info['payment_zone_id'] == $order_info['shipping_zone_id'] && $order_info['payment_zone_code'] == $order_info['shipping_zone_code'] && $order_info['payment_country_id'] == $order_info['shipping_country_id'] && $order_info['payment_country'] == $order_info['shipping_country'] && $order_info['payment_iso_code_3'] == $order_info['shipping_iso_code_3'])) {
+ $data['error_warning'] = $this->language->get('error_address_match');
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ $klarna_account = $this->config->get('payment_klarna_account');
+
+ $data['merchant'] = $klarna_account[$order_info['payment_iso_code_3']]['merchant'];
+ $data['phone_number'] = $order_info['telephone'];
+
+ $country_to_currency = array(
+ 'NOR' => 'NOK',
+ 'SWE' => 'SEK',
+ 'FIN' => 'EUR',
+ 'DNK' => 'DKK',
+ 'DEU' => 'EUR',
+ 'NLD' => 'EUR'
+ );
+
+ if ($order_info['payment_iso_code_3'] == 'DEU' || $order_info['payment_iso_code_3'] == 'NLD') {
+ $address = $this->splitAddress($order_info['payment_address_1']);
+
+ $data['street'] = $address[0];
+ $data['street_number'] = $address[1];
+ $data['street_extension'] = $address[2];
+
+ if ($order_info['payment_iso_code_3'] == 'DEU') {
+ $data['street_number'] = trim($address[1] . ' ' . $address[2]);
+ }
+ } else {
+ $data['street'] = '';
+ $data['street_number'] = '';
+ $data['street_extension'] = '';
+ }
+
+ $data['company'] = $order_info['payment_company'];
+ $data['iso_code_2'] = $order_info['payment_iso_code_2'];
+ $data['iso_code_3'] = $order_info['payment_iso_code_3'];
+
+ $payment_option = array();
+
+ $total = $this->currency->format($order_info['total'], $country_to_currency[$order_info['payment_iso_code_3']], '', false);
+
+ $pclasses = $this->config->get('klarna_account_pclasses');
+
+ if (isset($pclasses[$order_info['payment_iso_code_3']])) {
+ $pclasses = $pclasses[$order_info['payment_iso_code_3']];
+ } else {
+ $pclasses = array();
+ }
+
+ foreach ($pclasses as $pclass) {
+ // 0 - Campaign
+ // 1 - Account
+ // 2 - Special
+ // 3 - Fixed
+ if (!in_array($pclass['type'], array(0, 1, 3))) {
+ continue;
+ }
+
+ if ($pclass['type'] == 2) {
+ $monthly_cost = -1;
+ } else {
+ if ($total < $pclass['minamount']) {
+ continue;
+ }
+
+ if ($pclass['type'] == 3) {
+ continue;
+ } else {
+ $sum = $total;
+
+ $lowest_payment = $this->getLowestPaymentAccount($order_info['payment_iso_code_3']);
+ $monthly_cost = 0;
+
+ $monthly_fee = $pclass['invoicefee'];
+ $start_fee = $pclass['startfee'];
+
+ $sum += $start_fee;
+
+ $base = ($pclass['type'] == 1);
+
+ $minimum_payment = ($pclass['type'] === 1) ? $this->getLowestPaymentAccount($order_info['payment_iso_code_3']) : 0;
+
+ if ($pclass['months'] == 0) {
+ $payment = $sum;
+ } elseif ($pclass['interestrate'] == 0) {
+ $payment = $sum / $pclass['months'];
+ } else {
+ $interest = $pclass['interestrate'] / (100.0 * 12);
+ $payment = $sum * $interest / (1 - pow((1 + $interest), -$pclass['months']));
+ }
+
+ $payment += $monthly_fee;
+
+ $balance = $sum;
+ $pay_data = array();
+
+ $months = $pclass['months'];
+
+ while (($months != 0) && ($balance > 0.01)) {
+ $interest = $balance * $pclass['interestrate'] / (100.0 * 12);
+ $new_balance = $balance + $interest + $monthly_fee;
+
+ if ($minimum_payment >= $new_balance || $payment >= $new_balance) {
+ $pay_data[] = $new_balance;
+ break;
+ }
+
+ $new_payment = max($payment, $minimum_payment);
+
+ if ($base) {
+ $new_payment = max($new_payment, $balance / 24.0 + $monthly_fee + $interest);
+ }
+
+ $balance = $new_balance - $new_payment;
+
+ $pay_data[] = $new_payment;
+
+ $months -= 1;
+ }
+
+ $monthly_cost = round(isset($pay_data[0]) ? ($pay_data[0]) : 0, 2);
+
+ if ($monthly_cost < 0.01) {
+ continue;
+ }
+
+ if ($pclass['type'] == 1 && $monthly_cost < $lowest_payment) {
+ $monthly_cost = $lowest_payment;
+ }
+
+ if ($pclass['type'] == 0 && $monthly_cost < $lowest_payment) {
+ continue;
+ }
+ }
+ }
+
+ $payment_option[$pclass['id']]['pclass_id'] = $pclass['id'];
+ $payment_option[$pclass['id']]['title'] = $pclass['description'];
+ $payment_option[$pclass['id']]['months'] = $pclass['months'];
+ $payment_option[$pclass['id']]['monthly_cost'] = $monthly_cost;
+ }
+
+ $sort_order = array();
+
+ foreach ($payment_option as $key => $value) {
+ $sort_order[$key] = $value['pclass_id'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $payment_option);
+
+ $data['payment_options'] = array();
+
+ foreach ($payment_option as $payment_option) {
+ $data['payment_options'][] = array(
+ 'code' => $payment_option['pclass_id'],
+ 'title' => sprintf($this->language->get('text_monthly_payment'), $payment_option['title'], $this->currency->format($this->currency->convert($payment_option['monthly_cost'], $country_to_currency[$order_info['payment_iso_code_3']], $this->session->data['currency']), $this->session->data['currency'], 1))
+ );
+ }
+
+ return $this->load->view('extension/payment/klarna_account', $data);
+ }
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/klarna_account');
+
+ $json = array();
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ // Order must have identical shipping and billing address or have no shipping address at all
+ if ($order_info) {
+ if ($order_info['payment_iso_code_3'] == 'DEU' && empty($this->request->post['deu_terms'])) {
+ $json['error'] = $this->language->get('error_deu_terms');
+ }
+
+ if ($this->cart->hasShipping() && !($order_info['payment_firstname'] == $order_info['shipping_firstname'] && $order_info['payment_lastname'] == $order_info['shipping_lastname'] && $order_info['payment_address_1'] == $order_info['shipping_address_1'] && $order_info['payment_address_2'] == $order_info['shipping_address_2'] && $order_info['payment_postcode'] == $order_info['shipping_postcode'] && $order_info['payment_city'] == $order_info['shipping_city'] && $order_info['payment_zone_id'] == $order_info['shipping_zone_id'] && $order_info['payment_zone_code'] == $order_info['shipping_zone_code'] && $order_info['payment_country_id'] == $order_info['shipping_country_id'] && $order_info['payment_country'] == $order_info['shipping_country'] && $order_info['payment_iso_code_3'] == $order_info['shipping_iso_code_3'])) {
+ $json['error'] = $this->language->get('error_address_match');
+ }
+
+ if (!$json) {
+ $klarna_account = $this->config->get('payment_klarna_account');
+
+ if ($klarna_account[$order_info['payment_iso_code_3']]['server'] == 'live') {
+ $url = 'https://payment.klarna.com/';
+ } else {
+ $url = 'https://payment.testdrive.klarna.com/';
+ }
+
+ $country_to_currency = array(
+ 'NOR' => 'NOK',
+ 'SWE' => 'SEK',
+ 'FIN' => 'EUR',
+ 'DNK' => 'DKK',
+ 'DEU' => 'EUR',
+ 'NLD' => 'EUR'
+ );
+
+ switch ($order_info['payment_iso_code_3']) {
+ // Sweden
+ case 'SWE':
+ $country = 209;
+ $language = 138;
+ $encoding = 2;
+ $currency = 0;
+ break;
+ // Finland
+ case 'FIN':
+ $country = 73;
+ $language = 37;
+ $encoding = 4;
+ $currency = 2;
+ break;
+ // Denmark
+ case 'DNK':
+ $country = 59;
+ $language = 27;
+ $encoding = 5;
+ $currency = 3;
+ break;
+ // Norway
+ case 'NOR':
+ $country = 164;
+ $language = 97;
+ $encoding = 3;
+ $currency = 1;
+ break;
+ // Germany
+ case 'DEU':
+ $country = 81;
+ $language = 28;
+ $encoding = 6;
+ $currency = 2;
+ break;
+ // Netherlands
+ case 'NLD':
+ $country = 154;
+ $language = 101;
+ $encoding = 7;
+ $currency = 2;
+ break;
+ }
+
+ if (isset($this->request->post['street'])) {
+ $street = $this->request->post['street'];
+ } else {
+ $street = $order_info['payment_address_1'];
+ }
+
+ if (isset($this->request->post['house_no'])) {
+ $house_no = $this->request->post['house_no'];
+ } else {
+ $house_no = '';
+ }
+
+ if (isset($this->request->post['house_ext'])) {
+ $house_ext = $this->request->post['house_ext'];
+ } else {
+ $house_ext = '';
+ }
+
+ $address = array(
+ 'email' => $order_info['email'],
+ 'telno' => $this->request->post['phone_no'],
+ 'cellno' => '',
+ 'fname' => $order_info['payment_firstname'],
+ 'lname' => $order_info['payment_lastname'],
+ 'company' => $order_info['payment_company'],
+ 'careof' => '',
+ 'street' => $street,
+ 'house_number' => $house_no,
+ 'house_extension' => $house_ext,
+ 'zip' => $order_info['payment_postcode'],
+ 'city' => $order_info['payment_city'],
+ 'country' => $country
+ );
+
+ $product_query = $this->db->query("SELECT `name`, `model`, `price`, `quantity`, `tax` / `price` * 100 AS 'tax_rate' FROM `" . DB_PREFIX . "order_product` WHERE `order_id` = " . (int)$order_info['order_id'] . " UNION ALL SELECT '', `code`, `amount`, '1', 0.00 FROM `" . DB_PREFIX . "order_voucher` WHERE `order_id` = " . (int)$order_info['order_id']);
+
+ foreach ($product_query->rows as $product) {
+ $goods_list[] = array(
+ 'qty' => (int)$product['quantity'],
+ 'goods' => array(
+ 'artno' => $product['model'],
+ 'title' => $product['name'],
+ 'price' => (int)str_replace('.', '', $this->currency->format($product['price'], $country_to_currency[$order_info['payment_iso_code_3']], '', false)),
+ 'vat' => (float)$product['tax_rate'],
+ 'discount' => 0.0,
+ 'flags' => 0
+ )
+ );
+ }
+
+ if (isset($this->session->data['klarna'][$this->session->data['order_id']])) {
+ $totals = $this->session->data['klarna'][$this->session->data['order_id']];
+ } else {
+ $totals = array();
+ }
+
+ foreach ($totals as $total) {
+ if ($total['code'] != 'sub_total' && $total['code'] != 'tax' && $total['code'] != 'total') {
+ $goods_list[] = array(
+ 'qty' => 1,
+ 'goods' => array(
+ 'artno' => '',
+ 'title' => $total['title'],
+ 'price' => (int)str_replace('.', '', $this->currency->format($total['value'], $country_to_currency[$order_info['payment_iso_code_3']], '', false)),
+ 'vat' => (float)$total['tax_rate'],
+ 'discount' => 0.0,
+ 'flags' => 0
+ )
+ );
+ }
+ }
+
+ $digest = '';
+
+ foreach ($goods_list as $goods) {
+ $digest .= utf8_decode(htmlspecialchars(html_entity_decode($goods['goods']['title'], ENT_COMPAT, 'UTF-8'))) . ':';
+ }
+
+ $digest = base64_encode(pack('H*', hash('sha256', $digest . $klarna_account[$order_info['payment_iso_code_3']]['secret'])));
+
+ if (isset($this->request->post['pno'])) {
+ $pno = $this->request->post['pno'];
+ } else {
+ $pno = sprintf('%02d', (int)$this->request->post['pno_day']) . sprintf('%02d', (int)$this->request->post['pno_month']) . (int)$this->request->post['pno_year'];
+ }
+
+ if (isset($this->request->post['code'])) {
+ $pclass = (int)$this->request->post['code'];
+ } else {
+ $pclass = '';
+ }
+
+ if (isset($this->request->post['gender']) && ($order_info['payment_iso_code_3'] == 'DEU' || $order_info['payment_iso_code_3'] == 'NLD')) {
+ $gender = (int)$this->request->post['gender'];
+ } else {
+ $gender = '';
+ }
+
+ $transaction = array(
+ '4.1',
+ 'API:OPENCART:' . VERSION,
+ $pno,
+ $gender,
+ '',
+ '',
+ (string)$order_info['order_id'],
+ '',
+ $address,
+ $address,
+ $order_info['ip'],
+ 0,
+ $currency,
+ $country,
+ $language,
+ (int)$klarna_account[$order_info['payment_iso_code_3']]['merchant'],
+ $digest,
+ $encoding,
+ $pclass,
+ $goods_list,
+ $order_info['comment'],
+ array('delay_adjust' => 1),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ );
+
+ $xml = '<methodCall>';
+ $xml .= ' <methodName>add_invoice</methodName>';
+ $xml .= ' <params>';
+
+ foreach ($transaction as $parameter) {
+ $xml .= ' <param><value>' . $this->constructXmlrpc($parameter) . '</value></param>';
+ }
+
+ $xml .= ' </params>';
+ $xml .= '</methodCall>';
+
+ $header = array();
+
+ $header[] = 'Content-Type: text/xml';
+ $header[] = 'Content-Length: ' . strlen($xml);
+
+ $curl = curl_init();
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
+
+ $response = curl_exec($curl);
+
+ if (curl_errno($curl)) {
+ $log = new Log('klarna_account.log');
+ $log->write('HTTP Error for order #' . $order_info['order_id'] . '. Code: ' . curl_errno($curl) . ' message: ' . curl_error($curl));
+
+ $json['error'] = $this->language->get('error_network');
+ } else {
+ preg_match('/<member><name>faultString<\/name><value><string>(.+)<\/string><\/value><\/member>/', $response, $match);
+
+ if (isset($match[1])) {
+ preg_match('/<member><name>faultCode<\/name><value><int>([0-9]+)<\/int><\/value><\/member>/', $response, $match2);
+
+ $log = new Log('klarna_account.log');
+ $log->write('Failed to create an invoice for order #' . $order_info['order_id'] . '. Message: ' . utf8_encode($match[1]) . ' Code: ' . $match2[1]);
+
+ $json['error'] = utf8_encode($match[1]);
+ } else {
+ $xml = new DOMDocument();
+ $xml->loadXML($response);
+
+ $invoice_number = $xml->getElementsByTagName('string')->item(0)->nodeValue;
+ $klarna_order_status = $xml->getElementsByTagName('int')->item(0)->nodeValue;
+
+ if ($klarna_order_status == '1') {
+ $order_status = $klarna_account[$order_info['payment_iso_code_3']]['accepted_status_id'];
+ } elseif ($klarna_order_status == '2') {
+ $order_status = $klarna_account[$order_info['payment_iso_code_3']]['pending_status_id'];
+ } else {
+ $order_status = $this->config->get('config_order_status_id');
+ }
+
+ $comment = sprintf($this->language->get('text_comment'), $invoice_number, $this->config->get('config_currency'), $country_to_currency[$order_info['payment_iso_code_3']], $this->currency->getValue($country_to_currency[$order_info['payment_iso_code_3']]));
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $order_status, $comment, 1);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ }
+ }
+
+ curl_close($curl);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ private function constructXmlrpc($data) {
+ $type = gettype($data);
+
+ switch ($type) {
+ case 'boolean':
+ if ($data == true) {
+ $value = 1;
+ } else {
+ $value = false;
+ }
+
+ $xml = '<boolean>' . $value . '</boolean>';
+ break;
+ case 'integer':
+ $xml = '<int>' . (int)$data . '</int>';
+ break;
+ case 'double':
+ $xml = '<double>' . (float)$data . '</double>';
+ break;
+ case 'string':
+ $xml = '<string>' . htmlspecialchars($data) . '</string>';
+ break;
+ case 'array':
+ if ($data === array_values($data)) {
+ $xml = '<array><data>';
+
+ foreach ($data as $value) {
+ $xml .= '<value>' . $this->constructXmlrpc($value) . '</value>';
+ }
+
+ $xml .= '</data></array>';
+ } else {
+ $xml = '<struct>';
+
+ foreach ($data as $key => $value) {
+ $xml .= '<member>';
+ $xml .= ' <name>' . htmlspecialchars($key) . '</name>';
+ $xml .= ' <value>' . $this->constructXmlrpc($value) . '</value>';
+ $xml .= '</member>';
+ }
+
+ $xml .= '</struct>';
+ }
+ break;
+ default:
+ $xml = '<nil/>';
+ break;
+ }
+
+ return $xml;
+ }
+
+ private function getLowestPaymentAccount($country) {
+ switch ($country) {
+ case 'SWE':
+ $amount = 50.0;
+ break;
+ case 'NOR':
+ $amount = 95.0;
+ break;
+ case 'FIN':
+ $amount = 8.95;
+ break;
+ case 'DNK':
+ $amount = 89.0;
+ break;
+ case 'DEU':
+ case 'NLD':
+ $amount = 5.00;
+ break;
+
+ default:
+ $log = new Log('klarna.log');
+ $log->write('Unknown country ' . $country);
+
+ $amount = null;
+ break;
+ }
+
+ return $amount;
+ }
+
+ private function splitAddress($address) {
+ $numbers = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
+
+ $characters = array('-', '/', ' ', '#', '.', 'a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A',
+ 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z');
+
+ $specialchars = array('-', '/', ' ', '#', '.');
+
+ $num_pos = $this->strposArr($address, $numbers, 2);
+
+ $street_name = substr($address, 0, $num_pos);
+
+ $street_name = trim($street_name);
+
+ $number_part = substr($address, $num_pos);
+
+ $number_part = trim($number_part);
+
+ $ext_pos = $this->strposArr($number_part, $characters, 0);
+
+ if ($ext_pos != '') {
+ $house_number = substr($number_part, 0, $ext_pos);
+
+ $house_extension = substr($number_part, $ext_pos);
+
+ $house_extension = str_replace($specialchars, '', $house_extension);
+ } else {
+ $house_number = $number_part;
+ $house_extension = '';
+ }
+
+ return array($street_name, $house_number, $house_extension);
+ }
+
+ private function strposArr($haystack, $needle, $where) {
+ $defpos = 10000;
+
+ if (!is_array($needle)) {
+ $needle = array($needle);
+ }
+
+ foreach ($needle as $what) {
+ if (($pos = strpos($haystack, $what, $where)) !== false) {
+ if ($pos < $defpos) {
+ $defpos = $pos;
+ }
+ }
+ }
+
+ return $defpos;
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/klarna_checkout.php b/public/catalog/controller/extension/payment/klarna_checkout.php
new file mode 100644
index 0000000..675ea81
--- /dev/null
+++ b/public/catalog/controller/extension/payment/klarna_checkout.php
@@ -0,0 +1,1963 @@
+<?php
+class ControllerExtensionPaymentKlarnaCheckout extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout', $data));
+ }
+
+ public function main() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $redirect = false;
+ $html_snippet = '';
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+ }
+
+ // Validate cart has recurring products
+ if ($this->cart->hasRecurringProducts()) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ if ($this->config->get('klarna_checkout_total') > 0 && $this->config->get('klarna_checkout_total') > $total) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if ($this->model_extension_payment_klarna_checkout->checkForPaymentTaxes($products)) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ $text_title = $this->language->get('text_title');
+
+ unset($this->session->data['success']);
+
+ $this->setPayment();
+ $this->setShipping();
+
+ $this->session->data['payment_method'] = array(
+ 'code' => 'klarna_checkout',
+ 'title' => $text_title,
+ 'terms' => $this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true),
+ 'sort_order' => '1'
+ );
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote['code'] == $this->session->data['shipping_method']['code']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ //Klarna Connector
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
+
+ if (!$klarna_account || !$connector) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if (!$redirect) {
+ // Get currency code and currency value to use to calculate taxes
+
+ // Build order_lines
+ $create_order = true;
+ $klarna_checkout = false;
+
+ $this->createOrder();
+
+ list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
+
+ if (isset($this->session->data['klarna_checkout_currency']) && $this->session->data['klarna_checkout_currency'] != $this->session->data['currency']) {
+ $this->model_extension_payment_klarna_checkout->log('Currency changed, unsetting kc order id');
+ unset($this->session->data['klarna_checkout_order_id']);
+ unset($this->session->data['klarna_checkout_data']);
+ }
+
+ $this->session->data['klarna_checkout_currency'] = $this->session->data['currency'];
+
+ // Fetch or create order
+ if (isset($this->session->data['klarna_checkout_order_id'])) {
+ $retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->session->data['klarna_checkout_order_id']);
+
+ if ($retrieve) {
+ //If address has changed, unset klarna_checkout_order_id and create new order
+ $address_change = false;
+
+ if (isset($this->session->data['klarna_checkout_data']) && $this->session->data['klarna_checkout_data']) {
+ if (isset($this->session->data['klarna_checkout_data']['zone_code'])) {
+ $kc_region = $this->session->data['klarna_checkout_data']['zone_code'];
+ } else {
+ $kc_region = '';
+ }
+
+ if (isset($this->session->data['klarna_checkout_data']['iso_code_2'])) {
+ $kc_country = $this->session->data['klarna_checkout_data']['iso_code_2'];
+ } else {
+ $kc_country = '';
+ }
+
+ if (isset($this->session->data['shipping_address']['zone_code'])) {
+ $oc_region = $this->session->data['shipping_address']['zone_code'];
+ } else {
+ $oc_region = '';
+ }
+
+ if (isset($this->session->data['shipping_address']['iso_code_2'])) {
+ $oc_country = $this->session->data['shipping_address']['iso_code_2'];
+ } else {
+ $oc_country = '';
+ }
+
+ $kc_address = array(
+ 'region' => $kc_region,
+ 'country' => $kc_country,
+ );
+
+ $oc_address = array(
+ 'region' => $oc_region,
+ 'country' => $oc_country,
+ );
+
+ //If address has changed, dont use retrieved order, create new one instead
+ if (array_diff(array_map('strtolower', $kc_address), array_map('strtolower', $oc_address))) {
+ $address_change = true;
+ }
+ }
+
+ if (!$address_change) {
+ $this->model_extension_payment_klarna_checkout->log('Order Updated');
+ $this->model_extension_payment_klarna_checkout->log($klarna_order_data);
+
+ $create_order = false;
+
+ $update = $this->model_extension_payment_klarna_checkout->orderUpdate($connector, $this->session->data['klarna_checkout_order_id'], $klarna_order_data);
+
+ if ($update) {
+ $klarna_checkout = $update->fetch();
+
+ $this->model_extension_payment_klarna_checkout->updateOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
+ }
+ }
+ }
+ }
+
+ if ($create_order) {
+ $this->model_extension_payment_klarna_checkout->log('Order Created');
+ $this->model_extension_payment_klarna_checkout->log($klarna_order_data);
+
+ unset($this->session->data['klarna_checkout_data']);
+
+ $create = $this->model_extension_payment_klarna_checkout->orderCreate($connector, $klarna_order_data);
+
+ if ($create) {
+ $klarna_checkout = $create->fetch();
+
+ $this->model_extension_payment_klarna_checkout->addOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
+ }
+ }
+
+ if ($klarna_checkout) {
+ $this->session->data['klarna_checkout_order_id'] = $klarna_checkout['order_id'];
+
+ $html_snippet = $klarna_checkout['html_snippet'];
+ }
+ }
+
+ if (isset($this->request->post['response']) && $this->request->post['response'] == 'template') {
+ $data['redirect'] = $redirect;
+
+ $data['klarna_checkout'] = $html_snippet;
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_main', $data));
+ } elseif (isset($this->request->post['response']) && $this->request->post['response'] == 'json') {
+ $json['redirect'] = $redirect;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+ }
+
+ public function sidebar() {
+ $this->load->language('checkout/checkout');
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $this->setPayment();
+ $this->setShipping();
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote['code'] == $this->session->data['shipping_method']['code']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ $data['shipping_required'] = $this->cart->hasShipping();
+
+ if (isset($this->session->data['shipping_methods'])) {
+ $data['shipping_methods'] = $this->session->data['shipping_methods'];
+ } else {
+ unset($data['shipping_method']);
+
+ $data['shipping_methods'] = array();
+ }
+
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $data['code'] = $this->session->data['shipping_method']['code'];
+ } else {
+ $data['code'] = '';
+ }
+
+ $this->load->model('tool/image');
+ $this->load->model('tool/upload');
+
+ $data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['image']) {
+ $image = $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_height'));
+ } else {
+ $image = '';
+ }
+
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ if ($option['type'] != 'file') {
+ $value = $option['value'];
+ } else {
+ $upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
+
+ if ($upload_info) {
+ $value = $upload_info['name'];
+ } else {
+ $value = '';
+ }
+ }
+
+ $option_data[] = array(
+ 'name' => $option['name'],
+ 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value),
+ 'type' => $option['type']
+ );
+ }
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $total = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')) * $product['quantity'], $this->session->data['currency']);
+ } else {
+ $total = false;
+ }
+
+ $data['products'][] = array(
+ 'cart_id' => $product['cart_id'],
+ 'thumb' => $image,
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'recurring' => ($product['recurring'] ? $product['recurring']['name'] : ''),
+ 'quantity' => $product['quantity'],
+ 'price' => $price,
+ 'total' => $total,
+ 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id'])
+ );
+ }
+
+ // Gift Voucher
+ $data['vouchers'] = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $key => $voucher) {
+ $data['vouchers'][] = array(
+ 'key' => $key,
+ 'description' => $voucher['description'],
+ 'amount' => $this->currency->format($voucher['amount'], $this->session->data['currency'])
+ );
+ }
+ }
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get($result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $data['totals'] = array();
+
+ foreach ($totals as $total) {
+ $data['totals'][] = array(
+ 'title' => $total['title'],
+ 'text' => $this->currency->format($total['value'], $this->session->data['currency'])
+ );
+ }
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_sidebar', $data));
+ }
+
+ public function shippingAddress() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/zone');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $json = array();
+
+ unset($this->session->data['shipping_address']);
+ unset($this->session->data['shipping_methods']);
+
+ if (($this->request->server['REQUEST_METHOD'] == 'POST') && isset($this->request->post['country'])) {
+ $country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode3($this->request->post['country']);
+
+ if ($country_info) {
+ // Set default zone for shipping calculations. Get overwritten by correct data when order is confirmed
+ $zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
+
+ $zone = array();
+ if (isset($this->request->post['region']) && !empty($this->request->post['region'])) {
+ $zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($this->request->post['region'], $country_info['country_id']);
+ }
+
+ if ($zone || $zones) {
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => utf8_substr($this->request->post['given_name'], 0, 32),
+ 'lastname' => utf8_substr($this->request->post['family_name'], 0, 32),
+ 'company' => null,
+ 'address_1' => utf8_substr($this->request->post['street_address'], 0, 128),
+ 'address_2' => utf8_substr($this->request->post['street_address'], 129, 256),
+ 'postcode' => utf8_substr($this->request->post['postal_code'], 0, 10),
+ 'city' => utf8_substr($this->request->post['city'], 0, 128),
+ 'zone_id' => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
+ 'zone' => ($zone ? $zone['name'] : $zones[0]['name']),
+ 'zone_code' => ($zone ? $zone['code'] : $zones[0]['code']),
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => $country_info['address_format'],
+ 'custom_field' => array(),
+ );
+
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Couldnt find country: ' . $this->request->post['country']);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function cartTotal() {
+ $this->load->language('checkout/cart');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ // Totals
+ $this->load->model('setting/extension');
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get($result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $total = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total, $this->session->data['currency']));
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($total));
+ }
+
+ public function addressUpdate() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('account/customer');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/zone');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $process = true;
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ $json = array();
+
+ $http_response_code = 400;
+
+ // Check to see if request data is complete
+ if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address)) {
+ $this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $process = false;
+ }
+
+ // Get Klarna order info from db
+ if ($process) {
+ $order_id = null;
+
+ foreach ($request->order_lines as $order_line) {
+ if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
+ $order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
+ break;
+ }
+ }
+
+ if ($order_id) {
+ // Get klarna order data from db
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
+
+ if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
+ $this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
+ $process = false;
+ }
+ } else {
+ $process = false;
+ }
+ }
+
+ if ($process) {
+ $klarna_checkout_order_data = json_decode($this->encryption->decrypt($this->config->get('config_encryption'), $klarna_checkout_order['data']), true);
+
+ // Check credentials in request with ones stored in db
+ $valid_request = false;
+ foreach ($this->config->get('klarna_checkout_account') as $account) {
+ if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
+ $valid_request = true;
+ break;
+ }
+ }
+
+ if (!$valid_request) {
+ $this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
+ $process = false;
+ }
+ }
+
+ // Request is valid, we can spoof/simulate the customer to calculate shipping
+ if ($process) {
+ session_destroy();
+ session_id($klarna_checkout_order_data['session_id']);
+ session_start();
+ $this->session->start('default', $klarna_checkout_order_data['session_key']);
+
+ if ($klarna_checkout_order_data['customer_id']) {
+ $customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
+
+ if ($customer_info) {
+ $this->customer->login($customer_info['email'], '', true);
+ }
+ }
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if (!$order_info) {
+ $this->model_extension_payment_klarna_checkout->log('No order found using order_id: ' . $order_id . '. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $process = false;
+ }
+
+ // Set more session data from the order
+ $this->session->data['currency'] = $order_info['currency_code'];
+ $this->session->data['language'] = $order_info['language_code'];
+
+ $country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
+
+ if (!$country_info) {
+ $this->model_extension_payment_klarna_checkout->log('No country found using: ' . $request->shipping_address->country . '. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ }
+
+ if ($order_info && $country_info) {
+ $zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
+
+ $zone = array();
+ if (isset($request->shipping_address->region) && !empty($request->shipping_address->region)) {
+ $zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $country_info['country_id']);
+ }
+
+ if ($zone || $zones) {
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
+ 'zone' => ($zone ? $zone['name'] : $zones[0]['name']),
+ 'zone_code' => ($zone ? $zone['code'] : $zones[0]['code']),
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+
+ $this->session->data['klarna_checkout_data'] = array(
+ 'email' => $request->billing_address->email,
+ 'firstname' => $request->billing_address->given_name,
+ 'lastname' => $request->billing_address->family_name,
+ 'telephone' => $request->billing_address->phone,
+ 'iso_code_2' => $this->session->data['shipping_address']['iso_code_2'],
+ 'zone_code' => $this->session->data['shipping_address']['zone_code']
+ );
+
+ // Unset $tax_rates
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($country_info['country_id'], ($zone ? $zone['zone_id'] : $zones[0]['zone_id']));
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ //Check if customer is US. If so, send taxes differently
+ if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
+ $include_taxes = false;
+ } else {
+ $include_taxes = true;
+ }
+
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $method_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $shipping_methods = $method_data;
+
+ if ($shipping_methods) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
+
+ if ($klarna_account && $connector) {
+ list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
+
+ if ($this->cart->hasShipping()) {
+ $shipping_method = array();
+
+ if (isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
+ foreach ($shipping_methods as $individual_shipping_method) {
+ if ($individual_shipping_method['quote']) {
+ foreach ($individual_shipping_method['quote'] as $quote) {
+ if (($this->session->data['shipping_method']['code'] == $quote['code']) && ($this->session->data['shipping_method']['title'] == $quote['title']) && ($this->session->data['shipping_method']['cost'] == $quote['cost']) && ($this->session->data['shipping_method']['tax_class_id'] == $quote['tax_class_id'])) {
+ $shipping_method = $quote;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ // If the current shipping method isn't in the available shipping methods, assign default
+ if (!$shipping_method) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($shipping_methods);
+ }
+
+ $total_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id']), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], false), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
+ if ($order_line['type'] == 'shipping_fee') {
+ unset($klarna_order_data['order_lines'][$key]);
+ break;
+ }
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'shipping_fee',
+ 'name' => $this->session->data['shipping_method']['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ //If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
+ if (!$include_taxes) {
+ foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
+ if ($order_line['type'] == 'sales_tax') {
+ unset($klarna_order_data['order_lines'][$key]);
+ break;
+ }
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'sales_tax',
+ 'name' => $this->language->get('text_sales_tax'),
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ $http_response_code = 200;
+
+ $json = array(
+ 'order_amount' => round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'order_tax_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'order_lines' => array_values($klarna_order_data['order_lines'])
+ );
+ }
+ }
+ }
+ }
+ }
+
+ $this->model_extension_payment_klarna_checkout->log($http_response_code);
+ $this->model_extension_payment_klarna_checkout->log($json);
+
+ http_response_code($http_response_code);
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function notification() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ if (isset($request->order_id)) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($request->order_id);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if (!$klarna_account || !$connector) {
+ $this->model_extension_payment_klarna_checkout->log('Could not getConnector');
+ }
+
+ $retrieve = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $request->order_id);
+
+ $order_status_id = false;
+ if ($retrieve) {
+ switch ($request->event_type) {
+ case 'FRAUD_RISK_ACCEPTED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_accepted_id');
+ break;
+ case 'FRAUD_RISK_REJECTED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
+ break;
+ }
+ }
+
+ if ($order_status_id) {
+ $this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $request->order_id);
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('$request->order_id is not set');
+ }
+ }
+
+ public function validation() {
+ $this->load->model('account/customer');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $validate = true;
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ $json = array();
+
+ // Check to see if request data is complete
+ if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address) || !isset($request->billing_address) || empty($request->billing_address)) {
+ $this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $validate = false;
+ }
+
+ // Get Klarna order info from db
+ if ($validate) {
+ $order_id = null;
+
+ foreach ($request->order_lines as $order_line) {
+ if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
+ $order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
+ break;
+ }
+ }
+
+ if ($order_id) {
+ // Get klarna order data from db
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
+
+ if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
+ $this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
+ $validate = false;
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot get decrypted order_id');
+ $validate = false;
+ }
+ }
+
+ if ($validate) {
+ $klarna_checkout_order_data = json_decode($this->encryption->decrypt($klarna_checkout_order['data']), true);
+
+ // Check credentials in request with ones stored in db
+ $valid_request = false;
+ foreach ($this->config->get('klarna_checkout_account') as $account) {
+ if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
+ $valid_request = true;
+ break;
+ }
+ }
+
+ if (!$valid_request) {
+ $this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
+ $validate = false;
+ }
+ }
+
+ // Spoof/simulate the customer to calculate shipping
+ if ($validate) {
+ session_destroy();
+ session_id($klarna_checkout_order_data['session_id']);
+ session_start();
+ $this->session->start('default', $klarna_checkout_order_data['session_key']);
+
+ if ($klarna_checkout_order_data['customer_id']) {
+ $customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
+
+ if ($customer_info) {
+ $this->customer->login($customer_info['email'], '', true);
+ }
+ }
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->model_extension_payment_klarna_checkout->log('Cart has no products or cart has no stock');
+ $validate = false;
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $this->model_extension_payment_klarna_checkout->log('Cart doesnt meet minimum quantities');
+ $validate = false;
+ }
+ }
+
+ // Validate cart has recurring products
+ if ($this->cart->hasRecurringProducts()) {
+ $this->model_extension_payment_klarna_checkout->log('Cart has recurring products');
+ $validate = false;
+ }
+ }
+
+ // Check order total to see if session matches post data
+ if ($validate) {
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ // Unset $tax_rates and set them again using correct shipping data
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ // Check order_amount
+ if (round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_amount) {
+ $this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_amount does not match session order total. Klarna Request: ' . $request->order_amount . '. OpenCart: ' . round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100));
+ $this->model_extension_payment_klarna_checkout->log($order_info);
+ $this->model_extension_payment_klarna_checkout->log($this->cart->getTaxes());
+ $validate = false;
+ }
+
+ // Check order_tax_amount
+ if (round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_tax_amount) {
+ $this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_tax_amount does not match session tax total. Totals below:');
+ $this->model_extension_payment_klarna_checkout->log('Session taxes:');
+ $this->model_extension_payment_klarna_checkout->log(round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100));
+ $this->model_extension_payment_klarna_checkout->log('Request taxes:');
+ $this->model_extension_payment_klarna_checkout->log($request->order_tax_amount);
+ $validate = false;
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot find order using: ' . $order_id);
+ $validate = false;
+ }
+ }
+
+ // If validates, add customer's email (if guest checkout) and then send 200 response
+ if ($validate) {
+ if (!$this->customer->isLogged()) {
+ $this->model_extension_payment_klarna_checkout->updateOcOrderEmail($order_id, utf8_substr($request->shipping_address->email, 0, 96));
+ }
+
+ // Update OpenCart order with payment and shipping details
+ $payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->billing_address->country);
+ $shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
+
+ //If region is passed, try to update OpenCart order with correct region/zone
+ $payment_zone_info = array();
+ if ($payment_country_info && isset($request->billing_address->region)) {
+ $payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->billing_address->region, $payment_country_info['country_id']);
+ }
+
+ $shipping_zone_info = array();
+ if ($shipping_country_info && isset($request->shipping_address->region)) {
+ $shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $shipping_country_info['country_id']);
+ }
+
+ $order_data = array(
+ 'firstname' => utf8_substr($request->billing_address->given_name, 0, 32),
+ 'lastname' => utf8_substr($request->billing_address->family_name, 0, 32),
+ 'telephone' => utf8_substr($request->billing_address->phone, 0, 32),
+ 'payment_firstname' => utf8_substr($request->billing_address->given_name, 0, 32),
+ 'payment_lastname' => utf8_substr($request->billing_address->family_name, 0, 32),
+ 'payment_address_1' => utf8_substr($request->billing_address->street_address, 0, 128),
+ 'payment_address_2' => (isset($request->billing_address->street_address2) ? utf8_substr($request->billing_address->street_address2, 0, 128) : ''),
+ 'payment_city' => utf8_substr($request->billing_address->city, 0, 128),
+ 'payment_postcode' => utf8_substr($request->billing_address->postal_code, 0, 10),
+ 'payment_zone' => ($payment_zone_info ? $payment_zone_info['name'] : ''),
+ 'payment_zone_id' => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
+ 'payment_country' => ($payment_country_info ? $payment_country_info['name'] : ''),
+ 'payment_country_id' => ($payment_country_info ? $payment_country_info['country_id'] : ''),
+ 'payment_address_format' => ($payment_country_info ? $payment_country_info['address_format'] : ''),
+ 'shipping_firstname' => utf8_substr($request->shipping_address->given_name, 0, 32),
+ 'shipping_lastname' => utf8_substr($request->shipping_address->family_name, 0, 32),
+ 'shipping_address_1' => utf8_substr($request->shipping_address->street_address, 0, 128),
+ 'shipping_address_2' => (isset($request->shipping_address->street_address2) ? utf8_substr($request->shipping_address->street_address2, 0, 128) : ''),
+ 'shipping_city' => utf8_substr($request->shipping_address->city, 0, 128),
+ 'shipping_postcode' => utf8_substr($request->shipping_address->postal_code, 0, 10),
+ 'shipping_zone' => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
+ 'shipping_zone_id' => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
+ 'shipping_country' => ($shipping_country_info ? $shipping_country_info['name'] : ''),
+ 'shipping_country_id' => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
+ 'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
+ );
+
+ $this->model_extension_payment_klarna_checkout->updateOcOrder($order_id, $order_data);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+
+ http_response_code(200);
+ } else {
+ http_response_code(303);
+ $this->response->addHeader('Location: ' . $this->url->link('checkout/failure', '', true));
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function confirmation() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ if (isset($this->session->data['order_id'])) {
+ $this->cart->clear();
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+ unset($this->session->data['guest']);
+ unset($this->session->data['comment']);
+ unset($this->session->data['order_id']);
+ unset($this->session->data['coupon']);
+ unset($this->session->data['reward']);
+ unset($this->session->data['voucher']);
+ unset($this->session->data['vouchers']);
+ unset($this->session->data['totals']);
+
+ unset($this->session->data['klarna_checkout_order_id']);
+ unset($this->session->data['klarna_checkout_data']);
+ }
+
+ $this->document->setTitle($this->language->get('heading_title_success'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_basket'),
+ 'href' => $this->url->link('checkout/cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_checkout'),
+ 'href' => $this->url->link('checkout/checkout', '', true)
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_success'),
+ 'href' => $this->url->link('checkout/success')
+ );
+
+ $data['continue'] = $this->url->link('common/home');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ $klarna_checkout = false;
+ $html_snippet = '';
+
+ if (isset($this->request->get['klarna_order_id'])) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if (!$klarna_account || !$connector) {
+ $this->model_extension_payment_klarna_checkout->log('Could not getConnector');
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ $retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->request->get['klarna_order_id']);
+
+ if ($retrieve) {
+ $klarna_checkout = $retrieve->fetch();
+
+ if ($klarna_checkout && $klarna_checkout['html_snippet']) {
+ $html_snippet = $klarna_checkout['html_snippet'];
+ }
+ } else {
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $this->request->get['klarna_order_id']);
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('$this->request->get[\'klarna_order_id\'] is not set');
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ $data['klarna_checkout'] = $html_snippet;
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_success', $data));
+ }
+
+ public function push() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ if (isset($this->request->get['klarna_order_id'])) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if ($klarna_account && $connector) {
+ $order = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $this->request->get['klarna_order_id']);
+
+ $this->model_extension_payment_klarna_checkout->log('Order details from push:');
+ $this->model_extension_payment_klarna_checkout->log($order);
+
+ if ($order) {
+ if ($order->acknowledge()) {
+ // Update OpenCart order with payment and shipping details
+ $payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['billing_address']['country']);
+ $shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['shipping_address']['country']);
+
+ //If region is passed, try to update OpenCart order with correct region/zone
+ $payment_zone_info = array();
+ if ($payment_country_info && isset($order['billing_address']['region'])) {
+ $payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['billing_address']['region'], $payment_country_info['country_id']);
+ }
+
+ $shipping_zone_info = array();
+ if ($shipping_country_info && isset($order['shipping_address']['region'])) {
+ $shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['shipping_address']['region'], $shipping_country_info['country_id']);
+ }
+
+ $order_data = array(
+ 'firstname' => utf8_substr($order['billing_address']['given_name'], 0, 32),
+ 'lastname' => utf8_substr($order['billing_address']['family_name'], 0, 32),
+ 'telephone' => utf8_substr($order['billing_address']['phone'], 0, 32),
+ 'payment_firstname' => utf8_substr($order['billing_address']['given_name'], 0, 32),
+ 'payment_lastname' => utf8_substr($order['billing_address']['family_name'], 0, 32),
+ 'payment_address_1' => utf8_substr($order['billing_address']['street_address'], 0, 128),
+ 'payment_address_2' => (isset($order['billing_address']['street_address2']) ? utf8_substr($order['billing_address']['street_address2'], 0, 128) : ''),
+ 'payment_city' => utf8_substr($order['billing_address']['city'], 0, 128),
+ 'payment_postcode' => utf8_substr($order['billing_address']['postal_code'], 0, 10),
+ 'payment_zone' => ($payment_zone_info ? $payment_zone_info['name'] : ''),
+ 'payment_zone_id' => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
+ 'payment_country' => ($payment_country_info ? $payment_country_info['name'] : ''),
+ 'payment_country_id' => ($payment_country_info ? $payment_country_info['country_id'] : ''),
+ 'payment_address_format' => ($payment_country_info ? $payment_country_info['address_format'] : ''),
+ 'shipping_firstname' => utf8_substr($order['shipping_address']['given_name'], 0, 32),
+ 'shipping_lastname' => utf8_substr($order['shipping_address']['family_name'], 0, 32),
+ 'shipping_address_1' => utf8_substr($order['shipping_address']['street_address'], 0, 128),
+ 'shipping_address_2' => (isset($order['shipping_address']['street_address2']) ? utf8_substr($order['shipping_address']['street_address2'], 0, 128) : ''),
+ 'shipping_city' => utf8_substr($order['shipping_address']['city'], 0, 128),
+ 'shipping_postcode' => utf8_substr($order['shipping_address']['postal_code'], 0, 10),
+ 'shipping_zone' => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
+ 'shipping_zone_id' => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
+ 'shipping_country' => ($shipping_country_info ? $shipping_country_info['name'] : ''),
+ 'shipping_country_id' => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
+ 'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
+ );
+
+ $this->model_extension_payment_klarna_checkout->updateOcOrder($klarna_checkout_order['order_id'], $order_data);
+
+ $order_status_id = false;
+ switch ($order['status']) {
+ case 'AUTHORIZED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_authorised_id');
+
+ if ($order['fraud_status'] == 'PENDING') {
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_pending_id');
+ } elseif ($order['fraud_status'] == 'REJECTED') {
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
+ }
+ break;
+ case 'PART_CAPTURED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_part_captured_id');
+ break;
+ case 'CAPTURED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_captured_id');
+ break;
+ case 'CANCELLED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_cancelled_id');
+ break;
+ }
+
+ if ($order_status_id) {
+ $this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot retrieve KC order using order_id: ' . $this->request->get['klarna_order_id']);
+ }
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot find KC order using order_id: ' . $this->request->get['klarna_order_id']);
+ }
+ }
+ }
+
+ private function setPayment() {
+ $this->load->model('account/address');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ if (isset($this->session->data['payment_address']) && !empty($this->session->data['payment_address'])) {
+ $this->session->data['payment_address'] = $this->session->data['payment_address'];
+ } elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
+ $this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ } else {
+ $country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
+
+ $zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
+
+ $this->session->data['payment_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => $zone_info['zone_id'],
+ 'zone' => $zone_info['name'],
+ 'zone_code' => $zone_info['code'],
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+ }
+
+ $this->tax->setPaymentAddress($this->session->data['payment_address']['country_id'], $this->session->data['payment_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ }
+
+ private function setShipping() {
+ $this->load->model('account/address');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ if (isset($this->session->data['shipping_address']) && !empty($this->session->data['shipping_address'])) {
+ $this->session->data['shipping_address'] = $this->session->data['shipping_address'];
+ } elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
+ $this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ } else {
+ $country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
+
+ $zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
+
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => $zone_info['zone_id'],
+ 'zone' => $zone_info['name'],
+ 'zone_code' => $zone_info['code'],
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+ }
+
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ if (isset($this->session->data['shipping_address'])) {
+ // Shipping Methods
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $method_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $this->session->data['shipping_methods'] = $method_data;
+ }
+ }
+
+ private function createOrder() {
+ //Klarna defaults:
+ $this->session->data['comment'] = '';
+
+ if (!$this->customer->isLogged()) {
+ $this->session->data['guest'] = array(
+ 'customer_group_id' => $this->config->get('config_customer_group_id'),
+ 'firstname' => '',
+ 'lastname' => '',
+ 'email' => '',
+ 'telephone' => '',
+ 'fax' => '',
+ 'custom_field' => array(),
+ );
+ }
+
+ //OpenCart:
+ $order_data = array();
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ $order_data['totals'] = $totals;
+
+ $this->load->language('checkout/checkout');
+
+ $order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
+ $order_data['store_id'] = $this->config->get('config_store_id');
+ $order_data['store_name'] = $this->config->get('config_name');
+
+ if ($order_data['store_id']) {
+ $order_data['store_url'] = $this->config->get('config_url');
+ } else {
+ $order_data['store_url'] = HTTP_SERVER;
+ }
+
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/customer');
+
+ $customer_info = $this->model_account_customer->getCustomer($this->customer->getId());
+
+ $order_data['customer_id'] = $this->customer->getId();
+ $order_data['customer_group_id'] = $customer_info['customer_group_id'];
+ $order_data['firstname'] = $customer_info['firstname'];
+ $order_data['lastname'] = $customer_info['lastname'];
+ $order_data['email'] = $customer_info['email'];
+ $order_data['telephone'] = $customer_info['telephone'];
+ $order_data['custom_field'] = json_decode($customer_info['custom_field'], true);
+ } elseif (isset($this->session->data['guest'])) {
+ $order_data['customer_id'] = 0;
+ $order_data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
+ $order_data['firstname'] = $this->session->data['guest']['firstname'];
+ $order_data['lastname'] = $this->session->data['guest']['lastname'];
+ $order_data['email'] = $this->session->data['guest']['email'];
+ $order_data['telephone'] = $this->session->data['guest']['telephone'];
+ $order_data['custom_field'] = $this->session->data['guest']['custom_field'];
+ }
+
+ $order_data['payment_firstname'] = $this->session->data['payment_address']['firstname'];
+ $order_data['payment_lastname'] = $this->session->data['payment_address']['lastname'];
+ $order_data['payment_company'] = $this->session->data['payment_address']['company'];
+ $order_data['payment_address_1'] = $this->session->data['payment_address']['address_1'];
+ $order_data['payment_address_2'] = $this->session->data['payment_address']['address_2'];
+ $order_data['payment_city'] = $this->session->data['payment_address']['city'];
+ $order_data['payment_postcode'] = $this->session->data['payment_address']['postcode'];
+ $order_data['payment_zone'] = $this->session->data['payment_address']['zone'];
+ $order_data['payment_zone_id'] = $this->session->data['payment_address']['zone_id'];
+ $order_data['payment_country'] = $this->session->data['payment_address']['country'];
+ $order_data['payment_country_id'] = $this->session->data['payment_address']['country_id'];
+ $order_data['payment_address_format'] = $this->session->data['payment_address']['address_format'];
+ $order_data['payment_custom_field'] = (isset($this->session->data['payment_address']['custom_field']) ? $this->session->data['payment_address']['custom_field'] : array());
+
+ if (isset($this->session->data['payment_method']['title'])) {
+ $order_data['payment_method'] = $this->session->data['payment_method']['title'];
+ } else {
+ $order_data['payment_method'] = '';
+ }
+
+ if (isset($this->session->data['payment_method']['code'])) {
+ $order_data['payment_code'] = $this->session->data['payment_method']['code'];
+ } else {
+ $order_data['payment_code'] = '';
+ }
+
+ if ($this->cart->hasShipping()) {
+ $order_data['shipping_firstname'] = $this->session->data['shipping_address']['firstname'];
+ $order_data['shipping_lastname'] = $this->session->data['shipping_address']['lastname'];
+ $order_data['shipping_company'] = $this->session->data['shipping_address']['company'];
+ $order_data['shipping_address_1'] = $this->session->data['shipping_address']['address_1'];
+ $order_data['shipping_address_2'] = $this->session->data['shipping_address']['address_2'];
+ $order_data['shipping_city'] = $this->session->data['shipping_address']['city'];
+ $order_data['shipping_postcode'] = $this->session->data['shipping_address']['postcode'];
+ $order_data['shipping_zone'] = $this->session->data['shipping_address']['zone'];
+ $order_data['shipping_zone_id'] = $this->session->data['shipping_address']['zone_id'];
+ $order_data['shipping_country'] = $this->session->data['shipping_address']['country'];
+ $order_data['shipping_country_id'] = $this->session->data['shipping_address']['country_id'];
+ $order_data['shipping_address_format'] = $this->session->data['shipping_address']['address_format'];
+ $order_data['shipping_custom_field'] = (isset($this->session->data['shipping_address']['custom_field']) ? $this->session->data['shipping_address']['custom_field'] : array());
+
+ if (isset($this->session->data['shipping_method']['title'])) {
+ $order_data['shipping_method'] = $this->session->data['shipping_method']['title'];
+ } else {
+ $order_data['shipping_method'] = '';
+ }
+
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $order_data['shipping_code'] = $this->session->data['shipping_method']['code'];
+ } else {
+ $order_data['shipping_code'] = '';
+ }
+ } else {
+ $order_data['shipping_firstname'] = '';
+ $order_data['shipping_lastname'] = '';
+ $order_data['shipping_company'] = '';
+ $order_data['shipping_address_1'] = '';
+ $order_data['shipping_address_2'] = '';
+ $order_data['shipping_city'] = '';
+ $order_data['shipping_postcode'] = '';
+ $order_data['shipping_zone'] = '';
+ $order_data['shipping_zone_id'] = '';
+ $order_data['shipping_country'] = '';
+ $order_data['shipping_country_id'] = '';
+ $order_data['shipping_address_format'] = '';
+ $order_data['shipping_custom_field'] = array();
+ $order_data['shipping_method'] = '';
+ $order_data['shipping_code'] = '';
+ }
+
+ $order_data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ $option_data[] = array(
+ 'product_option_id' => $option['product_option_id'],
+ 'product_option_value_id' => $option['product_option_value_id'],
+ 'option_id' => $option['option_id'],
+ 'option_value_id' => $option['option_value_id'],
+ 'name' => $option['name'],
+ 'value' => $option['value'],
+ 'type' => $option['type']
+ );
+ }
+
+ $order_data['products'][] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'download' => $product['download'],
+ 'quantity' => $product['quantity'],
+ 'subtract' => $product['subtract'],
+ 'price' => $product['price'],
+ 'total' => $product['total'],
+ 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
+ 'reward' => $product['reward']
+ );
+ }
+
+ // Gift Voucher
+ $order_data['vouchers'] = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $voucher) {
+ $order_data['vouchers'][] = array(
+ 'description' => $voucher['description'],
+ 'code' => token(10),
+ 'to_name' => $voucher['to_name'],
+ 'to_email' => $voucher['to_email'],
+ 'from_name' => $voucher['from_name'],
+ 'from_email' => $voucher['from_email'],
+ 'voucher_theme_id' => $voucher['voucher_theme_id'],
+ 'message' => $voucher['message'],
+ 'amount' => $voucher['amount']
+ );
+ }
+ }
+
+ $order_data['comment'] = $this->session->data['comment'];
+ $order_data['total'] = $total;
+
+ if (isset($this->request->cookie['tracking'])) {
+ $order_data['tracking'] = $this->request->cookie['tracking'];
+
+ $subtotal = $this->cart->getSubTotal();
+
+ // Affiliate
+ $this->load->model('affiliate/affiliate');
+
+ $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
+
+ if ($affiliate_info) {
+ $order_data['affiliate_id'] = $affiliate_info['affiliate_id'];
+ $order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ }
+
+ // Marketing
+ $this->load->model('checkout/marketing');
+
+ $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
+
+ if ($marketing_info) {
+ $order_data['marketing_id'] = $marketing_info['marketing_id'];
+ } else {
+ $order_data['marketing_id'] = 0;
+ }
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ $order_data['marketing_id'] = 0;
+ $order_data['tracking'] = '';
+ }
+
+ $order_data['language_id'] = $this->config->get('config_language_id');
+ $order_data['currency_id'] = $this->currency->getId($this->session->data['currency']);
+ $order_data['currency_code'] = $this->session->data['currency'];
+ $order_data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
+ $order_data['ip'] = $this->request->server['REMOTE_ADDR'];
+
+ if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
+ } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
+ } else {
+ $order_data['forwarded_ip'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $order_data['user_agent'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
+ $order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
+ } else {
+ $order_data['accept_language'] = '';
+ }
+
+ $this->load->model('checkout/order');
+
+ $this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
+ }
+
+ private function klarnaOrderData($klarna_account) {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $currency_code = $this->session->data['currency'];
+ $currency_value = $this->currency->getValue($this->session->data['currency']);
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote == $this->session->data['shipping_method']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ //Check if customer is US. If so, send taxes differently
+ if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
+ $include_taxes = false;
+ } else {
+ $include_taxes = true;
+ }
+
+ if ($this->cart->hasShipping() && isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
+ $total_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id']), $currency_code, $currency_value, false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], false), $currency_code, $currency_value, false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'shipping_fee',
+ 'name' => $this->session->data['shipping_method']['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ // Billing Address
+ if (isset($this->session->data['klarna_checkout_data'])) {
+ $klarna_order_data['billing_address'] = array(
+ 'given_name' => $this->session->data['klarna_checkout_data']['firstname'],
+ 'family_name' => $this->session->data['klarna_checkout_data']['lastname'],
+ 'email' => $this->session->data['klarna_checkout_data']['email'],
+ 'phone' => $this->session->data['klarna_checkout_data']['telephone'],
+ 'postal_code' => $this->session->data['shipping_address']['postcode'],
+ 'region' => $this->session->data['shipping_address']['zone_code'],
+ 'country' => $this->session->data['shipping_address']['iso_code_2'],
+ );
+ } else {
+ $klarna_order_data['billing_address'] = array(
+ 'given_name' => $this->session->data['shipping_address']['firstname'],
+ 'family_name' => $this->session->data['shipping_address']['lastname'],
+ 'email' => ($this->customer->isLogged() ? $this->customer->getEmail() : null),
+ 'phone' => ($this->customer->isLogged() ? $this->customer->getTelephone() : null)
+ );
+ }
+
+ // Order Total
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ $merchant_urls = array(
+ 'checkout' => html_entity_decode($this->url->link('extension/payment/klarna_checkout', 'klarna_order_id={checkout.order.id}', true)),
+ 'confirmation' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/confirmation', 'klarna_order_id={checkout.order.id}', true)),
+ 'push' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/push', 'klarna_order_id={checkout.order.id}', true)),
+ 'validation' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/validation', 'klarna_order_id={checkout.order.id}', true)),
+ 'address_update' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/addressUpdate', 'klarna_order_id={checkout.order.id}', true)),
+ 'notification' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/notification', 'klarna_order_id={checkout.order.id}', true)),
+ );
+
+ if ($this->config->get('klarna_checkout_terms')) {
+ $merchant_urls['terms'] = html_entity_decode($this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true));
+ }
+
+ $country_info = $this->model_localisation_country->getCountry($klarna_account['country']);
+
+ if ($country_info) {
+ $klarna_order_data['purchase_country'] = $country_info['iso_code_2'];
+ }
+
+ $klarna_order_data['purchase_currency'] = $currency_code;
+ $klarna_order_data['locale'] = $klarna_account['locale'];
+
+ $klarna_order_data['order_amount'] = round($this->currency->format($total, $currency_code, $currency_value, false) * 100);
+ $klarna_order_data['order_tax_amount'] = round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100);
+
+ $klarna_order_data['merchant_urls'] = $merchant_urls;
+
+ // Callback data to be used to spoof/simulate customer to accurately calculate shipping
+ $encrypted_order_data = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode(array(
+ 'session_id' => session_id(),
+ 'session_key' => $this->session->getId(),
+ 'customer_id' => $this->customer->getId(),
+ 'order_id' => $this->session->data['order_id'],
+ 'merchant_id' => $klarna_account['merchant_id'],
+ 'secret' => $klarna_account['secret']
+ )));
+
+ $encrypted_order_id = $this->encryption->encrypt($this->config->get('config_encryption'), $this->session->data['order_id']);
+
+ $klarna_order_data['merchant_reference1'] = $this->session->data['order_id'];
+
+ $klarna_order_data['options'] = array();
+
+ if ($this->config->get('klarna_checkout_colour_button')) {
+ $klarna_order_data['options']['color_button'] = $this->config->get('klarna_checkout_colour_button');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_button_text')) {
+ $klarna_order_data['options']['color_button_text'] = $this->config->get('klarna_checkout_colour_button_text');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_checkbox')) {
+ $klarna_order_data['options']['color_checkbox'] = $this->config->get('klarna_checkout_colour_checkbox');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_checkbox_checkmark')) {
+ $klarna_order_data['options']['color_checkbox_checkmark'] = $this->config->get('klarna_checkout_colour_checkbox_checkmark');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_header')) {
+ $klarna_order_data['options']['color_header'] = $this->config->get('klarna_checkout_colour_header');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_link')) {
+ $klarna_order_data['options']['color_link'] = $this->config->get('klarna_checkout_colour_link');
+ }
+
+ if ($this->config->get('klarna_checkout_separate_shipping_address')) {
+ $klarna_order_data['options']['allow_separate_shipping_address'] = true;
+ }
+
+ // Only pass DOB/title mandatory for UK stores
+ if ($country_info['iso_code_2'] == 'GB') {
+ if ($this->config->get('klarna_checkout_dob_mandatory')) {
+ $klarna_order_data['options']['date_of_birth_mandatory'] = true;
+ }
+
+ if ($this->config->get('klarna_checkout_title_mandatory')) {
+ $klarna_order_data['options']['title_mandatory'] = true;
+ }
+ }
+
+ if ($this->config->get('klarna_checkout_additional_text_box') && $this->customer->isLogged() && !$this->customer->getNewsletter()) {
+ $klarna_order_data['options']['additional_checkbox'] = array(
+ 'text' => $this->language->get('text_newsletter'),
+ 'checked' => false,
+ 'required' => false
+ );
+ }
+
+ $shipping_countries = $this->model_extension_payment_klarna_checkout->getCountriesByGeoZone($klarna_account['shipping']);
+
+ $klarna_shipping_countries = array();
+ foreach ($shipping_countries as $shipping_country) {
+ $country_info = $this->model_localisation_country->getCountry($shipping_country['country_id']);
+
+ if ($country_info && $country_info['iso_code_2']) {
+ $klarna_shipping_countries[] = $country_info['iso_code_2'];
+ }
+ }
+
+ $klarna_order_data['shipping_countries'] = $klarna_shipping_countries;
+
+ $average_product_tax_rate = array();
+
+ // Products (Add these last because we send encrypted session order_id)
+ foreach ($this->cart->getProducts() as $product) {
+ $total_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($product['price'], $product['tax_class_id']) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], false) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ $average_product_tax_rate[] = round($tax_rate * 100);
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => ($product['shipping'] ? 'physical' : 'digital'),
+ 'reference' => $product['model'],
+ 'name' => $product['name'],
+ 'quantity' => $product['quantity'],
+ 'quantity_unit' => 'pcs',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'merchant_data' => $encrypted_order_id,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ // Gift Voucher
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $key => $voucher) {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'gift_card',
+ 'reference' => '',
+ 'name' => $voucher['description'],
+ 'quantity' => 1,
+ 'quantity_unit' => 'pcs',
+ 'unit_price' => round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'merchant_data' => $encrypted_order_id,
+ 'total_discount_amount' => 0
+ );
+ }
+ }
+
+ foreach ($totals as $result) {
+ if ($result['code'] == 'coupon') {
+ $discount_total_price = 0;
+ $discount_sub_total_price = 0;
+ foreach ($this->cart->getProducts() as $product) {
+ $discount_total_price += $this->tax->calculate($result['value'], $product['tax_class_id'], $include_taxes);
+ $discount_sub_total_price += $result['value'];
+ }
+
+ $average_discount_total_price = $discount_total_price / count($average_product_tax_rate);
+
+ $average_discount_sub_total_price = $discount_sub_total_price / count($average_product_tax_rate);
+
+ $total_tax_amount = ($average_discount_sub_total_price / 100) * (array_sum($average_product_tax_rate) / count($average_product_tax_rate));
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'discount',
+ 'name' => $result['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => array_sum($average_product_tax_rate) / count($average_product_tax_rate),
+ 'total_amount' => round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ if ($result['code'] == 'voucher') {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'discount',
+ 'name' => $result['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+ }
+
+ //If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
+ if (!$include_taxes) {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'sales_tax',
+ 'name' => $this->language->get('text_sales_tax'),
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ return array($klarna_order_data, $encrypted_order_data);
+ }
+}
diff --git a/public/catalog/controller/extension/payment/klarna_invoice.php b/public/catalog/controller/extension/payment/klarna_invoice.php
new file mode 100644
index 0000000..8b3feae
--- /dev/null
+++ b/public/catalog/controller/extension/payment/klarna_invoice.php
@@ -0,0 +1,527 @@
+<?php
+class ControllerExtensionPaymentKlarnaInvoice extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $this->load->language('extension/payment/klarna_invoice');
+
+ $data['days'] = array();
+
+ for ($i = 1; $i <= 31; $i++) {
+ $data['days'][] = array(
+ 'text' => sprintf('%02d', $i),
+ 'value' => $i
+ );
+ }
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => sprintf('%02d', $i),
+ 'value' => $i
+ );
+ }
+
+ $data['years'] = array();
+
+ for ($i = date('Y'); $i >= 1900; $i--) {
+ $data['years'][] = array(
+ 'text' => $i,
+ 'value' => $i
+ );
+ }
+
+ // Store Taxes to send to Klarna
+ $total_data = array();
+ $total = 0;
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ $klarna_tax = array();
+
+ foreach ($results as $result) {
+ if ($this->config->get($result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ $taxes = array();
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal(array("totals"=>$total_data, "total"=>$total, "taxes"=>$taxes));
+
+ $amount = 0;
+
+ foreach ($taxes as $tax_id => $value) {
+ $amount += $value;
+ }
+
+ $klarna_tax[$result['code']] = $amount;
+ }
+ }
+
+ foreach ($total_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+
+ if (isset($klarna_tax[$value['code']])) {
+ if ($klarna_tax[$value['code']]) {
+ $total_data[$key]['tax_rate'] = abs($klarna_tax[$value['code']] / $value['value'] * 100);
+ } else {
+ $total_data[$key]['tax_rate'] = 0;
+ }
+ } else {
+ $total_data[$key]['tax_rate'] = '0';
+ }
+ }
+
+ $this->session->data['klarna'][$this->session->data['order_id']] = $total_data;
+
+ // Order must have identical shipping and billing address or have no shipping address at all
+ if ($this->cart->hasShipping() && !($order_info['payment_firstname'] == $order_info['shipping_firstname'] && $order_info['payment_lastname'] == $order_info['shipping_lastname'] && $order_info['payment_address_1'] == $order_info['shipping_address_1'] && $order_info['payment_address_2'] == $order_info['shipping_address_2'] && $order_info['payment_postcode'] == $order_info['shipping_postcode'] && $order_info['payment_city'] == $order_info['shipping_city'] && $order_info['payment_zone_id'] == $order_info['shipping_zone_id'] && $order_info['payment_zone_code'] == $order_info['shipping_zone_code'] && $order_info['payment_country_id'] == $order_info['shipping_country_id'] && $order_info['payment_country'] == $order_info['shipping_country'] && $order_info['payment_iso_code_3'] == $order_info['shipping_iso_code_3'])) {
+ $data['error_warning'] = $this->language->get('error_address_match');
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ $klarna_invoice = $this->config->get('payment_klarna_invoice');
+
+ $data['merchant'] = $klarna_invoice[$order_info['payment_iso_code_3']]['merchant'];
+ $data['phone_number'] = $order_info['telephone'];
+
+ if ($order_info['payment_iso_code_3'] == 'DEU' || $order_info['payment_iso_code_3'] == 'NLD') {
+ $address = $this->splitAddress($order_info['payment_address_1']);
+
+ $data['street'] = $address[0];
+ $data['street_number'] = $address[1];
+ $data['street_extension'] = $address[2];
+
+ if ($order_info['payment_iso_code_3'] == 'DEU') {
+ $data['street_number'] = trim($address[1] . ' ' . $address[2]);
+ }
+ } else {
+ $data['street'] = '';
+ $data['street_number'] = '';
+ $data['street_extension'] = '';
+ }
+
+ $data['company'] = $order_info['payment_company'];
+ $data['iso_code_2'] = $order_info['payment_iso_code_2'];
+ $data['iso_code_3'] = $order_info['payment_iso_code_3'];
+
+ // Get the invoice fee
+ $query = $this->db->query("SELECT `value` FROM `" . DB_PREFIX . "order_total` WHERE `order_id` = " . (int)$order_info['order_id'] . " AND `code` = 'klarna_fee'");
+
+ if ($query->num_rows && !$query->row['value']) {
+ $data['klarna_fee'] = $query->row['value'];
+ } else {
+ $data['klarna_fee'] = '';
+ }
+
+ return $this->load->view('extension/payment/klarna_invoice', $data);
+ }
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/klarna_invoice');
+
+ $json = array();
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ // Order must have identical shipping and billing address or have no shipping address at all
+ if ($order_info) {
+ if ($order_info['payment_iso_code_3'] == 'DEU' && empty($this->request->post['deu_terms'])) {
+ $json['error'] = $this->language->get('error_deu_terms');
+ }
+
+ if ($this->cart->hasShipping() && !($order_info['payment_firstname'] == $order_info['shipping_firstname'] && $order_info['payment_lastname'] == $order_info['shipping_lastname'] && $order_info['payment_address_1'] == $order_info['shipping_address_1'] && $order_info['payment_address_2'] == $order_info['shipping_address_2'] && $order_info['payment_postcode'] == $order_info['shipping_postcode'] && $order_info['payment_city'] == $order_info['shipping_city'] && $order_info['payment_zone_id'] == $order_info['shipping_zone_id'] && $order_info['payment_zone_code'] == $order_info['shipping_zone_code'] && $order_info['payment_country_id'] == $order_info['shipping_country_id'] && $order_info['payment_country'] == $order_info['shipping_country'] && $order_info['payment_iso_code_3'] == $order_info['shipping_iso_code_3'])) {
+ $json['error'] = $this->language->get('error_address_match');
+ }
+
+ if (!$json) {
+ $klarna_invoice = $this->config->get('payment_klarna_invoice');
+
+ if ($klarna_invoice[$order_info['payment_iso_code_3']]['server'] == 'live') {
+ $url = 'https://payment.klarna.com/';
+ } else {
+ $url = 'https://payment.testdrive.klarna.com/';
+ }
+
+ $country_to_currency = array(
+ 'NOR' => 'NOK',
+ 'SWE' => 'SEK',
+ 'FIN' => 'EUR',
+ 'DNK' => 'DKK',
+ 'DEU' => 'EUR',
+ 'NLD' => 'EUR'
+ );
+
+ switch ($order_info['payment_iso_code_3']) {
+ // Sweden
+ case 'SWE':
+ $country = 209;
+ $language = 138;
+ $encoding = 2;
+ $currency = 0;
+ break;
+ // Finland
+ case 'FIN':
+ $country = 73;
+ $language = 37;
+ $encoding = 4;
+ $currency = 2;
+ break;
+ // Denmark
+ case 'DNK':
+ $country = 59;
+ $language = 27;
+ $encoding = 5;
+ $currency = 3;
+ break;
+ // Norway
+ case 'NOR':
+ $country = 164;
+ $language = 97;
+ $encoding = 3;
+ $currency = 1;
+ break;
+ // Germany
+ case 'DEU':
+ $country = 81;
+ $language = 28;
+ $encoding = 6;
+ $currency = 2;
+ break;
+ // Netherlands
+ case 'NLD':
+ $country = 154;
+ $language = 101;
+ $encoding = 7;
+ $currency = 2;
+ break;
+ }
+
+ if (isset($this->request->post['street'])) {
+ $street = $this->request->post['street'];
+ } else {
+ $street = $order_info['payment_address_1'];
+ }
+
+ if (isset($this->request->post['house_no'])) {
+ $house_no = $this->request->post['house_no'];
+ } else {
+ $house_no = '';
+ }
+
+ if (isset($this->request->post['house_ext'])) {
+ $house_ext = $this->request->post['house_ext'];
+ } else {
+ $house_ext = '';
+ }
+
+ $address = array(
+ 'email' => $order_info['email'],
+ 'telno' => $this->request->post['phone_no'],
+ 'cellno' => '',
+ 'fname' => $order_info['payment_firstname'],
+ 'lname' => $order_info['payment_lastname'],
+ 'company' => $order_info['payment_company'],
+ 'careof' => '',
+ 'street' => $street,
+ 'house_number' => $house_no,
+ 'house_extension' => $house_ext,
+ 'zip' => $order_info['payment_postcode'],
+ 'city' => $order_info['payment_city'],
+ 'country' => $country,
+ );
+
+ $product_query = $this->db->query("SELECT `name`, `model`, `price`, `quantity`, `tax` / `price` * 100 AS 'tax_rate' FROM `" . DB_PREFIX . "order_product` WHERE `order_id` = " . (int)$order_info['order_id'] . " UNION ALL SELECT '', `code`, `amount`, '1', 0.00 FROM `" . DB_PREFIX . "order_voucher` WHERE `order_id` = " . (int)$order_info['order_id']);
+
+ foreach ($product_query->rows as $product) {
+ $goods_list[] = array(
+ 'qty' => (int)$product['quantity'],
+ 'goods' => array(
+ 'artno' => $product['model'],
+ 'title' => $product['name'],
+ 'price' => (int)str_replace('.', '', $this->currency->format($product['price'], $country_to_currency[$order_info['payment_iso_code_3']], '', false)),
+ 'vat' => (float)$product['tax_rate'],
+ 'discount' => 0.0,
+ 'flags' => 0
+ )
+ );
+ }
+
+ if (isset($this->session->data['klarna'][$this->session->data['order_id']])) {
+ $totals = $this->session->data['klarna'][$this->session->data['order_id']];
+ } else {
+ $totals = array();
+ }
+
+ foreach ($totals as $total) {
+ if ($total['code'] != 'sub_total' && $total['code'] != 'tax' && $total['code'] != 'total') {
+ $goods_list[] = array(
+ 'qty' => 1,
+ 'goods' => array(
+ 'artno' => '',
+ 'title' => $total['title'],
+ 'price' => (int)str_replace('.', '', $this->currency->format($total['value'], $country_to_currency[$order_info['payment_iso_code_3']], '', false)),
+ 'vat' => (float)$total['tax_rate'],
+ 'discount' => 0.0,
+ 'flags' => 0
+ )
+ );
+ }
+ }
+
+ $digest = '';
+
+ foreach ($goods_list as $goods) {
+ $digest .= utf8_decode(htmlspecialchars(html_entity_decode($goods['goods']['title'], ENT_COMPAT, 'UTF-8'))) . ':';
+ }
+
+ $digest = base64_encode(pack('H*', hash('sha256', $digest . $klarna_invoice[$order_info['payment_iso_code_3']]['secret'])));
+
+ if (isset($this->request->post['pno'])) {
+ $pno = $this->request->post['pno'];
+ } else {
+ $pno = sprintf('%02d', (int)$this->request->post['pno_day']) . sprintf('%02d', (int)$this->request->post['pno_month']) . (int)$this->request->post['pno_year'];
+ }
+
+ $pclass = -1;
+
+ if (isset($this->request->post['gender']) && ($order_info['payment_iso_code_3'] == 'DEU' || $order_info['payment_iso_code_3'] == 'NLD')) {
+ $gender = (int)$this->request->post['gender'];
+ } else {
+ $gender = '';
+ }
+
+ $transaction = array(
+ '4.1',
+ 'API:OPENCART:' . VERSION,
+ $pno,
+ $gender,
+ '',
+ '',
+ (string)$order_info['order_id'],
+ '',
+ $address,
+ $address,
+ $order_info['ip'],
+ 0,
+ $currency,
+ $country,
+ $language,
+ (int)$klarna_invoice[$order_info['payment_iso_code_3']]['merchant'],
+ $digest,
+ $encoding,
+ $pclass,
+ $goods_list,
+ $order_info['comment'],
+ array('delay_adjust' => 1),
+ array(),
+ array(),
+ array(),
+ array(),
+ array()
+ );
+
+ $xml = '<methodCall>';
+ $xml .= ' <methodName>add_invoice</methodName>';
+ $xml .= ' <params>';
+
+ foreach ($transaction as $parameter) {
+ $xml .= ' <param><value>' . $this->constructXmlrpc($parameter) . '</value></param>';
+ }
+
+ $xml .= ' </params>';
+ $xml .= '</methodCall>';
+
+ $header = array();
+
+ $header[] = 'Content-Type: text/xml';
+ $header[] = 'Content-Length: ' . strlen($xml);
+
+ $curl = curl_init();
+
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
+
+ $response = curl_exec($curl);
+
+ if (curl_errno($curl)) {
+ $log = new Log('klarna_invoice.log');
+ $log->write('HTTP Error for order #' . $order_info['order_id'] . '. Code: ' . curl_errno($curl) . ' message: ' . curl_error($curl));
+
+ $json['error'] = $this->language->get('error_network');
+ } else {
+ preg_match('/<member><name>faultString<\/name><value><string>(.+)<\/string><\/value><\/member>/', $response, $match);
+
+ if (isset($match[1])) {
+ preg_match('/<member><name>faultCode<\/name><value><int>([0-9]+)<\/int><\/value><\/member>/', $response, $match2);
+
+ $log = new Log('klarna_invoice.log');
+ $log->write('Failed to create an invoice for order #' . $order_info['order_id'] . '. Message: ' . utf8_encode($match[1]) . ' Code: ' . $match2[1]);
+
+ $json['error'] = utf8_encode($match[1]);
+ } else {
+ $xml = new DOMDocument();
+ $xml->loadXML($response);
+
+ $invoice_number = $xml->getElementsByTagName('string')->item(0)->nodeValue;
+ $klarna_order_status = $xml->getElementsByTagName('int')->item(0)->nodeValue;
+
+ if ($klarna_order_status == '1') {
+ $order_status = $klarna_invoice[$order_info['payment_iso_code_3']]['accepted_status_id'];
+ } elseif ($klarna_order_status == '2') {
+ $order_status = $klarna_invoice[$order_info['payment_iso_code_3']]['pending_status_id'];
+ } else {
+ $order_status = $this->config->get('config_order_status_id');
+ }
+
+ $comment = sprintf($this->language->get('text_comment'), $invoice_number, $this->config->get('config_currency'), $country_to_currency[$order_info['payment_iso_code_3']], $this->currency->getValue($country_to_currency[$order_info['payment_iso_code_3']]));
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $order_status, $comment, 1);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ }
+ }
+
+ curl_close($curl);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ private function constructXmlrpc($data) {
+ $type = gettype($data);
+
+ switch ($type) {
+ case 'boolean':
+ if ($data == true) {
+ $value = 1;
+ } else {
+ $value = false;
+ }
+
+ $xml = '<boolean>' . $value . '</boolean>';
+ break;
+ case 'integer':
+ $xml = '<int>' . (int)$data . '</int>';
+ break;
+ case 'double':
+ $xml = '<double>' . (float)$data . '</double>';
+ break;
+ case 'string':
+ $xml = '<string>' . htmlspecialchars($data) . '</string>';
+ break;
+ case 'array':
+ // is numeric ?
+ if ($data === array_values($data)) {
+ $xml = '<array><data>';
+
+ foreach ($data as $value) {
+ $xml .= '<value>' . $this->constructXmlrpc($value) . '</value>';
+ }
+
+ $xml .= '</data></array>';
+
+ } else {
+ // array is associative
+ $xml = '<struct>';
+
+ foreach ($data as $key => $value) {
+ $xml .= '<member>';
+ $xml .= ' <name>' . htmlspecialchars($key) . '</name>';
+ $xml .= ' <value>' . $this->constructXmlrpc($value) . '</value>';
+ $xml .= '</member>';
+ }
+
+ $xml .= '</struct>';
+ }
+
+ break;
+ default:
+ $xml = '<nil/>';
+ break;
+ }
+
+ return $xml;
+ }
+
+ private function splitAddress($address) {
+ $numbers = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
+
+ $characters = array('-', '/', ' ', '#', '.', 'a', 'b', 'c', 'd', 'e',
+ 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A',
+ 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z');
+
+ $specialchars = array('-', '/', ' ', '#', '.');
+
+ $num_pos = $this->strposArr($address, $numbers, 2);
+
+ $street_name = substr($address, 0, $num_pos);
+
+ $street_name = trim($street_name);
+
+ $number_part = substr($address, $num_pos);
+
+ $number_part = trim($number_part);
+
+ $ext_pos = $this->strposArr($number_part, $characters, 0);
+
+ if ($ext_pos != '') {
+ $house_number = substr($number_part, 0, $ext_pos);
+
+ $house_extension = substr($number_part, $ext_pos);
+
+ $house_extension = str_replace($specialchars, '', $house_extension);
+ } else {
+ $house_number = $number_part;
+ $house_extension = '';
+ }
+
+ return array($street_name, $house_number, $house_extension);
+ }
+
+ private function strposArr($haystack, $needle, $where) {
+ $defpos = 10000;
+
+ if (!is_array($needle)) {
+ $needle = array($needle);
+ }
+
+ foreach ($needle as $what) {
+ if (($pos = strpos($haystack, $what, $where)) !== false) {
+ if ($pos < $defpos) {
+ $defpos = $pos;
+ }
+ }
+ }
+
+ return $defpos;
+ }
+}
diff --git a/public/catalog/controller/extension/payment/laybuy.php b/public/catalog/controller/extension/payment/laybuy.php
new file mode 100644
index 0000000..433aaf0
--- /dev/null
+++ b/public/catalog/controller/extension/payment/laybuy.php
@@ -0,0 +1,478 @@
+<?php
+class ControllerExtensionPaymentLaybuy extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/laybuy');
+
+ $this->load->model('extension/payment/laybuy');
+
+ $this->load->model('checkout/order');
+
+ $data['action'] = $this->url->link('extension/payment/laybuy/postToLaybuy', '', true);
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['order_info'] = $order_info;
+
+ $data['total'] = $order_info['total'];
+
+ $data['currency_symbol_left'] = $this->currency->getSymbolLeft($this->session->data['currency']);
+
+ $data['currency_symbol_right'] = $this->currency->getSymbolRight($this->session->data['currency']);
+
+ $data['initial_payments'] = $this->model_extension_payment_laybuy->getInitialPayments();
+
+ $data['months'] = $this->model_extension_payment_laybuy->getMonths();
+
+ return $this->load->view('extension/payment/laybuy', $data);
+ }
+
+ public function postToLaybuy() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Posting to Laybuy');
+
+ if ($this->request->server['REQUEST_METHOD'] == 'POST') {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $this->model_extension_payment_laybuy->log('Order ID: ' . $order_info['order_id']);
+
+ $data = array();
+
+ $data['VERSION'] = '0.2';
+ $data['MEMBER'] = $this->config->get('payment_laybuys_membership_id');
+ $data['RETURNURL'] = $this->url->link('extension/payment/laybuy/callback', '', true);
+ $data['CANCELURL'] = $this->url->link('extension/payment/laybuy/cancel', '', true);
+ $data['AMOUNT'] = round(floatval($order_info['total']), 2, PHP_ROUND_HALF_DOWN);
+ $data['CURRENCY'] = $order_info['currency_code'];
+ $data['INIT'] = (int)$this->request->post['INIT'];
+ $data['MONTHS'] = (int)$this->request->post['MONTHS'];
+ $data['MIND'] = ((int)$this->config->get('payment_laybuy_min_deposit')) ? (int)$this->config->get('payment_laybuy_min_deposit') : 20;
+ $data['MAXD'] = ((int)$this->config->get('payment_laybuy_max_deposit')) ? (int)$this->config->get('payment_laybuy_max_deposit') : 50;
+ $data['CUSTOM'] = $order_info['order_id'] . ':' . md5($this->config->get('payment_laybuy_token'));
+ $data['EMAIL'] = $order_info['email'];
+
+ $data_string = '';
+
+ foreach ($data as $param => $value) {
+ $data_string .= $param . '=' . $value . '&';
+ }
+
+ $data_string = rtrim($data_string, '&');
+
+ $this->model_extension_payment_laybuy->log('Data String: ' . $data_string);
+
+ $this->model_extension_payment_laybuy->log('Gateway URL: ' . $this->config->get('payment_laybuy_gateway_url'));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $this->config->get('payment_laybuy_gateway_url'));
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $result = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_laybuy->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $result = json_decode($result, true);
+
+ $this->model_extension_payment_laybuy->log('Response: ' . print_r($result, true));
+
+ if (isset($result['ACK']) && isset($result['TOKEN']) && $result['ACK'] == 'SUCCESS') {
+ $this->model_extension_payment_laybuy->log('Success response. Redirecting to PayPal.');
+
+ $this->response->redirect($this->config->get('payment_laybuy_gateway_url') . '?TOKEN=' . $result['TOKEN']);
+ } else {
+ $this->model_extension_payment_laybuy->log('Failure response. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('No matching order. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('No $_POST data. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ }
+
+ public function callback() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Receiving callback');
+
+ if ($this->request->server['REQUEST_METHOD'] == 'POST' && isset($this->request->post['RESULT']) && $this->request->post['RESULT'] == 'SUCCESS') {
+ $this->load->model('checkout/order');
+
+ $custom = $this->request->post['CUSTOM'];
+
+ $custom = explode(':', $custom);
+
+ $order_id = $custom[0];
+
+ $token = $custom[1];
+
+ $this->model_extension_payment_laybuy->log('Received Token: ' . $token);
+
+ $this->model_extension_payment_laybuy->log('Actual Token: ' . md5($this->config->get('payment_laybuy_token')));
+
+ if (hash_equals(md5($this->config->get('payment_laybuy_token')), $token)) {
+ $this->model_extension_payment_laybuy->log('Order ID: ' . $order_id);
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_laybuy_order_status_id_pending'));
+
+ $transaction_report = $this->model_extension_payment_laybuy->prepareTransactionReport($this->request->post);
+
+ $this->model_extension_payment_laybuy->addTransaction($transaction_report, 1);
+
+ $this->model_extension_payment_laybuy->log('Success. Redirecting to checkout/success.');
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->model_extension_payment_laybuy->log('No matching order. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('Token does not match. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } elseif ($this->request->server['REQUEST_METHOD'] == 'POST' && isset($this->request->post['RESULT']) && $this->request->post['RESULT'] == 'FAILURE') {
+ $this->model_extension_payment_laybuy->log('Failure Response: ' . $this->request->post);
+
+ $this->model_extension_payment_laybuy->log('Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ } else {
+ $this->model_extension_payment_laybuy->log('Either no $_POST data or unknown response. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ }
+
+ public function cancel() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Transaction canceled by user. Redirecting to checkout/checkout.');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ public function reviseCallback() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->load->language('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Receiving callback');
+
+ if ($this->request->server['REQUEST_METHOD'] == 'POST') {
+ if (isset($this->request->post['RESULT']) && $this->request->post['RESULT'] == 'SUCCESS') {
+ $this->load->model('checkout/order');
+
+ $custom = $this->request->post['CUSTOM'];
+
+ $custom = explode(':', $custom);
+
+ $order_id = $custom[0];
+
+ $token = $custom[1];
+
+ $this->model_extension_payment_laybuy->log('Received Token: ' . $token);
+
+ $this->model_extension_payment_laybuy->log('Actual Token: ' . md5($this->config->get('payment_laybuy_token')));
+
+ if (hash_equals(md5($this->config->get('payment_laybuy_token')), $token)) {
+ $this->model_extension_payment_laybuy->log('Order ID: ' . $order_id);
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $response = $this->request->post;
+
+ $this->model_extension_payment_laybuy->log('Response: ' . print_r($response, true));
+
+ $revised_transaction_id = $response['MERCHANTS_REF_NO'];
+
+ $revised_transaction = $this->model_extension_payment_laybuy->getRevisedTransaction($revised_transaction_id);
+
+ $this->model_extension_payment_laybuy->log('Revised transaction: ' . print_r($revised_transaction, true));
+
+ $status = 1;
+
+ $current_date = date('Y-m-d h:i:s');
+
+ if (!isset($response['DOWNPAYMENT']) && !$revised_transaction['payment_type']) {
+ $this->model_extension_payment_laybuy->log('Buy-Now');
+
+ $response['DOWNPAYMENT'] = 100;
+ $response['MONTHS'] = 0;
+ $response['DOWNPAYMENT_AMOUNT'] = $response['AMOUNT'];
+ $response['PAYMENT_AMOUNTS'] = 0;
+ $response['FIRST_PAYMENT_DUE'] = $current_date;
+ $response['LAST_PAYMENT_DUE'] = $current_date;
+ $response['PAYPAL_PROFILE_ID'] = '';
+
+ $status = 5;
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_laybuy_order_status_id_processing'), $this->language->get('text_comment'));
+ } else {
+ $this->model_extension_payment_laybuy->log('Lay-Buy');
+ }
+
+ $this->session->data['order_id'] = $order_id;
+
+ $transaction_report = $this->model_extension_payment_laybuy->prepareTransactionReport($response);
+
+ $transaction_report['order_id'] = $order_id;
+
+ $this->model_extension_payment_laybuy->addTransaction($transaction_report, $status);
+
+ $old_transaction = $this->model_extension_payment_laybuy->getTransaction($revised_transaction['laybuy_transaction_id']);
+
+ $report_content = json_decode($old_transaction['report'], true);
+
+ foreach ($report_content as &$array) {
+ $array['status'] = str_replace('Pending', 'Canceled', $array['status']);
+ }
+
+ $report_content = json_encode($report_content);
+
+ if ($old_transaction['paypal_profile_id']) {
+ $this->model_extension_payment_laybuy->log('Canceling transaction');
+
+ $data_string = 'mid=' . $this->config->get('payment_laybuys_membership_id') . '&' . 'paypal_profile_id=' . $old_transaction['paypal_profile_id'];
+
+ $this->model_extension_payment_laybuy->log('Data String: ' . $data_string);
+
+ $ch = curl_init();
+ $url = 'https://lay-buys.com/vtmob/deal5cancel.php';
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $result = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_laybuy->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $this->model_extension_payment_laybuy->log('Response: ' . $result);
+
+ if ($result == 'success') {
+ $this->model_extension_payment_laybuy->log('Success');
+ } else {
+ $this->model_extension_payment_laybuy->log('Failure');
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('Transaction has no paypal_profile_id');
+ }
+
+ $this->model_extension_payment_laybuy->updateTransaction($old_transaction['laybuy_transaction_id'], '51', $report_content, $old_transaction['transaction']);
+
+ $this->model_extension_payment_laybuy->deleteRevisedTransaction($revised_transaction['laybuy_revise_request_id']);
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->model_extension_payment_laybuy->log('No matching order. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('Token does not match. Redirecting to checkout/failure.');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('No success response');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('No $_POST data');
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ }
+
+ public function reviseCancel() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Revise canceled. Redirecting to checkout/checkout.');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ public function deleteOrder($route = '', $output = '', $order_id = 0, $order_status_id = 0) {
+ $this->load->model('extension/payment/laybuy');
+
+ if (isset($this->session->data['api_id'])) {
+ $this->model_extension_payment_laybuy->log('Deleting order #' . $order_id);
+
+ $this->model_extension_payment_laybuy->deleteTransactionByOrderId($order_id);
+ } else {
+ $this->model_extension_payment_laybuy->log('No API ID in session');
+ }
+ }
+
+ public function cron() {
+ $this->load->model('extension/payment/laybuy');
+
+ $this->load->language('extension/payment/laybuy');
+
+ $this->model_extension_payment_laybuy->log('Running cron');
+
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_laybuy_token'), $this->request->get['token'])) {
+ $paypal_profile_id_array = $this->model_extension_payment_laybuy->getPayPalProfileIds();
+
+ if ($paypal_profile_id_array) {
+ $paypal_profile_ids = '';
+
+ foreach ($paypal_profile_id_array as $profile_id) {
+ $paypal_profile_ids .= $profile_id['paypal_profile_id'] . ',';
+ }
+
+ $paypal_profile_ids = rtrim($paypal_profile_ids, ',');
+
+ $data_string = 'mid=' . $this->config->get('payment_laybuys_membership_id') . '&' . 'profileIds=' . $paypal_profile_ids;
+
+ $this->model_extension_payment_laybuy->log('Data String: ' . $data_string);
+
+ $this->model_extension_payment_laybuy->log('API URL: ' . $this->config->get('payment_laybuy_api_url'));
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $this->config->get('payment_laybuy_api_url'));
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HEADER, false);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ $result = curl_exec($ch);
+ if (curl_errno($ch)) {
+ $this->model_extension_payment_laybuy->log('cURL error: ' . curl_errno($ch));
+ }
+ curl_close($ch);
+
+ $results = json_decode($result, true);
+
+ $this->model_extension_payment_laybuy->log('Response: ' . print_r($results, true));
+
+ if ($results) {
+ $this->load->model('checkout/order');
+
+ foreach ($results as $laybuy_ref_id => $reports) {
+ $status = $reports['status'];
+
+ $report = $reports['report'];
+
+ $transaction = array();
+
+ $transaction = $this->model_extension_payment_laybuy->getTransactionByLayBuyRefId($laybuy_ref_id);
+
+ $order_id = $transaction['order_id'];
+
+ $paypal_profile_id = $transaction['paypal_profile_id'];
+
+ $months = $transaction['months'];
+
+ $report_content = array();
+
+ $pending_flag = false;
+
+ $next_payment_status = $this->language->get('text_status_1');
+
+ foreach ($report as $month => $payment) {
+ $payment['paymentDate'] = date('Y-m-d h:i:s', strtotime(str_replace('/', '-', $payment['paymentDate'])));
+ $date = date($this->language->get('date_format_short'), strtotime($payment['paymentDate']));
+ $next_payment_date = $payment['paymentDate'];
+
+ if ($payment['type'] == 'd') {
+ $report_content[] = array(
+ 'instalment' => 0,
+ 'amount' => $this->currency->format($payment['amount'], $transaction['currency']),
+ 'date' => $date,
+ 'pp_trans_id' => $payment['txnID'],
+ 'status' => $payment['paymentStatus']
+ );
+ } elseif ($payment['type'] == 'p') {
+ $pending_flag = true;
+
+ $report_content[] = array(
+ 'instalment' => $month,
+ 'amount' => $this->currency->format($payment['amount'], $transaction['currency']),
+ 'date' => $date,
+ 'pp_trans_id' => $payment['txnID'],
+ 'status' => $payment['paymentStatus']
+ );
+
+ $next_payment_status = $payment['paymentStatus'];
+ }
+ }
+
+ if ($pending_flag) {
+ $start_index = $month + 1;
+ } else {
+ $start_index = $month + 2;
+ }
+
+ if ($month < $months) {
+ for ($month = 1; $month <= $months; $month++) {
+ $next_payment_date = date("Y-m-d h:i:s", strtotime($next_payment_date . " +1 month"));
+ $date = date($this->language->get('date_format_short'), strtotime($next_payment_date));
+
+ $report_content[] = array(
+ 'instalment' => $month,
+ 'amount' => $this->currency->format($transaction['payment_amounts'], $transaction['currency']),
+ 'date' => $date,
+ 'pp_trans_id' => '',
+ 'status' => $next_payment_status
+ );
+ }
+ }
+
+ $report_content = json_encode($report_content);
+
+ switch ($status) {
+ case -1: // Cancel
+ $this->model_extension_payment_laybuy->log('Transaction #' . $transaction['laybuy_transaction_id'] . ' canceled');
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_laybuy_order_status_id_canceled'), $this->language->get('text_comment'), false, false);
+ $this->model_extension_payment_laybuy->updateTransaction($transaction['laybuy_transaction_id'], '7', $report_content, $start_index);
+ break;
+ case 0: // Pending
+ $this->model_extension_payment_laybuy->log('Transaction #' . $transaction['laybuy_transaction_id'] . ' still pending');
+ $this->model_extension_payment_laybuy->updateTransaction($transaction['laybuy_transaction_id'], $transaction['status'], $report_content, $start_index);
+ break;
+ case 1: // Paid
+ $this->model_extension_payment_laybuy->log('Transaction #' . $transaction['laybuy_transaction_id'] . ' paid');
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_laybuy_order_status_id_processing'), $this->language->get('text_comment'), false, false);
+ $this->model_extension_payment_laybuy->updateTransaction($transaction['laybuy_transaction_id'], '5', $report_content, $start_index);
+ break;
+ }
+ }
+ }
+ } else {
+ $this->model_extension_payment_laybuy->log('No PayPal Profile IDs to update');
+ }
+
+ $this->model_extension_payment_laybuy->updateCronRunTime();
+ } else {
+ $this->model_extension_payment_laybuy->log('Token does not match.');
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/liqpay.php b/public/catalog/controller/extension/payment/liqpay.php
new file mode 100644
index 0000000..a2c7171
--- /dev/null
+++ b/public/catalog/controller/extension/payment/liqpay.php
@@ -0,0 +1,46 @@
+<?php
+class ControllerExtensionPaymentLiqPay extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['action'] = 'https://liqpay.com/?do=clickNbuy';
+
+ $xml = '<request>';
+ $xml .= ' <version>1.2</version>';
+ $xml .= ' <result_url>' . $this->url->link('checkout/success', '', true) . '</result_url>';
+ $xml .= ' <server_url>' . $this->url->link('extension/payment/liqpay/callback', '', true) . '</server_url>';
+ $xml .= ' <merchant_id>' . $this->config->get('payment_liqpay_merchant') . '</merchant_id>';
+ $xml .= ' <order_id>' . $this->session->data['order_id'] . '</order_id>';
+ $xml .= ' <amount>' . $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) . '</amount>';
+ $xml .= ' <currency>' . $order_info['currency_code'] . '</currency>';
+ $xml .= ' <description>' . $this->config->get('config_name') . ' ' . $order_info['payment_firstname'] . ' ' . $order_info['payment_address_1'] . ' ' . $order_info['payment_address_2'] . ' ' . $order_info['payment_city'] . ' ' . $order_info['email'] . '</description>';
+ $xml .= ' <default_phone></default_phone>';
+ $xml .= ' <pay_way>' . $this->config->get('payment_liqpay_type') . '</pay_way>';
+ $xml .= '</request>';
+
+ $data['xml'] = base64_encode($xml);
+ $data['signature'] = base64_encode(sha1($this->config->get('payment_liqpay_signature') . $xml . $this->config->get('payment_liqpay_signature'), true));
+
+ return $this->load->view('extension/payment/liqpay', $data);
+ }
+
+ public function callback() {
+ $xml = base64_decode($this->request->post['operation_xml']);
+ $signature = base64_encode(sha1($this->config->get('payment_liqpay_signature') . $xml . $this->config->get('payment_liqpay_signature'), true));
+
+ $posleft = strpos($xml, 'order_id');
+ $posright = strpos($xml, '/order_id');
+
+ $order_id = substr($xml, $posleft + 9, $posright - $posleft - 10);
+
+ if ($signature == $this->request->post['signature']) {
+ $this->load->model('checkout/order');
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/nochex.php b/public/catalog/controller/extension/payment/nochex.php
new file mode 100644
index 0000000..7e42536
--- /dev/null
+++ b/public/catalog/controller/extension/payment/nochex.php
@@ -0,0 +1,125 @@
+<?php
+// Nochex via form will work for both simple "Seller" account and "Merchant" account holders
+// Nochex via APC maybe only avaiable to "Merchant" account holders only - site docs a bit vague on this point
+class ControllerExtensionPaymentNochex extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/nochex');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['action'] = 'https://secure.nochex.com/';
+
+ // Nochex minimum requirements
+ // The merchant ID is usually your Nochex registered email address but can be altered for "Merchant" accounts see below
+ if ($this->config->get('payment_nochex_email') != $this->config->get('payment_nochex_merchant')) {
+ // This MUST be changed on your Nochex account!!!!
+ $data['merchant_id'] = $this->config->get('payment_nochex_merchant');
+ } else {
+ $data['merchant_id'] = $this->config->get('payment_nochex_email');
+ }
+
+ $data['amount'] = $this->currency->format($order_info['total'], 'GBP', false, false);
+ $data['order_id'] = $this->session->data['order_id'];
+ $data['description'] = $this->config->get('config_name');
+
+ $data['billing_fullname'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+
+ if ($order_info['payment_address_2']) {
+ $data['billing_address'] = $order_info['payment_address_1'] . "\r\n" . $order_info['payment_address_2'] . "\r\n" . $order_info['payment_city'] . "\r\n" . $order_info['payment_zone'] . "\r\n";
+ } else {
+ $data['billing_address'] = $order_info['payment_address_1'] . "\r\n" . $order_info['payment_city'] . "\r\n" . $order_info['payment_zone'] . "\r\n";
+ }
+
+ $data['billing_postcode'] = $order_info['payment_postcode'];
+
+ if ($this->cart->hasShipping()) {
+ $data['delivery_fullname'] = $order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname'];
+
+ if ($order_info['shipping_address_2']) {
+ $data['delivery_address'] = $order_info['shipping_address_1'] . "\r\n" . $order_info['shipping_address_2'] . "\r\n" . $order_info['shipping_city'] . "\r\n" . $order_info['shipping_zone'] . "\r\n";
+ } else {
+ $data['delivery_address'] = $order_info['shipping_address_1'] . "\r\n" . $order_info['shipping_city'] . "\r\n" . $order_info['shipping_zone'] . "\r\n";
+ }
+
+ $data['delivery_postcode'] = $order_info['shipping_postcode'];
+ } else {
+ $data['delivery_fullname'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+
+ if ($order_info['payment_address_2']) {
+ $data['delivery_address'] = $order_info['payment_address_1'] . "\r\n" . $order_info['payment_address_2'] . "\r\n" . $order_info['payment_city'] . "\r\n" . $order_info['payment_zone'] . "\r\n";
+ } else {
+ $data['delivery_address'] = $order_info['shipping_address_1'] . "\r\n" . $order_info['payment_city'] . "\r\n" . $order_info['payment_zone'] . "\r\n";
+ }
+
+ $data['delivery_postcode'] = $order_info['payment_postcode'];
+ }
+
+ $data['email_address'] = $order_info['email'];
+ $data['customer_phone_number']= $order_info['telephone'];
+ $data['test'] = $this->config->get('payment_nochex_test');
+ $data['success_url'] = $this->url->link('checkout/success', '', true);
+ $data['cancel_url'] = $this->url->link('checkout/payment', '', true);
+ $data['declined_url'] = $this->url->link('extension/payment/nochex/callback', 'method=decline', true);
+ $data['callback_url'] = $this->url->link('extension/payment/nochex/callback', 'order=' . $this->session->data['order_id'], true);
+
+ return $this->load->view('extension/payment/nochex', $data);
+ }
+
+ public function callback() {
+ $this->load->language('extension/payment/nochex');
+
+ if (isset($this->request->get['method']) && $this->request->get['method'] == 'decline') {
+ $this->session->data['error'] = $this->language->get('error_declined');
+
+ $this->response->redirect($this->url->link('checkout/cart'));
+ }
+
+ if (isset($this->request->post['order_id'])) {
+ $order_id = $this->request->post['order_id'];
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if (!$order_info) {
+ $this->session->data['error'] = $this->language->get('error_no_order');
+
+ $this->response->redirect($this->url->link('checkout/cart'));
+ }
+
+ // Fraud Verification Step.
+ $request = '';
+
+ foreach ($this->request->post as $key => $value) {
+ $request .= '&' . $key . '=' . urlencode(stripslashes($value));
+ }
+
+ $curl = curl_init('https://www.nochex.com/nochex.dll/apc/apc');
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, trim($request, '&'));
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ if (strcmp($response, 'AUTHORISED') == 0) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_nochex_order_status_id'));
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'), 'Auto-Verification step failed. Manually check the transaction.');
+ }
+
+ // Since it returned, the customer should see success.
+ // It's up to the store owner to manually verify payment.
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/paymate.php b/public/catalog/controller/extension/payment/paymate.php
new file mode 100644
index 0000000..e35ae3a
--- /dev/null
+++ b/public/catalog/controller/extension/payment/paymate.php
@@ -0,0 +1,105 @@
+<?php
+class ControllerExtensionPaymentPaymate extends Controller {
+ public function index() {
+ if (!$this->config->get('payment_paymate_test')) {
+ $data['action'] = 'https://www.paymate.com/PayMate/ExpressPayment';
+ } else {
+ $data['action'] = 'https://www.paymate.com.au/PayMate/TestExpressPayment';
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['mid'] = $this->config->get('payment_paymate_username');
+ $data['amt'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+
+ $data['currency'] = $order_info['currency_code'];
+ $data['ref'] = $order_info['order_id'];
+
+ $data['pmt_sender_email'] = $order_info['email'];
+ $data['pmt_contact_firstname'] = $order_info['payment_firstname'];
+ $data['pmt_contact_surname'] = $order_info['payment_lastname'];
+ $data['pmt_contact_phone'] = $order_info['telephone'];
+ $data['pmt_country'] = $order_info['payment_iso_code_2'];
+
+ $data['regindi_address1'] = $order_info['payment_address_1'];
+ $data['regindi_address2'] = $order_info['payment_address_2'];
+ $data['regindi_sub'] = $order_info['payment_city'];
+ $data['regindi_state'] = $order_info['payment_zone'];
+ $data['regindi_pcode'] = $order_info['payment_postcode'];
+
+ $data['return'] = $this->url->link('extension/payment/paymate/callback', 'hash=' . md5($order_info['order_id'] . $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) . $order_info['currency_code'] . $this->config->get('payment_paymate_password')));
+
+ return $this->load->view('extension/payment/paymate', $data);
+ }
+
+ public function callback() {
+ $this->load->language('extension/payment/paymate');
+
+ if (isset($this->request->post['ref'])) {
+ $order_id = $this->request->post['ref'];
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $error = '';
+
+ if (!isset($this->request->post['responseCode']) || !isset($this->request->get['hash'])) {
+ $error = $this->language->get('text_unable');
+ } elseif ($this->request->get['hash'] != md5($order_info['order_id'] . $this->currency->format($this->request->post['paymentAmount'], $this->request->post['currency'], 1.0000000, false) . $this->request->post['currency'] . $this->config->get('payment_paymate_password'))) {
+ $error = $this->language->get('text_unable');
+ } elseif ($this->request->post['responseCode'] != 'PA' && $this->request->post['responseCode'] != 'PP') {
+ $error = $this->language->get('text_declined');
+ }
+ } else {
+ $error = $this->language->get('text_unable');
+ }
+
+ if ($error) {
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_basket'),
+ 'href' => $this->url->link('checkout/cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_checkout'),
+ 'href' => $this->url->link('checkout/checkout', '', true)
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_failed'),
+ 'href' => $this->url->link('checkout/success')
+ );
+
+ $data['text_message'] = sprintf($this->language->get('text_failed_message'), $error, $this->url->link('information/contact'));
+
+ $data['continue'] = $this->url->link('common/home');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('common/success', $data));
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_paymate_order_status_id'));
+
+ $this->response->redirect($this->url->link('checkout/success'));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/paypoint.php b/public/catalog/controller/extension/payment/paypoint.php
new file mode 100644
index 0000000..06f7a92
--- /dev/null
+++ b/public/catalog/controller/extension/payment/paypoint.php
@@ -0,0 +1,161 @@
+<?php
+class ControllerExtensionPaymentPaypoint extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['merchant'] = $this->config->get('payment_paypoint_merchant');
+ $data['trans_id'] = $this->session->data['order_id'];
+ $data['amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+
+ if ($this->config->get('payment_paypoint_password')) {
+ $data['digest'] = md5($this->session->data['order_id'] . $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) . $this->config->get('payment_paypoint_password'));
+ } else {
+ $data['digest'] = '';
+ }
+
+ $data['bill_name'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+ $data['bill_addr_1'] = $order_info['payment_address_1'];
+ $data['bill_addr_2'] = $order_info['payment_address_2'];
+ $data['bill_city'] = $order_info['payment_city'];
+ $data['bill_state'] = $order_info['payment_zone'];
+ $data['bill_post_code'] = $order_info['payment_postcode'];
+ $data['bill_country'] = $order_info['payment_country'];
+ $data['bill_tel'] = $order_info['telephone'];
+ $data['bill_email'] = $order_info['email'];
+
+ if ($this->cart->hasShipping()) {
+ $data['ship_name'] = $order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname'];
+ $data['ship_addr_1'] = $order_info['shipping_address_1'];
+ $data['ship_addr_2'] = $order_info['shipping_address_2'];
+ $data['ship_city'] = $order_info['shipping_city'];
+ $data['ship_state'] = $order_info['shipping_zone'];
+ $data['ship_post_code'] = $order_info['shipping_postcode'];
+ $data['ship_country'] = $order_info['shipping_country'];
+ } else {
+ $data['ship_name'] = '';
+ $data['ship_addr_1'] = '';
+ $data['ship_addr_2'] = '';
+ $data['ship_city'] = '';
+ $data['ship_state'] = '';
+ $data['ship_post_code'] = '';
+ $data['ship_country'] = '';
+ }
+
+ $data['currency'] = $this->session->data['currency'];
+ $data['callback'] = $this->url->link('extension/payment/paypoint/callback', '', true);
+
+ switch ($this->config->get('payment_paypoint_test')) {
+ case 'live':
+ $status = 'live';
+ break;
+ case 'successful':
+ default:
+ $status = 'true';
+ break;
+ case 'fail':
+ $status = 'false';
+ break;
+ }
+
+ $data['options'] = 'test_status=' . $status . ',dups=false,cb_post=false';
+
+ return $this->load->view('extension/payment/paypoint', $data);
+ }
+
+ public function callback() {
+ if (isset($this->request->get['trans_id'])) {
+ $order_id = $this->request->get['trans_id'];
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ // Validate the request is from PayPoint
+ if ($this->config->get('payment_paypoint_password')) {
+ if (!empty($this->request->get['hash'])) {
+ $status = ($this->request->get['hash'] == md5(str_replace('hash=' . $this->request->get['hash'], '', htmlspecialchars_decode($this->request->server['REQUEST_URI'], ENT_COMPAT)) . $this->config->get('payment_paypoint_password')));
+ } else {
+ $status = false;
+ }
+ } else {
+ $status = true;
+ }
+
+ if ($order_info) {
+ $this->load->language('extension/payment/paypoint');
+
+ $data['title'] = sprintf($this->language->get('heading_title'), $this->config->get('config_name'));
+
+ if (!$this->request->server['HTTPS']) {
+ $data['base'] = HTTP_SERVER;
+ } else {
+ $data['base'] = HTTPS_SERVER;
+ }
+
+ $data['language'] = $this->language->get('code');
+ $data['direction'] = $this->language->get('direction');
+
+ $data['heading_title'] = sprintf($this->language->get('heading_title'), $this->config->get('config_name'));
+
+ $data['text_success_wait'] = sprintf($this->language->get('text_success_wait'), $this->url->link('checkout/success'));
+ $data['text_failure_wait'] = sprintf($this->language->get('text_failure_wait'), $this->url->link('checkout/cart'));
+
+ if (isset($this->request->get['code']) && $this->request->get['code'] == 'A' && $status) {
+ $message = '';
+
+ if (isset($this->request->get['code'])) {
+ $message .= 'code: ' . $this->request->get['code'] . "\n";
+ }
+
+ if (isset($this->request->get['auth_code'])) {
+ $message .= 'auth_code: ' . $this->request->get['auth_code'] . "\n";
+ }
+
+ if (isset($this->request->get['ip'])) {
+ $message .= 'ip: ' . $this->request->get['ip'] . "\n";
+ }
+
+ if (isset($this->request->get['cv2avs'])) {
+ $message .= 'cv2avs: ' . $this->request->get['cv2avs'] . "\n";
+ }
+
+ if (isset($this->request->get['valid'])) {
+ $message .= 'valid: ' . $this->request->get['valid'] . "\n";
+ }
+
+ $this->load->model('checkout/order');
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_paypoint_order_status_id'), $message, false);
+
+ $data['continue'] = $this->url->link('checkout/success');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/paypoint_success', $data));
+ } else {
+ $data['continue'] = $this->url->link('checkout/cart');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/paypoint_failure', $data));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/payza.php b/public/catalog/controller/extension/payment/payza.php
new file mode 100644
index 0000000..15b3434
--- /dev/null
+++ b/public/catalog/controller/extension/payment/payza.php
@@ -0,0 +1,31 @@
+<?php
+class ControllerExtensionPaymentPayza extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['action'] = 'https://secure.payza.com/checkout';
+
+ $data['ap_merchant'] = $this->config->get('payment_payza_merchant');
+ $data['ap_amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['ap_currency'] = $order_info['currency_code'];
+ $data['ap_purchasetype'] = 'Item';
+ $data['ap_itemname'] = $this->config->get('config_name') . ' - #' . $this->session->data['order_id'];
+ $data['ap_itemcode'] = $this->session->data['order_id'];
+ $data['ap_returnurl'] = $this->url->link('checkout/success');
+ $data['ap_cancelurl'] = $this->url->link('checkout/checkout', '', true);
+
+ return $this->load->view('extension/payment/payza', $data);
+ }
+
+ public function callback() {
+ if (isset($this->request->post['ap_securitycode']) && ($this->request->post['ap_securitycode'] == $this->config->get('payment_payza_security'))) {
+ $this->load->model('checkout/order');
+
+ $this->model_checkout_order->addOrderHistory($this->request->post['ap_itemcode'], $this->config->get('payment_payza_order_status_id'));
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/perpetual_payments.php b/public/catalog/controller/extension/payment/perpetual_payments.php
new file mode 100644
index 0000000..a0cb9f5
--- /dev/null
+++ b/public/catalog/controller/extension/payment/perpetual_payments.php
@@ -0,0 +1,115 @@
+<?php
+class ControllerExtensionPaymentPerpetualPayments extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/perpetual_payments');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_valid'] = array();
+
+ for ($i = $today['year'] - 10; $i < $today['year'] + 1; $i++) {
+ $data['year_valid'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/perpetual_payments', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/perpetual_payments');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $payment_data = array(
+ 'auth_id' => $this->config->get('payment_perpetual_payments_auth_id'),
+ 'auth_pass' => $this->config->get('payment_perpetual_payments_auth_pass'),
+ 'card_num' => str_replace(' ', '', $this->request->post['cc_number']),
+ 'card_cvv' => $this->request->post['cc_cvv2'],
+ 'card_start' => $this->request->post['cc_start_date_month'] . substr($this->request->post['cc_start_date_year'], 2),
+ 'card_expiry' => $this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], 2),
+ 'cust_name' => $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'],
+ 'cust_address' => $order_info['payment_address_1'] . ' ' . $order_info['payment_city'],
+ 'cust_country' => $order_info['payment_iso_code_2'],
+ 'cust_postcode' => $order_info['payment_postcode'],
+ 'cust_tel' => $order_info['telephone'],
+ 'cust_ip' => $this->request->server['REMOTE_ADDR'],
+ 'cust_email' => $order_info['email'],
+ 'tran_ref' => $order_info['order_id'],
+ 'tran_amount' => $this->currency->format($order_info['total'], $order_info['currency_code'], 1.00000, false),
+ 'tran_currency' => $order_info['currency_code'],
+ 'tran_testmode' => $this->config->get('payment_perpetual_payments_test'),
+ 'tran_type' => 'Sale',
+ 'tran_class' => 'MoTo',
+ );
+
+ $curl = curl_init('https://secure.voice-pay.com/gateway/remote');
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($payment_data));
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ if ($response) {
+ $data = explode('|', $response);
+
+ if (isset($data[0]) && $data[0] == 'A') {
+ $message = '';
+
+ if (isset($data[1])) {
+ $message .= $this->language->get('text_transaction') . ' ' . $data[1] . "\n";
+ }
+
+ if (isset($data[2])) {
+ if ($data[2] == '232') {
+ $message .= $this->language->get('text_avs') . ' ' . $this->language->get('text_avs_full_match') . "\n";
+ } elseif ($data[2] == '400') {
+ $message .= $this->language->get('text_avs') . ' ' . $this->language->get('text_avs_not_match') . "\n";
+ }
+ }
+
+ if (isset($data[3])) {
+ $message .= $this->language->get('text_authorisation') . ' ' . $data[3] . "\n";
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_perpetual_payments_order_status_id'), $message, false);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ } else {
+ $json['error'] = end($data);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pilibaba.php b/public/catalog/controller/extension/payment/pilibaba.php
new file mode 100644
index 0000000..ae7829a
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pilibaba.php
@@ -0,0 +1,416 @@
+<?php
+class ControllerExtensionPaymentPilibaba extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/pilibaba');
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pilibaba');
+
+ $this->model_extension_payment_pilibaba->log('Regular called');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['version'] = 'V2.0.01';
+ $data['merchantNo'] = $this->config->get('payment_pilibaba_merchant_number');
+ $data['currencyType'] = $order_info['currency_code'];
+ $data['orderNo'] = $order_info['order_id'];
+ $data['orderAmount'] = intval(round($order_info['total'], 2) * 100);
+ $data['orderTime'] = date('Y-m-d H:i:s');
+ $data['pageUrl'] = $this->url->link('checkout/checkout', '', true);
+ $data['serverUrl'] = $this->url->link('extension/payment/pilibaba/callback', '', true);
+ $data['redirectUrl'] = $this->url->link('checkout/success', '', true);
+ $data['notifyType'] = 'json';
+ $data['shipper'] = 0;
+ $data['tax'] = ($this->config->get('config_tax')) ? 0 : $this->model_extension_payment_pilibaba->getOrderTaxAmount($order_info['order_id']);
+ $data['signType'] = 'MD5';
+ $data['signMsg'] = strtoupper(md5($data['version'] . $data['merchantNo'] . $data['currencyType'] . $data['orderNo'] . $data['orderAmount'] . $data['orderTime'] . $data['pageUrl'] . $data['serverUrl'] . $data['redirectUrl'] . $data['notifyType'] . $data['shipper'] . $data['tax'] . $data['signType'] . $this->config->get('payment_pilibaba_secret_key')));
+
+ $products = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ // kilograms
+ if ($product['weight_class_id'] == '1') {
+ $weight = intval(round($product['weight'], 2) * 1000);
+ } else {
+ $weight = intval($product['weight']);
+ }
+
+ $products[] = array_map('strval', array(
+ 'name' => $product['name'],
+ 'pictureUrl' => $this->config->get('config_url') . 'image/' . $product['image'],
+ 'price' => intval(round($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'), $this->session->data['currency']), 2) * 100),
+ 'productUrl' => str_replace('&amp;', '&', $this->url->link('product/product', 'product_id=' . $product['product_id'])),
+ 'productId' => $product['product_id'],
+ 'quantity' => $product['quantity'],
+ 'weight' => $weight
+ ));
+ }
+
+ $data['products'] = $products;
+
+ $data['goodsList'] = urlencode(json_encode($products));
+
+ if ($this->config->get('payment_pilibaba_environment') == 'live') {
+ $data['url'] = 'https://www.pilibaba.com/pilipay/payreq';
+ } else {
+ $data['url'] = 'http://pre.pilibaba.com/pilipay/payreq';
+ }
+
+ $data['auto_submit'] = false;
+
+ $this->model_extension_payment_pilibaba->log('Request: ' . print_r($data, true));
+
+ return $this->load->view('extension/payment/pilibaba', $data);
+ }
+
+ public function express() {
+ $this->load->language('extension/shipping/pilibaba');
+
+ $this->load->language('extension/payment/pilibaba');
+
+ $this->load->model('extension/payment/pilibaba');
+
+ $this->model_extension_payment_pilibaba->log('Express called');
+
+ if ($this->config->get('payment_pilibaba_status')) {
+ if (!$this->cart->hasProducts() || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->model_extension_payment_pilibaba->log('No physical products. Redirecting to checkout/cart');
+
+ $this->response->redirect($this->url->link('checkout/cart'));
+ } else {
+ $order_data = array();
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $order_data['totals'] = $totals;
+
+ $this->load->language('checkout/checkout');
+
+ $order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
+ $order_data['store_id'] = $this->config->get('config_store_id');
+ $order_data['store_name'] = $this->config->get('config_name');
+
+ if ($order_data['store_id']) {
+ $order_data['store_url'] = $this->config->get('config_url');
+ } else {
+ $order_data['store_url'] = HTTP_SERVER;
+ }
+
+ $order_data['customer_id'] = 0;
+ $order_data['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $order_data['firstname'] = '';
+ $order_data['lastname'] = '';
+ $order_data['email'] = '';
+ $order_data['telephone'] = '';
+ $order_data['custom_field'] = null;
+
+ $order_data['payment_firstname'] = '';
+ $order_data['payment_lastname'] = '';
+ $order_data['payment_company'] = '';
+ $order_data['payment_address_1'] = '';
+ $order_data['payment_address_2'] = '';
+ $order_data['payment_city'] = '';
+ $order_data['payment_postcode'] = '';
+ $order_data['payment_zone'] = '';
+ $order_data['payment_zone_id'] = 0;
+ $order_data['payment_country'] = '';
+ $order_data['payment_country_id'] = 0;
+ $order_data['payment_address_format'] = '';
+ $order_data['payment_custom_field'] = array();
+ $order_data['payment_method'] = $this->language->get('text_title');
+ $order_data['payment_code'] = 'pilibaba';
+
+ $order_data['shipping_firstname'] = '';
+ $order_data['shipping_lastname'] = '';
+ $order_data['shipping_company'] = '';
+ $order_data['shipping_address_1'] = '';
+ $order_data['shipping_address_2'] = '';
+ $order_data['shipping_city'] = '';
+ $order_data['shipping_postcode'] = '';
+ $order_data['shipping_zone'] = '';
+ $order_data['shipping_zone_id'] = 0;
+ $order_data['shipping_country'] = '';
+ $order_data['shipping_country_id'] = 0;
+ $order_data['shipping_address_format'] = '';
+ $order_data['shipping_custom_field'] = array();
+ $order_data['shipping_method'] = $this->language->get('text_description');
+ $order_data['shipping_code'] = 'pilibaba.pilibaba';
+
+ $this->session->data['guest']['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $this->session->data['guest']['firstname'] = '';
+ $this->session->data['guest']['lastname'] = '';
+ $this->session->data['guest']['email'] = '';
+ $this->session->data['guest']['telephone'] = '';
+ $this->session->data['guest']['custom_field'] = array();
+
+ $order_data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ $option_data[] = array(
+ 'product_option_id' => $option['product_option_id'],
+ 'product_option_value_id' => $option['product_option_value_id'],
+ 'option_id' => $option['option_id'],
+ 'option_value_id' => $option['option_value_id'],
+ 'name' => $option['name'],
+ 'value' => $option['value'],
+ 'type' => $option['type']
+ );
+ }
+
+ $order_data['products'][] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'download' => $product['download'],
+ 'quantity' => $product['quantity'],
+ 'subtract' => $product['subtract'],
+ 'price' => $product['price'],
+ 'total' => $product['total'],
+ 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
+ 'reward' => $product['reward']
+ );
+ }
+
+ // Gift Voucher
+ $order_data['vouchers'] = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $voucher) {
+ $order_data['vouchers'][] = array(
+ 'description' => $voucher['description'],
+ 'code' => token(10),
+ 'to_name' => $voucher['to_name'],
+ 'to_email' => $voucher['to_email'],
+ 'from_name' => $voucher['from_name'],
+ 'from_email' => $voucher['from_email'],
+ 'voucher_theme_id' => $voucher['voucher_theme_id'],
+ 'message' => $voucher['message'],
+ 'amount' => $voucher['amount']
+ );
+ }
+ }
+
+ $order_data['comment'] = '';
+ $order_data['total'] = $total_data['total'];
+
+ if (isset($this->request->cookie['tracking'])) {
+ $order_data['tracking'] = $this->request->cookie['tracking'];
+
+ $subtotal = $this->cart->getSubTotal();
+
+ // Affiliate
+ $this->load->model('affiliate/affiliate');
+
+ $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
+
+ if ($affiliate_info) {
+ $order_data['affiliate_id'] = $affiliate_info['affiliate_id'];
+ $order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ }
+
+ // Marketing
+ $this->load->model('checkout/marketing');
+
+ $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
+
+ if ($marketing_info) {
+ $order_data['marketing_id'] = $marketing_info['marketing_id'];
+ } else {
+ $order_data['marketing_id'] = 0;
+ }
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ $order_data['marketing_id'] = 0;
+ $order_data['tracking'] = '';
+ }
+
+ $order_data['language_id'] = $this->config->get('config_language_id');
+ $order_data['currency_id'] = $this->currency->getId($this->session->data['currency']);
+ $order_data['currency_code'] = $this->session->data['currency'];
+ $order_data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
+ $order_data['ip'] = $this->request->server['REMOTE_ADDR'];
+
+ if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
+ } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
+ } else {
+ $order_data['forwarded_ip'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $order_data['user_agent'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
+ $order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
+ } else {
+ $order_data['accept_language'] = '';
+ }
+
+ $this->load->model('checkout/order');
+
+ $this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['version'] = 'V2.0.01';
+ $data['merchantNo'] = $this->config->get('payment_pilibaba_merchant_number');
+ $data['currencyType'] = $order_info['currency_code'];
+ $data['orderNo'] = $order_info['order_id'];
+ $data['orderAmount'] = intval(round($order_info['total'], 2) * 100);
+ $data['orderTime'] = date('Y-m-d H:i:s');
+ $data['pageUrl'] = $this->url->link('checkout/checkout', '', true);
+ $data['serverUrl'] = $this->url->link('extension/payment/pilibaba/callback', '', true);
+ $data['redirectUrl'] = $this->url->link('checkout/success', '', true);
+ $data['notifyType'] = 'json';
+ $data['shipper'] = intval(round($this->config->get('payment_pilibaba_shipping_fee'), 2) * 100);
+ $data['tax'] = ($this->config->get('config_tax')) ? 0 : $this->model_extension_payment_pilibaba->getOrderTaxAmount($order_info['order_id']);
+ $data['signType'] = 'MD5';
+ $data['signMsg'] = strtoupper(md5($data['version'] . $data['merchantNo'] . $data['currencyType'] . $data['orderNo'] . $data['orderAmount'] . $data['orderTime'] . $data['pageUrl'] . $data['serverUrl'] . $data['redirectUrl'] . $data['notifyType'] . $data['shipper'] . $data['tax'] . $data['signType'] . $this->config->get('payment_pilibaba_secret_key')));
+
+ $products = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ // kilograms
+ if ($product['weight_class_id'] == '1') {
+ $weight = intval(round($product['weight'], 2) * 1000);
+ } else {
+ $weight = intval($product['weight']);
+ }
+
+ $products[] = array_map('strval', array(
+ 'name' => $product['name'],
+ 'pictureUrl' => $this->config->get('config_url') . 'image/' . $product['image'],
+ 'price' => intval(round($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'), $this->session->data['currency']), 2) * 100),
+ 'productUrl' => str_replace('&amp;', '&', $this->url->link('product/product', 'product_id=' . $product['product_id'])),
+ 'productId' => $product['product_id'],
+ 'quantity' => $product['quantity'],
+ 'weight' => $weight
+ ));
+ }
+
+ $data['products'] = $products;
+
+ $data['goodsList'] = urlencode(json_encode($products));
+
+ if ($this->config->get('payment_pilibaba_environment') == 'live') {
+ $data['url'] = 'https://www.pilibaba.com/pilipay/payreq';
+ } else {
+ $data['url'] = 'http://pre.pilibaba.com/pilipay/payreq';
+ }
+
+ $data['text_redirecting'] = $this->language->get('text_redirecting');
+
+ $data['auto_submit'] = true;
+
+ $this->model_extension_payment_pilibaba->log('Request: ' . print_r($data, true));
+
+ $this->response->setOutput($this->load->view('extension/payment/pilibaba', $data));
+ }
+ } else {
+ $this->model_extension_payment_pilibaba->log('Module disabled');
+ }
+ }
+
+ public function callback() {
+ $this->load->language('extension/payment/pilibaba');
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pilibaba');
+
+ $this->model_extension_payment_pilibaba->log('Receiving callback');
+
+ $response_data = $this->request->get;
+
+ $this->model_extension_payment_pilibaba->log('Response: ' . print_r($response_data, true));
+
+ $sign_msg = strtoupper(md5($this->config->get('payment_pilibaba_merchant_number') . $response_data['orderNo'] . $response_data['orderAmount'] . 'MD5' . $response_data['fee'] . $response_data['orderTime'] . $response_data['customerMail'] . $this->config->get('payment_pilibaba_secret_key')));
+
+ $this->model_extension_payment_pilibaba->log('signMsg: ' . $sign_msg);
+
+ if (hash_equals($sign_msg, $response_data['signMsg'])) {
+ $this->model_extension_payment_pilibaba->log('Adding Pilibaba order');
+
+ $this->model_extension_payment_pilibaba->addPilibabaOrder($response_data);
+
+ $this->model_extension_payment_pilibaba->log('Pilibaba order added');
+
+ $this->model_extension_payment_pilibaba->log('Getting consumer info');
+
+ $consumer_info = $this->model_extension_payment_pilibaba->getConsumerInfo($response_data['orderNo']);
+
+ if (isset($consumer_info['message']) && $consumer_info['message'] == 'success') {
+ $this->model_extension_payment_pilibaba->log('Updating order info');
+
+ $this->model_extension_payment_pilibaba->updateOrderInfo($consumer_info, $response_data['orderNo']);
+
+ $this->model_extension_payment_pilibaba->log('Order info updated');
+
+ $this->model_extension_payment_pilibaba->log('Adding order history');
+
+ $this->model_checkout_order->addOrderHistory($response_data['orderNo'], $this->config->get('payment_pilibaba_order_status_id'));
+
+ $this->model_extension_payment_pilibaba->log('Order history added');
+ } else {
+ $this->model_extension_payment_pilibaba->log('Invalid consumer info response');
+ }
+
+ $this->model_extension_payment_pilibaba->log('Outputting "OK"');
+
+ echo 'OK';
+
+ $this->model_extension_payment_pilibaba->log('"OK" outputted');
+ } else {
+ $this->model_extension_payment_pilibaba->log('Invalid callback response');
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pp_braintree.php b/public/catalog/controller/extension/payment/pp_braintree.php
new file mode 100644
index 0000000..de2f965
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_braintree.php
@@ -0,0 +1,1635 @@
+<?php
+class ControllerExtensionPaymentPPBraintree extends Controller {
+ private $customer_id_prefix = 'braintree_oc_';
+ private $gateway = null;
+
+ public function index() {
+ $this->initialise();
+
+ $this->load->language('extension/payment/pp_braintree');
+
+ $data['payment_url'] = $this->url->link('extension/payment/pp_braintree/payment', '', true);
+ $data['vaulted_url'] = $this->url->link('extension/payment/pp_braintree/vaulted', '', true);
+
+ $data['payment_pp_braintree_3ds_status'] = $this->config->get('payment_pp_braintree_3ds_status');
+ $data['payment_pp_braintree_vault_cvv_3ds'] = $this->config->get('payment_pp_braintree_vault_cvv_3ds');
+ $data['payment_pp_braintree_paypal_option'] = $this->config->get('payment_pp_braintree_paypal_option');
+ $data['payment_pp_braintree_vault_cvv'] = $this->config->get('payment_pp_braintree_vault_cvv');
+ $data['payment_pp_braintree_settlement_immediate'] = $this->config->get('payment_pp_braintree_settlement_immediate');
+ $data['payment_pp_braintree_paypal_button_colour'] = $this->config->get('payment_pp_braintree_paypal_button_colour');
+ $data['payment_pp_braintree_paypal_button_size'] = $this->config->get('payment_pp_braintree_paypal_button_size');
+ $data['payment_pp_braintree_paypal_button_shape'] = $this->config->get('payment_pp_braintree_paypal_button_shape');
+
+ if (!$this->session->data['order_id']) {
+ return false;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $create_token = array();
+ $merchant_id = $this->config->get('payment_pp_braintree_merchant_id');
+
+ if ($this->gateway == '') {
+ $merchant_accounts = $this->config->get('payment_pp_braintree_account');
+
+ foreach ($merchant_accounts as $merchant_account_currency => $merchant_account) {
+ if (($merchant_account_currency == $order_info['currency_code']) && !empty($merchant_account['merchant_account_id'])) {
+ $create_token['merchantAccountId'] = $merchant_account['merchant_account_id'];
+
+ $merchant_id = $merchant_account['merchant_account_id'];
+
+ break;
+ }
+ }
+ }
+
+ $data['merchant_id'] = $merchant_id;
+
+ if ($this->customer->isLogged() && ($this->config->get('payment_pp_braintree_card_vault') || $this->config->get('payment_pp_braintree_paypal_vault'))) {
+ $data['payment_pp_braintree_card_vault'] = $this->config->get('payment_pp_braintree_card_vault');
+ $data['payment_pp_braintree_paypal_vault'] = $this->config->get('payment_pp_braintree_paypal_vault');
+ $data['payment_pp_braintree_card_check_vault'] = $this->config->get('payment_pp_braintree_card_check_vault');
+ $data['payment_pp_braintree_paypal_check_vault'] = $this->config->get('payment_pp_braintree_paypal_check_vault');
+ $vaulted_customer_info = $this->model_extension_payment_pp_braintree->getCustomer($this->gateway, $this->customer_id_prefix . $this->customer->getId(), false);
+ } else {
+ $data['payment_pp_braintree_card_vault'] = 0;
+ $data['payment_pp_braintree_paypal_vault'] = 0;
+ $data['payment_pp_braintree_card_check_vault'] = 0;
+ $data['payment_pp_braintree_paypal_check_vault'] = 0;
+ $vaulted_customer_info = false;
+ }
+
+ $data['client_token'] = $this->model_extension_payment_pp_braintree->generateToken($this->gateway, $create_token);
+ $data['total'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+
+ $data['currency_code'] = $order_info['currency_code'];
+
+ // disable paypal option if currency is not in supported array
+ if (!in_array($order_info['currency_code'], array('USD', 'EUR', 'GBP', 'CAD', 'AUD', 'DKK', 'NOK', 'PLN', 'SEK', 'CHF', 'TRY'))) {
+ $data['payment_pp_braintree_paypal_option'] = false;
+ }
+
+ // pass shipping info to paypal if set
+ if ($data['payment_pp_braintree_paypal_option'] && $this->cart->hasShipping()) {
+ $data['customer_shipping_address'] = array(
+ 'name' => addslashes($order_info['shipping_firstname']) . ' ' . addslashes($order_info['shipping_lastname']),
+ 'line_1' => addslashes($order_info['shipping_address_1']),
+ 'line_2' => addslashes($order_info['shipping_address_2']),
+ 'city' => addslashes($order_info['shipping_city']),
+ 'state' => addslashes($order_info['shipping_zone_code']),
+ 'post_code' => addslashes($order_info['shipping_postcode']),
+ 'country_code' => addslashes($order_info['shipping_iso_code_2']),
+ 'phone' => addslashes($order_info['telephone']),
+ );
+ }
+
+ $vaulted_payment_methods = array('cards', 'paypal');
+ $vaulted_payment_count = 0;
+
+ if ($vaulted_customer_info) {
+ $vaulted_card_count = 0;
+ $vaulted_paypal_count = 0;
+
+ if ($vaulted_customer_info->creditCards && $this->config->get('payment_pp_braintree_card_vault') == 1) {
+ $vaulted_card_count = count($vaulted_customer_info->creditCards);
+
+ foreach ($vaulted_customer_info->creditCards as $credit_card) {
+ $vaulted_payment_methods['cards'][] = array(
+ 'image' => $credit_card->imageUrl,
+ 'name' => sprintf($this->language->get('text_vaulted_payment_method_name'), $credit_card->cardType, $credit_card->last4, $credit_card->expirationDate),
+ 'token' => $credit_card->token,
+ 'expired' => $credit_card->expired,
+ 'default' => $credit_card->default
+ );
+ }
+ }
+
+ if ($vaulted_customer_info->paypalAccounts && $this->config->get('payment_pp_braintree_paypal_vault') == 1) {
+ $vaulted_paypal_count = count($vaulted_customer_info->paypalAccounts);
+
+ foreach ($vaulted_customer_info->paypalAccounts as $paypal_account) {
+ $vaulted_payment_methods['paypal'][] = array(
+ 'image' => $paypal_account->imageUrl,
+ 'name' => $paypal_account->email,
+ 'token' => $paypal_account->token,
+ 'default' => $paypal_account->default
+ );
+ }
+ }
+
+ $vaulted_payment_count = $vaulted_card_count + $vaulted_paypal_count;
+ }
+
+ $data['vaulted_payment_methods'] = $vaulted_payment_methods;
+ $data['vaulted_payment_count'] = $vaulted_payment_count;
+
+ $data['form_styles'] = json_encode("{
+ 'input': { 'font-size': '12px', 'font-family': 'Source Sans Pro, sans-serif', 'color': '#7A8494' },
+ 'input.invalid': { 'color': 'red' },
+ 'input.valid': { 'color': 'green' }
+ }");
+
+ if ($this->customer->isLogged()) {
+ $data['guest'] = false;
+ } else {
+ $data['guest'] = true;
+ }
+
+ return $this->load->view('extension/payment/pp_braintree', $data);
+ }
+
+ public function payment() {
+ //set_time_limit(120);
+
+ $this->initialise();
+
+ $this->load->language('extension/payment/pp_braintree');
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pp_braintree');
+
+ $this->model_extension_payment_pp_braintree->log('Starting payment');
+ $this->model_extension_payment_pp_braintree->log($this->request->post);
+
+ $success = true;
+
+ if (!$this->session->data['order_id']) {
+ $this->model_extension_payment_pp_braintree->log('Session data: order_id not found');
+
+ $success = false;
+ }
+
+ if (isset($this->request->post['device_data'])) {
+ $device_data = $this->request->post['device_data'];
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Post data: device_data not found');
+
+ $device_data = '';
+
+ $success = false;
+ }
+
+ if (isset($this->request->post['payment_method_token'])) {
+ $payment_method_token = $this->request->post['payment_method_token'];
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Post data: payment_method_token not found');
+ $payment_method_token = '';
+ }
+
+ if (isset($this->request->post['payment_method_nonce'])) {
+ $payment_method_nonce = $this->request->post['payment_method_nonce'];
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Post data: payment_method_nonce not found');
+ $payment_method_nonce = '';
+ }
+
+ if ($payment_method_nonce == '' && $payment_method_token == '') {
+ $success = false;
+ }
+
+ //Start creating transaction array
+ if ($success) {
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $create_sale = array(
+ 'amount' => $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false),
+ 'channel' => 'OpenCart_Cart_vzero',
+ 'orderId' => $order_info['order_id'],
+ 'deviceData' => $device_data,
+ 'customer' => array(
+ 'firstName' => $order_info['firstname'],
+ 'lastName' => $order_info['lastname'],
+ 'phone' => $order_info['telephone'],
+ 'email' => $order_info['email']
+ ),
+ 'billing' => array(
+ 'firstName' => $order_info['payment_firstname'],
+ 'lastName' => $order_info['payment_lastname'],
+ 'company' => $order_info['payment_company'],
+ 'streetAddress' => $order_info['payment_address_1'],
+ 'extendedAddress' => $order_info['payment_address_2'],
+ 'locality' => $order_info['payment_city'],
+ 'countryCodeAlpha2' => $order_info['payment_iso_code_2'],
+ 'postalCode' => $order_info['payment_postcode'],
+ 'region' => $order_info['payment_zone_code']
+ ),
+ 'options' => array('three_d_secure' => array('required' => false))
+ );
+
+ //Add shipping details
+ if ($this->cart->hasShipping()) {
+ $create_sale['shipping'] = array(
+ 'firstName' => $order_info['shipping_firstname'],
+ 'lastName' => $order_info['shipping_lastname'],
+ 'company' => $order_info['shipping_company'],
+ 'streetAddress' => $order_info['shipping_address_1'],
+ 'extendedAddress' => $order_info['shipping_address_2'],
+ 'locality' => $order_info['shipping_city'],
+ 'countryCodeAlpha2' => $order_info['shipping_iso_code_2'],
+ 'postalCode' => $order_info['shipping_postcode'],
+ 'region' => $order_info['shipping_zone_code']
+ );
+ }
+
+ if ($this->customer->isLogged() && ($this->config->get('payment_pp_braintree_card_vault') || $this->config->get('payment_pp_braintree_paypal_vault'))) {
+ $customer_id = $this->customer_id_prefix . $this->customer->getId();
+
+ $vaulted_customer_info = $this->model_extension_payment_pp_braintree->getCustomer($this->gateway, $customer_id, false);
+
+ if ($vaulted_customer_info) {
+ $create_sale['customerId'] = $customer_id;
+ } else {
+ $create_sale['customer']['id'] = $customer_id;
+ }
+
+ if (isset($this->request->post['vault_method']) && $this->request->post['vault_method'] == '1') {
+ $create_sale['options']['storeInVaultOnSuccess'] = true;
+ }
+ }
+
+ if ($payment_method_token != '') {
+ $create_sale['paymentMethodToken'] = $payment_method_token;
+
+ // unset the billing info for a vaulted payment
+ $create_sale['billing'] = array();
+ }
+
+ if ($payment_method_nonce != '') {
+ $create_sale['paymentMethodNonce'] = $payment_method_nonce;
+ }
+
+ if ($this->gateway == '') {
+ $merchant_accounts = $this->config->get('payment_pp_braintree_account');
+
+ foreach ($merchant_accounts as $merchant_account_currency => $merchant_account) {
+ if (($merchant_account_currency == $order_info['currency_code']) && !empty($merchant_account['merchant_account_id'])) {
+ $create_sale['merchantAccountId'] = $merchant_account['merchant_account_id'];
+ }
+ }
+ }
+
+ if ($this->config->get('payment_pp_braintree_settlement_immediate') == 1) {
+ $create_sale['options']['submitForSettlement'] = true;
+ } else {
+ $create_sale['options']['submitForSettlement'] = false;
+ }
+ }
+
+ // If the $payment_method_token is not empty it indicates the vaulted payment used CVV or was set to none
+ if ($success && (($this->config->get('payment_pp_braintree_3ds_status') == 1 && $payment_method_token == '') || ($this->config->get('payment_pp_braintree_vault_cvv_3ds') == '3ds' && $payment_method_token != ''))) {
+ $nonce_info = $this->model_extension_payment_pp_braintree->getPaymentMethodNonce($this->gateway, $payment_method_nonce);
+
+ $this->model_extension_payment_pp_braintree->log($nonce_info);
+
+ if ($nonce_info->type == 'CreditCard' && $this->config->get('payment_pp_braintree_3ds_status') == 1) {
+ $create_sale['options']['three_d_secure'] = array(
+ 'required' => true
+ );
+
+ $three_ds_info = array();
+
+ if (isset($nonce_info->threeDSecureInfo) && !empty($nonce_info->threeDSecureInfo)) {
+ $three_ds_info = $nonce_info->threeDSecureInfo;
+ }
+
+ if (!empty($three_ds_info)) {
+ $success = false;
+
+ switch ($three_ds_info->status) {
+ case 'unsupported_card':
+ if ($nonce_info->details['cardType'] == 'American Express') {
+ $success = true;
+ } else {
+ $success = $this->config->get('payment_pp_braintree_3ds_unsupported_card');
+ }
+ break;
+ case 'lookup_error':
+ $success = $this->config->get('payment_pp_braintree_3ds_lookup_error');
+ break;
+ case 'lookup_enrolled':
+ $success = $this->config->get('payment_pp_braintree_3ds_lookup_enrolled');
+ break;
+ case 'lookup_not_enrolled':
+ $success = $this->config->get('payment_pp_braintree_3ds_lookup_not_enrolled');
+ break;
+ case 'authenticate_successful_issuer_not_participating':
+ $success = $this->config->get('payment_pp_braintree_3ds_not_participating');
+ break;
+ case 'authentication_unavailable':
+ $success = $this->config->get('payment_pp_braintree_3ds_unavailable');
+ break;
+ case 'authenticate_signature_verification_failed':
+ $success = $this->config->get('payment_pp_braintree_3ds_signature_failed');
+ break;
+ case 'authenticate_successful':
+ $success = $this->config->get('payment_pp_braintree_3ds_successful');
+ break;
+ case 'authenticate_attempt_successful':
+ $success = $this->config->get('payment_pp_braintree_3ds_attempt_successful');
+ break;
+ case 'authenticate_failed':
+ $success = $this->config->get('payment_pp_braintree_3ds_failed');
+ break;
+ case 'authenticate_unable_to_authenticate':
+ $success = $this->config->get('payment_pp_braintree_3ds_unable_to_auth');
+ break;
+ case 'authenticate_error':
+ $success = $this->config->get('payment_pp_braintree_3ds_error');
+ break;
+ }
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Liability shift failed, nonce was not 3D Secured');
+
+ $success = false;
+ }
+ }
+ }
+ $this->model_extension_payment_pp_braintree->log("Success:" . (int)$success);
+
+ //Create transaction
+ if ($success) {
+ $transaction = $this->model_extension_payment_pp_braintree->addTransaction($this->gateway, $create_sale);
+
+ $order_status_id = 0;
+ switch ($transaction->transaction->status) {
+ case 'authorization_expired':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorization_expired_id');
+ break;
+ case 'authorized':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorized_id');
+ break;
+ case 'authorizing':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorizing_id');
+ break;
+ case 'settlement_pending':
+ $order_status_id = $this->config->get('payment_pp_braintree_settlement_pending_id');
+ break;
+ case 'failed':
+ $order_status_id = $this->config->get('payment_pp_braintree_failed_id');
+ break;
+ case 'gateway_rejected':
+ $order_status_id = $this->config->get('payment_pp_braintree_gateway_rejected_id');
+ break;
+ case 'processor_declined':
+ $order_status_id = $this->config->get('payment_pp_braintree_processor_declined_id');
+ break;
+ case 'settled':
+ $order_status_id = $this->config->get('payment_pp_braintree_settled_id');
+ break;
+ case 'settling':
+ $order_status_id = $this->config->get('payment_pp_braintree_settling_id');
+ break;
+ case 'submitted_for_settlement':
+ $order_status_id = $this->config->get('payment_pp_braintree_submitted_for_settlement_id');
+ break;
+ case 'voided':
+ $order_status_id = $this->config->get('payment_pp_braintree_voided_id');
+ break;
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $order_status_id);
+
+ if ($transaction->success) {
+ $this->model_extension_payment_pp_braintree->log('Transaction success, details below');
+ $this->model_extension_payment_pp_braintree->log($transaction);
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Transaction failed, details below');
+ $this->model_extension_payment_pp_braintree->log($transaction);
+
+ $this->session->data['error'] = $this->language->get('error_process_order');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ //If this is reached, transaction has failed
+ $this->model_extension_payment_pp_braintree->log('Transaction reached end of method without being handled, failure');
+
+ if (isset($this->session->data['order_id'])) {
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_pp_braintree_failed_id'));
+ }
+
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ public function nonce() {
+ $this->initialise();
+
+ $this->load->language('extension/payment/pp_braintree');
+
+ $this->load->model('extension/payment/pp_braintree');
+
+ $this->model_extension_payment_pp_braintree->log('Starting vaulted');
+ $this->model_extension_payment_pp_braintree->log($this->request->post);
+
+ $json = array();
+
+ $json['payment_method'] = '';
+
+ $success = true;
+
+ if (!isset($this->request->post['vaulted_payment_token'])) {
+ $success = false;
+ }
+
+ if ($success) {
+ $payment_method = $this->model_extension_payment_pp_braintree->createPaymentMethodNonce($this->gateway, $this->request->post['vaulted_payment_token']);
+
+ if ($payment_method && $payment_method->success) {
+ $json['payment_method'] = array(
+ 'type' => $payment_method->paymentMethodNonce->type,
+ 'nonce' => $payment_method->paymentMethodNonce->nonce
+ );
+ } else {
+ $success = false;
+ }
+ }
+
+ $json['success'] = $success;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function remove() {
+ $this->initialise();
+
+ $this->load->language('extension/payment/pp_braintree');
+
+ $this->load->model('extension/payment/pp_braintree');
+
+ $json = array();
+
+ $json['success'] = false;
+
+ if (isset($this->request->post['vaulted_payment_method'])) {
+ $vaulted_payment_method = $this->request->post['vaulted_payment_method'];
+ } else {
+ $vaulted_payment_method = '';
+ }
+
+ $delete_payment_method = $this->model_extension_payment_pp_braintree->deletePaymentMethod($this->gateway, $vaulted_payment_method);
+
+ if ($delete_payment_method) {
+ $json['success'] = $this->language->get('text_method_removed');
+ } else {
+ $json['error'] = $this->language->get('text_method_not_removed');
+ }
+
+ $vaulted_customer_info = $this->model_extension_payment_pp_braintree->getCustomer($this->gateway, $this->customer_id_prefix . $this->customer->getId());
+
+ $vaulted_card_count = 0;
+ $vaulted_paypal_count = 0;
+
+ if ($vaulted_customer_info->creditCards && $this->config->get('payment_pp_braintree_card_vault') == 1) {
+ $vaulted_card_count = count($vaulted_customer_info->creditCards);
+ }
+
+ if ($vaulted_customer_info->paypalAccounts && $this->config->get('payment_pp_braintree_paypal_vault') == 1) {
+ $vaulted_paypal_count = count($vaulted_customer_info->paypalAccounts);
+ }
+
+ $json['vaulted_payment_count'] = $vaulted_card_count + $vaulted_paypal_count;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function expressSetup() {
+ // check checkout can continue due to stock checks or vouchers
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $json = array();
+ $json['error'] = true;
+ $json['url'] = $this->url->link('checkout/cart');
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ // if user not logged in check that the guest checkout is allowed
+ if (!$this->customer->isLogged() && (!$this->config->get('config_checkout_guest') || $this->config->get('config_customer_price') || $this->cart->hasDownload() || $this->cart->hasRecurringProducts())) {
+ $json = array();
+ $json['error'] = true;
+ $json['url'] = $this->url->link('checkout/checkout');
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ } else {
+ unset($this->session->data['guest']);
+ }
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+
+ if (!$this->customer->isLogged()) {
+ $this->session->data['paypal_braintree']['guest'] = true;
+
+ $this->session->data['guest']['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $this->session->data['guest']['firstname'] = $this->request->post['details']['firstName'];
+ $this->session->data['guest']['lastname'] = $this->request->post['details']['lastName'];
+ $this->session->data['guest']['email'] = $this->request->post['details']['email'];
+
+ if (isset($this->request->post['details']['phone'])) {
+ $this->session->data['guest']['telephone'] = $this->request->post['details']['phone'];
+ } else {
+ $this->session->data['guest']['telephone'] = '';
+ }
+
+ $this->session->data['guest']['payment']['company'] = '';
+
+ $this->session->data['guest']['payment']['firstname'] = $this->request->post['details']['firstName'];
+ $this->session->data['guest']['payment']['lastname'] = $this->request->post['details']['lastName'];
+
+ $this->session->data['guest']['payment']['company_id'] = '';
+ $this->session->data['guest']['payment']['tax_id'] = '';
+
+ if ($this->cart->hasShipping()) {
+ $shipping_name = explode(' ', $this->request->post['details']['shippingAddress']['recipientName']);
+ $shipping_first_name = $shipping_name[0];
+ unset($shipping_name[0]);
+ $shipping_last_name = implode(' ', $shipping_name);
+
+ $this->session->data['guest']['payment']['address_1'] = $this->request->post['details']['shippingAddress']['line1'];
+ if (isset($this->request->post['details']['shippingAddress']['line2'])) {
+ $this->session->data['guest']['payment']['address_2'] = $this->request->post['details']['shippingAddress']['line2'];
+ } else {
+ $this->session->data['guest']['payment']['address_2'] = '';
+ }
+
+ $this->session->data['guest']['payment']['postcode'] = $this->request->post['details']['shippingAddress']['postalCode'];
+ $this->session->data['guest']['payment']['city'] = $this->request->post['details']['shippingAddress']['city'];
+
+ $this->session->data['guest']['shipping']['firstname'] = $shipping_first_name;
+ $this->session->data['guest']['shipping']['lastname'] = $shipping_last_name;
+ $this->session->data['guest']['shipping']['company'] = '';
+ $this->session->data['guest']['shipping']['address_1'] = $this->request->post['details']['shippingAddress']['line1'];
+
+ if (isset($this->request->post['details']['shippingAddress']['line2'])) {
+ $this->session->data['guest']['shipping']['address_2'] =$this->request->post['details']['shippingAddress']['line2'];
+ } else {
+ $this->session->data['guest']['shipping']['address_2'] = '';
+ }
+
+ $this->session->data['guest']['shipping']['postcode'] = $this->request->post['details']['shippingAddress']['postalCode'];
+ $this->session->data['guest']['shipping']['city'] = $this->request->post['details']['shippingAddress']['city'];
+
+ $this->session->data['shipping_postcode'] = $this->request->post['details']['shippingAddress']['postalCode'];
+
+ $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($this->request->post['details']['shippingAddress']['countryCode']) . "' AND `status` = '1' LIMIT 1")->row;
+
+ if ($country_info) {
+ $this->session->data['guest']['shipping']['country_id'] = $country_info['country_id'];
+ $this->session->data['guest']['shipping']['country'] = $country_info['name'];
+ $this->session->data['guest']['shipping']['iso_code_2'] = $country_info['iso_code_2'];
+ $this->session->data['guest']['shipping']['iso_code_3'] = $country_info['iso_code_3'];
+ $this->session->data['guest']['shipping']['address_format'] = $country_info['address_format'];
+ $this->session->data['guest']['payment']['country_id'] = $country_info['country_id'];
+ $this->session->data['guest']['payment']['country'] = $country_info['name'];
+ $this->session->data['guest']['payment']['iso_code_2'] = $country_info['iso_code_2'];
+ $this->session->data['guest']['payment']['iso_code_3'] = $country_info['iso_code_3'];
+ $this->session->data['guest']['payment']['address_format'] = $country_info['address_format'];
+ $this->session->data['shipping_country_id'] = $country_info['country_id'];
+
+ if (isset($this->request->post['details']['shippingAddress']['state'])) {
+ $returned_shipping_zone = $this->request->post['details']['shippingAddress']['state'];
+ } else {
+ $returned_shipping_zone = '';
+ }
+
+ $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($returned_shipping_zone) . "' OR `code` = '" . $this->db->escape($returned_shipping_zone) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "' LIMIT 1")->row;
+ } else {
+ $this->session->data['guest']['shipping']['country_id'] = '';
+ $this->session->data['guest']['shipping']['country'] = '';
+ $this->session->data['guest']['shipping']['iso_code_2'] = '';
+ $this->session->data['guest']['shipping']['iso_code_3'] = '';
+ $this->session->data['guest']['shipping']['address_format'] = '';
+ $this->session->data['guest']['payment']['country_id'] = '';
+ $this->session->data['guest']['payment']['country'] = '';
+ $this->session->data['guest']['payment']['iso_code_2'] = '';
+ $this->session->data['guest']['payment']['iso_code_3'] = '';
+ $this->session->data['guest']['payment']['address_format'] = '';
+ $this->session->data['shipping_country_id'] = '';
+
+ $zone_info = array();
+ }
+
+ if ($zone_info) {
+ $this->session->data['guest']['shipping']['zone'] = $zone_info['name'];
+ $this->session->data['guest']['shipping']['zone_code'] = $zone_info['code'];
+ $this->session->data['guest']['shipping']['zone_id'] = $zone_info['zone_id'];
+ $this->session->data['guest']['payment']['zone'] = $zone_info['name'];
+ $this->session->data['guest']['payment']['zone_code'] = $zone_info['code'];
+ $this->session->data['guest']['payment']['zone_id'] = $zone_info['zone_id'];
+ $this->session->data['shipping_zone_id'] = $zone_info['zone_id'];
+ } else {
+ $this->session->data['guest']['shipping']['zone'] = '';
+ $this->session->data['guest']['shipping']['zone_code'] = '';
+ $this->session->data['guest']['shipping']['zone_id'] = '';
+ $this->session->data['guest']['payment']['zone'] = '';
+ $this->session->data['guest']['payment']['zone_code'] = '';
+ $this->session->data['guest']['payment']['zone_id'] = '';
+ $this->session->data['shipping_zone_id'] = '';
+ }
+
+ $this->session->data['guest']['shipping_address'] = true;
+ } else {
+ $this->session->data['guest']['payment']['address_1'] = '';
+ $this->session->data['guest']['payment']['address_2'] = '';
+ $this->session->data['guest']['payment']['postcode'] = '';
+ $this->session->data['guest']['payment']['city'] = '';
+ $this->session->data['guest']['payment']['country_id'] = '';
+ $this->session->data['guest']['payment']['country'] = '';
+ $this->session->data['guest']['payment']['iso_code_2'] = '';
+ $this->session->data['guest']['payment']['iso_code_3'] = '';
+ $this->session->data['guest']['payment']['address_format'] = '';
+ $this->session->data['guest']['payment']['zone'] = '';
+ $this->session->data['guest']['payment']['zone_code'] = '';
+ $this->session->data['guest']['payment']['zone_id'] = '';
+ $this->session->data['guest']['shipping_address'] = false;
+ }
+
+ $this->session->data['account'] = 'guest';
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+ } else {
+ $this->session->data['paypal_braintree']['guest'] = false;
+
+ unset($this->session->data['guest']);
+ /**
+ * if the user is logged in, add the address to the account and set the ID.
+ */
+
+ if ($this->cart->hasShipping()) {
+ $this->load->model('account/address');
+
+ $addresses = $this->model_account_address->getAddresses();
+
+ /**
+ * Compare all of the user addresses and see if there is a match
+ */
+ $match = false;
+ foreach($addresses as $address) {
+ if (trim(strtolower($address['address_1'])) == trim(strtolower($this->request->post['details']['shippingAddress']['line1'])) && trim(strtolower($address['postcode'])) == trim(strtolower($this->request->post['details']['shippingAddress']['postalCode']))) {
+ $match = true;
+
+ $this->session->data['payment_address_id'] = $address['address_id'];
+ $this->session->data['payment_country_id'] = $address['country_id'];
+ $this->session->data['payment_zone_id'] = $address['zone_id'];
+
+ $this->session->data['shipping_address_id'] = $address['address_id'];
+ $this->session->data['shipping_country_id'] = $address['country_id'];
+ $this->session->data['shipping_zone_id'] = $address['zone_id'];
+ $this->session->data['shipping_postcode'] = $address['postcode'];
+
+ break;
+ }
+ }
+
+ /**
+ * If there is no address match add the address and set the info.
+ */
+ if ($match == false) {
+ $shipping_name = explode(' ', trim($this->request->post['details']['shippingAddress']['recipientName']));
+ $shipping_first_name = $shipping_name[0];
+ unset($shipping_name[0]);
+ $shipping_last_name = implode(' ', $shipping_name);
+
+ $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($this->request->post['details']['shippingAddress']['countryCode']) . "' AND `status` = '1' LIMIT 1")->row;
+ $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($this->request->post['details']['shippingAddress']['state']) . "' OR `code` = '" . $this->db->escape($this->request->post['details']['shippingAddress']['state']) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "'")->row;
+
+ $address_data = array(
+ 'firstname' => $shipping_first_name,
+ 'lastname' => $shipping_last_name,
+ 'company' => '',
+ 'company_id' => '',
+ 'tax_id' => '',
+ 'address_1' => $this->request->post['details']['shippingAddress']['line1'],
+ 'address_2' => (isset($this->request->post['details']['shippingAddress']['line2']) ? $this->request->post['details']['shippingAddress']['line2'] : ''),
+ 'postcode' => $this->request->post['details']['shippingAddress']['postalCode'],
+ 'city' => $this->request->post['details']['shippingAddress']['city'],
+ 'zone_id' => (isset($zone_info['zone_id']) ? $zone_info['zone_id'] : 0),
+ 'country_id' => (isset($country_info['country_id']) ? $country_info['country_id'] : 0)
+ );
+
+ $address_id = $this->model_account_address->addAddress($this->customer->getId(), $address_data);
+
+ $this->session->data['payment_address_id'] = $address_id;
+ $this->session->data['payment_country_id'] = $address_data['country_id'];
+ $this->session->data['payment_zone_id'] = $address_data['zone_id'];
+
+ $this->session->data['shipping_address_id'] = $address_id;
+ $this->session->data['shipping_country_id'] = $address_data['country_id'];
+ $this->session->data['shipping_zone_id'] = $address_data['zone_id'];
+ $this->session->data['shipping_postcode'] = $address_data['postcode'];
+ }
+ } else {
+ $this->session->data['payment_address_id'] = '';
+ $this->session->data['payment_country_id'] = '';
+ $this->session->data['payment_zone_id'] = '';
+ }
+ }
+
+ $this->session->data['paypal_braintree'] = $this->request->post;
+
+ $json = array(
+ 'error' => false,
+ 'url' => ''
+ );
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function expressConfirm() {
+ if (!isset($this->session->data['paypal_braintree']) || !isset($this->session->data['paypal_braintree']['nonce'])) {
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+
+ $this->load->language('extension/payment/pp_braintree');
+ $this->load->language('checkout/cart');
+
+ $this->load->model('tool/image');
+ $this->load->model('extension/payment/pp_braintree');
+
+ // Coupon
+ if (isset($this->request->post['coupon']) && $this->validateCoupon()) {
+ $this->session->data['coupon'] = $this->request->post['coupon'];
+
+ $this->session->data['success'] = $this->language->get('text_coupon');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_braintree/expressConfirm', '', true));
+ }
+
+ // Voucher
+ if (isset($this->request->post['voucher']) && $this->validateVoucher()) {
+ $this->session->data['voucher'] = $this->request->post['voucher'];
+
+ $this->session->data['success'] = $this->language->get('text_voucher');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_braintree/expressConfirm', '', true));
+ }
+
+ // Reward
+ if (isset($this->request->post['reward']) && $this->validateReward()) {
+ $this->session->data['reward'] = abs($this->request->post['reward']);
+
+ $this->session->data['success'] = $this->language->get('text_reward');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_braintree/expressConfirm', '', true));
+ }
+
+ $this->document->setTitle($this->language->get('text_express_title'));
+
+ $data['heading_title'] = $this->language->get('text_express_title');
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home'),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_cart'),
+ 'href' => $this->url->link('checkout/cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/pp_braintree/expressConfirm'),
+ 'text' => $this->language->get('text_express_title')
+ );
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ $data['column_name'] = $this->language->get('column_name');
+ $data['column_model'] = $this->language->get('column_model');
+ $data['column_quantity'] = $this->language->get('column_quantity');
+ $data['column_price'] = $this->language->get('column_price');
+ $data['column_total'] = $this->language->get('column_total');
+
+ $data['button_shipping'] = $this->language->get('button_express_shipping');
+ $data['button_confirm'] = $this->language->get('button_express_confirm');
+
+ if (isset($this->request->post['next'])) {
+ $data['next'] = $this->request->post['next'];
+ } else {
+ $data['next'] = '';
+ }
+
+ $data['action'] = $this->url->link('extension/payment/pp_braintree/expressConfirm', '', true);
+
+ $this->load->model('tool/upload');
+
+ $products = $this->cart->getProducts();
+
+ if (empty($products)) {
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $data['error_warning'] = sprintf($this->language->get('error_minimum'), $product['name'], $product['minimum']);
+ }
+
+ if ($product['image']) {
+ $image = $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_height'));
+ } else {
+ $image = '';
+ }
+
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ if ($option['type'] != 'file') {
+ $value = $option['value'];
+ } else {
+ $upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
+
+ if ($upload_info) {
+ $value = $upload_info['name'];
+ } else {
+ $value = '';
+ }
+ }
+
+ $option_data[] = array(
+ 'name' => $option['name'],
+ 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
+ );
+ }
+
+ // Display prices
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $unit_price = $this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'));
+
+ $price = $this->currency->format($unit_price, $this->session->data['currency']);
+ $total = $this->currency->format($unit_price * $product['quantity'], $this->session->data['currency']);
+ } else {
+ $price = false;
+ $total = false;
+ }
+
+ $data['products'][] = array(
+ 'cart_id' => $product['cart_id'],
+ 'thumb' => $image,
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'quantity' => $product['quantity'],
+ 'stock' => $product['stock'] ? true : !(!$this->config->get('config_stock_checkout') || $this->config->get('config_stock_warning')),
+ 'reward' => ($product['reward'] ? sprintf($this->language->get('text_points'), $product['reward']) : ''),
+ 'price' => $price,
+ 'total' => $total,
+ 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id']),
+ 'remove' => $this->url->link('checkout/cart', 'remove=' . $product['cart_id']),
+ );
+ }
+
+ $data['vouchers'] = array();
+
+ if ($this->cart->hasShipping()) {
+ $data['has_shipping'] = true;
+ /**
+ * Shipping services
+ */
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/address');
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ if (!empty($shipping_address)) {
+ // Shipping Methods
+ $quote_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ if (!empty($results)) {
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($shipping_address);
+
+ if ($quote) {
+ $quote_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ if (!empty($quote_data)) {
+ $sort_order = array();
+
+ foreach ($quote_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $quote_data);
+
+ $this->session->data['shipping_methods'] = $quote_data;
+ $data['shipping_methods'] = $quote_data;
+
+ if (!isset($this->session->data['shipping_method'])) {
+ //default the shipping to the very first option.
+ $key1 = key($quote_data);
+ $key2 = key($quote_data[$key1]['quote']);
+ $this->session->data['shipping_method'] = $quote_data[$key1]['quote'][$key2];
+ }
+
+ $data['code'] = $this->session->data['shipping_method']['code'];
+ $data['action_shipping'] = $this->url->link('extension/payment/pp_braintree/shipping', '', true);
+ } else {
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['shipping_method']);
+ $data['error_no_shipping'] = $this->language->get('error_no_shipping');
+ }
+ } else {
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['shipping_method']);
+ $data['error_no_shipping'] = $this->language->get('error_no_shipping');
+ }
+ }
+ } else {
+ $data['has_shipping'] = false;
+ }
+
+ // Totals
+ $this->load->model('setting/extension');
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ // Display prices
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+ }
+
+ $data['totals'] = array();
+
+ foreach ($totals as $total) {
+ $data['totals'][] = array(
+ 'title' => $total['title'],
+ 'text' => $this->currency->format($total['value'], $this->session->data['currency']),
+ );
+ }
+
+ /**
+ * Payment methods
+ */
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $this->load->model('account/address');
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('payment');
+
+ $this->model_extension_payment_pp_braintree->log("Payment methods returned based on new data");
+ $this->model_extension_payment_pp_braintree->log($results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('payment_' . $result['code'] . '_status')) {
+ $this->load->model('extension/payment/' . $result['code']);
+
+ $method = $this->{'model_extension_payment_' . $result['code']}->getMethod($payment_address, $total);
+
+ if ($method) {
+ $method_data[$result['code']] = $method;
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $this->model_extension_payment_pp_braintree->log("Payment methods again - sorted");
+ $this->model_extension_payment_pp_braintree->log($method_data);
+
+ if (!isset($method_data['pp_braintree'])) {
+ $this->model_extension_payment_pp_braintree->log("Braintree module was no longer an option. Check configured zones or minimum order amount based on user address info");
+ $this->session->data['error_warning'] = $this->language->get('error_unavailable');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ $this->session->data['payment_methods'] = $method_data;
+ $this->session->data['payment_method'] = $method_data['pp_braintree'];
+
+ $data['action_confirm'] = $this->url->link('extension/payment/pp_braintree/expressComplete', '', true);
+
+ if (isset($this->session->data['error_warning'])) {
+ $data['error_warning'] = $this->session->data['error_warning'];
+ unset($this->session->data['error_warning']);
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ if (isset($this->session->data['attention'])) {
+ $data['attention'] = $this->session->data['attention'];
+ unset($this->session->data['attention']);
+ } else {
+ $data['attention'] = '';
+ }
+
+ $data['coupon'] = $this->load->controller('extension/total/coupon');
+ $data['voucher'] = $this->load->controller('extension/total/voucher');
+ $data['reward'] = $this->load->controller('extension/total/reward');
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_braintree_confirm', $data));
+ }
+
+ public function expressComplete() {
+ if (!isset($this->session->data['paypal_braintree']) || !isset($this->session->data['paypal_braintree']['nonce'])) {
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+
+ $this->load->language('extension/payment/pp_braintree');
+ $redirect = '';
+
+ if ($this->cart->hasShipping()) {
+ // Validate if shipping address has been set.
+ $this->load->model('account/address');
+
+ if ($this->customer->isLogged() && isset($this->session->data['shipping_address_id'])) {
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ if (empty($shipping_address)) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+
+ // Validate if shipping method has been set.
+ if (!isset($this->session->data['shipping_method'])) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+ } else {
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ }
+
+ // Validate if payment address has been set.
+ $this->load->model('account/address');
+
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ // Validate if payment method has been set.
+ if (!isset($this->session->data['payment_method'])) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $redirect = $this->url->link('checkout/cart');
+
+ break;
+ }
+ }
+
+ if ($redirect == '') {
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $this->load->language('checkout/checkout');
+
+ $data = array();
+
+ $data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
+ $data['store_id'] = $this->config->get('config_store_id');
+ $data['store_name'] = $this->config->get('config_name');
+
+ if ($data['store_id']) {
+ $data['store_url'] = $this->config->get('config_url');
+ } else {
+ $data['store_url'] = HTTP_SERVER;
+ }
+
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $data['customer_id'] = $this->customer->getId();
+ $data['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $data['firstname'] = $this->customer->getFirstName();
+ $data['lastname'] = $this->customer->getLastName();
+ $data['email'] = $this->customer->getEmail();
+ $data['telephone'] = $this->customer->getTelephone();
+
+ $this->load->model('account/address');
+
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $data['customer_id'] = 0;
+ $data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
+ $data['firstname'] = $this->session->data['guest']['firstname'];
+ $data['lastname'] = $this->session->data['guest']['lastname'];
+ $data['email'] = $this->session->data['guest']['email'];
+ $data['telephone'] = $this->session->data['guest']['telephone'];
+
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ $data['payment_firstname'] = isset($payment_address['firstname']) ? $payment_address['firstname'] : '';
+ $data['payment_lastname'] = isset($payment_address['lastname']) ? $payment_address['lastname'] : '';
+ $data['payment_company'] = isset($payment_address['company']) ? $payment_address['company'] : '';
+ $data['payment_company_id'] = isset($payment_address['company_id']) ? $payment_address['company_id'] : '';
+ $data['payment_tax_id'] = isset($payment_address['tax_id']) ? $payment_address['tax_id'] : '';
+ $data['payment_address_1'] = isset($payment_address['address_1']) ? $payment_address['address_1'] : '';
+ $data['payment_address_2'] = isset($payment_address['address_2']) ? $payment_address['address_2'] : '';
+ $data['payment_city'] = isset($payment_address['city']) ? $payment_address['city'] : '';
+ $data['payment_postcode'] = isset($payment_address['postcode']) ? $payment_address['postcode'] : '';
+ $data['payment_zone'] = isset($payment_address['zone']) ? $payment_address['zone'] : '';
+ $data['payment_zone_id'] = isset($payment_address['zone_id']) ? $payment_address['zone_id'] : '';
+ $data['payment_country'] = isset($payment_address['country']) ? $payment_address['country'] : '';
+ $data['payment_country_id'] = isset($payment_address['country_id']) ? $payment_address['country_id'] : '';
+ $data['payment_address_format'] = isset($payment_address['address_format']) ? $payment_address['address_format'] : '';
+
+ $data['payment_method'] = '';
+ if (isset($this->session->data['payment_method']['title'])) {
+ $data['payment_method'] = $this->session->data['payment_method']['title'];
+ }
+
+ $data['payment_code'] = '';
+ if (isset($this->session->data['payment_method']['code'])) {
+ $data['payment_code'] = $this->session->data['payment_method']['code'];
+ }
+
+ if ($this->cart->hasShipping()) {
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/address');
+
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ $data['shipping_firstname'] = $shipping_address['firstname'];
+ $data['shipping_lastname'] = $shipping_address['lastname'];
+ $data['shipping_company'] = $shipping_address['company'];
+ $data['shipping_address_1'] = $shipping_address['address_1'];
+ $data['shipping_address_2'] = $shipping_address['address_2'];
+ $data['shipping_city'] = $shipping_address['city'];
+ $data['shipping_postcode'] = $shipping_address['postcode'];
+ $data['shipping_zone'] = $shipping_address['zone'];
+ $data['shipping_zone_id'] = $shipping_address['zone_id'];
+ $data['shipping_country'] = $shipping_address['country'];
+ $data['shipping_country_id'] = $shipping_address['country_id'];
+ $data['shipping_address_format'] = $shipping_address['address_format'];
+
+ $data['shipping_method'] = '';
+ if (isset($this->session->data['shipping_method']['title'])) {
+ $data['shipping_method'] = $this->session->data['shipping_method']['title'];
+ }
+
+ $data['shipping_code'] = '';
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $data['shipping_code'] = $this->session->data['shipping_method']['code'];
+ }
+ } else {
+ $data['shipping_firstname'] = '';
+ $data['shipping_lastname'] = '';
+ $data['shipping_company'] = '';
+ $data['shipping_address_1'] = '';
+ $data['shipping_address_2'] = '';
+ $data['shipping_city'] = '';
+ $data['shipping_postcode'] = '';
+ $data['shipping_zone'] = '';
+ $data['shipping_zone_id'] = '';
+ $data['shipping_country'] = '';
+ $data['shipping_country_id'] = '';
+ $data['shipping_address_format'] = '';
+ $data['shipping_method'] = '';
+ $data['shipping_code'] = '';
+ }
+
+ $product_data = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ $option_data[] = array(
+ 'product_option_id' => $option['product_option_id'],
+ 'product_option_value_id' => $option['product_option_value_id'],
+ 'option_id' => $option['option_id'],
+ 'option_value_id' => $option['option_value_id'],
+ 'name' => $option['name'],
+ 'value' => $option['value'],
+ 'type' => $option['type']
+ );
+ }
+
+ $product_data[] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'download' => $product['download'],
+ 'quantity' => $product['quantity'],
+ 'subtract' => $product['subtract'],
+ 'price' => $product['price'],
+ 'total' => $product['total'],
+ 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
+ 'reward' => $product['reward']
+ );
+ }
+
+ // Gift Voucher
+ $voucher_data = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $voucher) {
+ $voucher_data[] = array(
+ 'description' => $voucher['description'],
+ 'code' => token(10),
+ 'to_name' => $voucher['to_name'],
+ 'to_email' => $voucher['to_email'],
+ 'from_name' => $voucher['from_name'],
+ 'from_email' => $voucher['from_email'],
+ 'voucher_theme_id' => $voucher['voucher_theme_id'],
+ 'message' => $voucher['message'],
+ 'amount' => $voucher['amount']
+ );
+ }
+ }
+
+ $data['products'] = $product_data;
+ $data['vouchers'] = $voucher_data;
+ $data['totals'] = $totals;
+ $data['total'] = $total;
+ $data['comment'] = '';
+
+ if (isset($this->request->cookie['tracking'])) {
+ $data['tracking'] = $this->request->cookie['tracking'];
+
+ $subtotal = $this->cart->getSubTotal();
+
+ // Affiliate
+ $this->load->model('affiliate/affiliate');
+
+ $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
+
+ if ($affiliate_info) {
+ $data['affiliate_id'] = $affiliate_info['affiliate_id'];
+ $data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
+ } else {
+ $data['affiliate_id'] = 0;
+ $data['commission'] = 0;
+ }
+
+ // Marketing
+ $this->load->model('checkout/marketing');
+
+ $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
+
+ if ($marketing_info) {
+ $data['marketing_id'] = $marketing_info['marketing_id'];
+ } else {
+ $data['marketing_id'] = 0;
+ }
+ } else {
+ $data['affiliate_id'] = 0;
+ $data['commission'] = 0;
+ $data['marketing_id'] = 0;
+ $data['tracking'] = '';
+ }
+
+ $data['language_id'] = $this->config->get('config_language_id');
+ $data['currency_id'] = $this->currency->getId($this->session->data['currency']);
+ $data['currency_code'] = $this->session->data['currency'];
+ $data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
+ $data['ip'] = $this->request->server['REMOTE_ADDR'];
+
+ if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
+ $data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
+ } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
+ $data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
+ } else {
+ $data['forwarded_ip'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $data['user_agent'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
+ $data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
+ } else {
+ $data['accept_language'] = '';
+ }
+
+ $this->load->model('account/custom_field');
+ $this->load->model('checkout/order');
+
+ $order_id = $this->model_checkout_order->addOrder($data);
+ $this->session->data['order_id'] = $order_id;
+
+ $this->load->model('extension/payment/pp_braintree');
+
+ $this->initialise();
+
+ $create_sale = [
+ "amount" => $this->currency->format($data['total'], $data['currency_code'], $data['currency_value'], false),
+ "paymentMethodNonce" => $this->session->data['paypal_braintree']['nonce'],
+ "orderId" => $order_id,
+ 'channel' => 'OpenCart_Cart_vzero',
+ ];
+
+ $transaction = $this->model_extension_payment_pp_braintree->addTransaction($this->gateway, $create_sale);
+
+ //handle order status
+
+ $order_status_id = 0;
+ switch ($transaction->transaction->status) {
+ case 'authorization_expired':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorization_expired_id');
+ break;
+ case 'authorized':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorized_id');
+ break;
+ case 'authorizing':
+ $order_status_id = $this->config->get('payment_pp_braintree_authorizing_id');
+ break;
+ case 'settlement_pending':
+ $order_status_id = $this->config->get('payment_pp_braintree_settlement_pending_id');
+ break;
+ case 'failed':
+ $order_status_id = $this->config->get('payment_pp_braintree_failed_id');
+ break;
+ case 'gateway_rejected':
+ $order_status_id = $this->config->get('payment_pp_braintree_gateway_rejected_id');
+ break;
+ case 'processor_declined':
+ $order_status_id = $this->config->get('payment_pp_braintree_processor_declined_id');
+ break;
+ case 'settled':
+ $order_status_id = $this->config->get('payment_pp_braintree_settled_id');
+ break;
+ case 'settling':
+ $order_status_id = $this->config->get('payment_pp_braintree_settling_id');
+ break;
+ case 'submitted_for_settlement':
+ $order_status_id = $this->config->get('payment_pp_braintree_submitted_for_settlement_id');
+ break;
+ case 'voided':
+ $order_status_id = $this->config->get('payment_pp_braintree_voided_id');
+ break;
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $order_status_id);
+
+ if ($transaction->success) {
+ $this->model_extension_payment_pp_braintree->log('Transaction success, details below');
+ $this->model_extension_payment_pp_braintree->log($transaction);
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->model_extension_payment_pp_braintree->log('Transaction failed, details below');
+ $this->model_extension_payment_pp_braintree->log($transaction);
+
+ $this->session->data['error'] = $this->language->get('error_process_order');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->response->redirect($redirect);
+ }
+ }
+
+ private function initialise() {
+ $this->load->model('extension/payment/pp_braintree');
+
+ if ($this->config->get('payment_pp_braintree_access_token') != '') {
+ $this->gateway = $this->model_extension_payment_pp_braintree->setGateway($this->config->get('payment_pp_braintree_access_token'));
+ } else {
+ $this->model_extension_payment_pp_braintree->setCredentials();
+ }
+ }
+
+ public function shipping() {
+ $this->shippingValidate($this->request->post['shipping_method']);
+
+ $this->response->redirect($this->url->link('extension/payment/pp_braintree/expressConfirm'));
+ }
+
+ protected function shippingValidate($code) {
+ $this->load->language('checkout/cart');
+ $this->load->language('extension/payment/pp_braintree');
+
+ if (empty($code)) {
+ $this->session->data['error_warning'] = $this->language->get('error_shipping');
+ return false;
+ } else {
+ $shipping = explode('.', $code);
+
+ if (!isset($shipping[0]) || !isset($shipping[1]) || !isset($this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]])) {
+ $this->session->data['error_warning'] = $this->language->get('error_shipping');
+ return false;
+ } else {
+ $this->session->data['shipping_method'] = $this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]];
+ $this->session->data['success'] = $this->language->get('text_shipping_updated');
+ return true;
+ }
+ }
+ }
+
+ protected function validateCoupon() {
+ $this->load->model('extension/total/coupon');
+
+ $coupon_info = $this->model_extension_total_coupon->getCoupon($this->request->post['coupon']);
+
+ if ($coupon_info) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('error_coupon');
+ return false;
+ }
+ }
+
+ protected function validateVoucher() {
+ $this->load->model('extension/total/coupon');
+
+ $voucher_info = $this->model_extension_total_voucher->getVoucher($this->request->post['voucher']);
+
+ if ($voucher_info) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('error_voucher');
+ return false;
+ }
+ }
+
+ protected function validateReward() {
+ $points = $this->customer->getRewardPoints();
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ $error = '';
+
+ if (empty($this->request->post['reward'])) {
+ $error = $this->language->get('error_reward');
+ }
+
+ if ($this->request->post['reward'] > $points) {
+ $error = sprintf($this->language->get('error_points'), $this->request->post['reward']);
+ }
+
+ if ($this->request->post['reward'] > $points_total) {
+ $error = sprintf($this->language->get('error_maximum'), $points_total);
+ }
+
+ if (!$error) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $error;
+ return false;
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/pp_express.php b/public/catalog/controller/extension/payment/pp_express.php
new file mode 100644
index 0000000..9081cfe
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_express.php
@@ -0,0 +1,1963 @@
+<?php
+class ControllerExtensionPaymentPPExpress extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/pp_express');
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $data['paypal_environment'] = "sandbox";
+ } else {
+ $data['paypal_environment'] = "production";
+ }
+
+ $data['payment_pp_express_style_layout'] = $this->config->get('payment_pp_express_style_layout') != null ? $this->config->get('payment_pp_express_style_layout') : "vertical";
+ $data['payment_pp_express_style_size'] = $this->config->get('payment_pp_express_style_size') != null ? $this->config->get('payment_pp_express_style_size') : "medium";
+ $data['payment_pp_express_style_shape'] = $this->config->get('payment_pp_express_style_shape') != null ? $this->config->get('payment_pp_express_style_shape') : "rect";
+ $data['payment_pp_express_style_color'] = $this->config->get('payment_pp_express_style_color') != null ? $this->config->get('payment_pp_express_style_color') : "blue";
+
+ $data['payment_pp_express_pp_credit'] = $this->config->get('payment_pp_express_pp_credit');
+ $data['payment_pp_express_pp_cards'] = $this->config->get('payment_pp_express_pp_cards');
+ $data['payment_pp_express_pp_elv'] = $this->config->get('payment_pp_express_pp_elv');
+
+ $disallowed_payment_methods = array();
+ $allowed_payment_methods = array();
+
+ if ($this->config->get('payment_pp_express_pp_credit') == 1) {
+ $allowed_payment_methods[] = "paypal.FUNDING.CREDIT";
+ } else {
+ $disallowed_payment_methods[] = "paypal.FUNDING.CREDIT";
+ }
+
+ if ($this->config->get('payment_pp_express_pp_cards') == 1) {
+ $allowed_payment_methods[] = "paypal.FUNDING.CARD";
+ } else {
+ $disallowed_payment_methods[] = "paypal.FUNDING.CARD";
+ }
+
+ if ($this->config->get('payment_pp_express_pp_elv') == 1) {
+ $allowed_payment_methods[] = "paypal.FUNDING.ELV";
+ } else {
+ $disallowed_payment_methods[] = "paypal.FUNDING.ELV";
+ }
+
+ $data['allowed_payment_methods'] = implode(",", $allowed_payment_methods);
+ $data['disallowed_payment_methods'] = implode(",", $disallowed_payment_methods);
+
+ $data['continue'] = $this->url->link('extension/payment/pp_express/checkout', '', true);
+
+ unset($this->session->data['paypal']);
+
+ return $this->load->view('extension/payment/pp_express', $data);
+ }
+
+ public function eventLoadCheckoutJs($route, &$data) {
+ $this->document->addScript('https://www.paypalobjects.com/api/checkout.js');
+ }
+
+ public function express() {
+ $this->load->model('extension/payment/pp_express');
+
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->response->redirect($this->url->link('checkout/cart'));
+ }
+
+ if ($this->customer->isLogged()) {
+ /**
+ * If the customer is already logged in
+ */
+ $this->session->data['paypal']['guest'] = false;
+
+ unset($this->session->data['guest']);
+ } else {
+ if ($this->config->get('config_checkout_guest') && !$this->config->get('config_customer_price') && !$this->cart->hasDownload() && !$this->cart->hasRecurringProducts()) {
+ /**
+ * If the guest checkout is allowed (config ok, no login for price and doesn't have downloads)
+ */
+ $this->session->data['paypal']['guest'] = true;
+ } else {
+ /**
+ * If guest checkout disabled or login is required before price or order has downloads
+ *
+ * Send them to the normal checkout flow.
+ */
+ unset($this->session->data['guest']);
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+
+ $this->load->model('tool/image');
+
+ if ($this->cart->hasShipping()) {
+ $shipping = 2;
+ } else {
+ $shipping = 1;
+ }
+
+ $max_amount = $this->cart->getTotal() * 1.5;
+ $max_amount = $this->currency->format($max_amount, $this->session->data['currency'], '', false);
+
+ $data = array(
+ 'METHOD' => 'SetExpressCheckout',
+ 'MAXAMT' => $max_amount,
+ 'RETURNURL' => $this->url->link('extension/payment/pp_express/expressReturn', '', true),
+ 'CANCELURL' => $this->url->link('checkout/cart', '', true),
+ 'REQCONFIRMSHIPPING' => 0,
+ 'NOSHIPPING' => $shipping,
+ 'LANDINGPAGE' => 'Login',
+ 'LOGOIMG' => $this->model_tool_image->resize($this->config->get('payment_pp_express_logo'), 750, 90),
+ 'CHANNELTYPE' => 'Merchant'
+ );
+
+ if (isset($this->session->data['pp_login']['seamless']['access_token']) && (isset($this->session->data['pp_login']['seamless']['customer_id']) && $this->session->data['pp_login']['seamless']['customer_id'] == $this->customer->getId()) && $this->config->get('module_pp_login_seamless')) {
+ $data['IDENTITYACCESSTOKEN'] = $this->session->data['pp_login']['seamless']['access_token'];
+ }
+
+ $data = array_merge($data, $this->model_extension_payment_pp_express->paymentRequestInfo());
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+
+ /**
+ * If a failed PayPal setup happens, handle it.
+ */
+ if (!isset($result['TOKEN'])) {
+ $this->session->data['error'] = $result['L_LONGMESSAGE0'];
+ /**
+ * Unable to add error message to user as the session errors/success are not
+ * used on the cart or checkout pages - need to be added?
+ * If PayPal debug log is off then still log error to normal error log.
+ */
+
+ $this->log->write('Unable to create PayPal call: ' . json_encode($result));
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ $this->session->data['paypal']['token'] = $result['TOKEN'];
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ header('Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN']);
+ } else {
+ header('Location: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN']);
+ }
+ }
+
+ public function expressReturn() {
+ /**
+ * This is the url when PayPal has completed the auth.
+ *
+ * It has no output, instead it sets the data and locates to checkout
+ */
+ $this->load->model('extension/payment/pp_express');
+ $data = array(
+ 'METHOD' => 'GetExpressCheckoutDetails',
+ 'TOKEN' => $this->session->data['paypal']['token']
+ );
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+ $this->session->data['paypal']['payerid'] = $result['PAYERID'];
+ $this->session->data['paypal']['result'] = $result;
+
+ $this->session->data['comment'] = '';
+ if (isset($result['PAYMENTREQUEST_0_NOTETEXT'])) {
+ $this->session->data['comment'] = $result['PAYMENTREQUEST_0_NOTETEXT'];
+ }
+
+ if ($this->session->data['paypal']['guest'] == true) {
+ $this->session->data['guest']['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $this->session->data['guest']['firstname'] = trim($result['FIRSTNAME']);
+ $this->session->data['guest']['lastname'] = trim($result['LASTNAME']);
+ $this->session->data['guest']['email'] = trim($result['EMAIL']);
+
+ if (isset($result['PHONENUM'])) {
+ $this->session->data['guest']['telephone'] = $result['PHONENUM'];
+ } else {
+ $this->session->data['guest']['telephone'] = '';
+ }
+
+ $this->session->data['guest']['payment']['firstname'] = trim($result['FIRSTNAME']);
+ $this->session->data['guest']['payment']['lastname'] = trim($result['LASTNAME']);
+
+ if (isset($result['BUSINESS'])) {
+ $this->session->data['guest']['payment']['company'] = $result['BUSINESS'];
+ } else {
+ $this->session->data['guest']['payment']['company'] = '';
+ }
+
+ $this->session->data['guest']['payment']['company_id'] = '';
+ $this->session->data['guest']['payment']['tax_id'] = '';
+
+ if ($this->cart->hasShipping()) {
+ $shipping_name = explode(' ', trim($result['PAYMENTREQUEST_0_SHIPTONAME']));
+ $shipping_first_name = $shipping_name[0];
+ unset($shipping_name[0]);
+ $shipping_last_name = implode(' ', $shipping_name);
+
+ $this->session->data['guest']['payment']['address_1'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET'];
+ if (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2'])) {
+ $this->session->data['guest']['payment']['address_2'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET2'];
+ } else {
+ $this->session->data['guest']['payment']['address_2'] = '';
+ }
+
+ $this->session->data['guest']['payment']['postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP'];
+ $this->session->data['guest']['payment']['city'] = $result['PAYMENTREQUEST_0_SHIPTOCITY'];
+
+ $this->session->data['guest']['shipping']['firstname'] = $shipping_first_name;
+ $this->session->data['guest']['shipping']['lastname'] = $shipping_last_name;
+ $this->session->data['guest']['shipping']['company'] = '';
+ $this->session->data['guest']['shipping']['address_1'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET'];
+
+ if (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2'])) {
+ $this->session->data['guest']['shipping']['address_2'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET2'];
+ } else {
+ $this->session->data['guest']['shipping']['address_2'] = '';
+ }
+
+ $this->session->data['guest']['shipping']['postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP'];
+ $this->session->data['guest']['shipping']['city'] = $result['PAYMENTREQUEST_0_SHIPTOCITY'];
+
+ $this->session->data['shipping_postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP'];
+
+ $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE']) . "' AND `status` = '1' LIMIT 1")->row;
+
+ if ($country_info) {
+ $this->session->data['guest']['shipping']['country_id'] = $country_info['country_id'];
+ $this->session->data['guest']['shipping']['country'] = $country_info['name'];
+ $this->session->data['guest']['shipping']['iso_code_2'] = $country_info['iso_code_2'];
+ $this->session->data['guest']['shipping']['iso_code_3'] = $country_info['iso_code_3'];
+ $this->session->data['guest']['shipping']['address_format'] = $country_info['address_format'];
+ $this->session->data['guest']['payment']['country_id'] = $country_info['country_id'];
+ $this->session->data['guest']['payment']['country'] = $country_info['name'];
+ $this->session->data['guest']['payment']['iso_code_2'] = $country_info['iso_code_2'];
+ $this->session->data['guest']['payment']['iso_code_3'] = $country_info['iso_code_3'];
+ $this->session->data['guest']['payment']['address_format'] = $country_info['address_format'];
+ $this->session->data['shipping_country_id'] = $country_info['country_id'];
+ } else {
+ $this->session->data['guest']['shipping']['country_id'] = '';
+ $this->session->data['guest']['shipping']['country'] = '';
+ $this->session->data['guest']['shipping']['iso_code_2'] = '';
+ $this->session->data['guest']['shipping']['iso_code_3'] = '';
+ $this->session->data['guest']['shipping']['address_format'] = '';
+ $this->session->data['guest']['payment']['country_id'] = '';
+ $this->session->data['guest']['payment']['country'] = '';
+ $this->session->data['guest']['payment']['iso_code_2'] = '';
+ $this->session->data['guest']['payment']['iso_code_3'] = '';
+ $this->session->data['guest']['payment']['address_format'] = '';
+ $this->session->data['shipping_country_id'] = '';
+ }
+
+ if (isset($result['PAYMENTREQUEST_0_SHIPTOSTATE'])) {
+ $returned_shipping_zone = $result['PAYMENTREQUEST_0_SHIPTOSTATE'];
+ } else {
+ $returned_shipping_zone = '';
+ }
+
+ $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($returned_shipping_zone) . "' OR `code` = '" . $this->db->escape($returned_shipping_zone) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "' LIMIT 1")->row;
+
+ if ($zone_info) {
+ $this->session->data['guest']['shipping']['zone'] = $zone_info['name'];
+ $this->session->data['guest']['shipping']['zone_code'] = $zone_info['code'];
+ $this->session->data['guest']['shipping']['zone_id'] = $zone_info['zone_id'];
+ $this->session->data['guest']['payment']['zone'] = $zone_info['name'];
+ $this->session->data['guest']['payment']['zone_code'] = $zone_info['code'];
+ $this->session->data['guest']['payment']['zone_id'] = $zone_info['zone_id'];
+ $this->session->data['shipping_zone_id'] = $zone_info['zone_id'];
+ } else {
+ $this->session->data['guest']['shipping']['zone'] = '';
+ $this->session->data['guest']['shipping']['zone_code'] = '';
+ $this->session->data['guest']['shipping']['zone_id'] = '';
+ $this->session->data['guest']['payment']['zone'] = '';
+ $this->session->data['guest']['payment']['zone_code'] = '';
+ $this->session->data['guest']['payment']['zone_id'] = '';
+ $this->session->data['shipping_zone_id'] = '';
+ }
+
+ $this->session->data['guest']['shipping_address'] = true;
+ } else {
+ $this->session->data['guest']['payment']['address_1'] = '';
+ $this->session->data['guest']['payment']['address_2'] = '';
+ $this->session->data['guest']['payment']['postcode'] = '';
+ $this->session->data['guest']['payment']['city'] = '';
+ $this->session->data['guest']['payment']['country_id'] = '';
+ $this->session->data['guest']['payment']['country'] = '';
+ $this->session->data['guest']['payment']['iso_code_2'] = '';
+ $this->session->data['guest']['payment']['iso_code_3'] = '';
+ $this->session->data['guest']['payment']['address_format'] = '';
+ $this->session->data['guest']['payment']['zone'] = '';
+ $this->session->data['guest']['payment']['zone_code'] = '';
+ $this->session->data['guest']['payment']['zone_id'] = '';
+ $this->session->data['guest']['shipping_address'] = false;
+ }
+
+ $this->session->data['account'] = 'guest';
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+ } else {
+ unset($this->session->data['guest']);
+ /**
+ * if the user is logged in, add the address to the account and set the ID.
+ */
+
+ if ($this->cart->hasShipping()) {
+ $this->load->model('account/address');
+
+ $addresses = $this->model_account_address->getAddresses();
+
+ /**
+ * Compare all of the user addresses and see if there is a match
+ */
+ $match = false;
+ foreach($addresses as $address) {
+ if (trim(strtolower($address['address_1'])) == trim(strtolower($result['PAYMENTREQUEST_0_SHIPTOSTREET'])) && trim(strtolower($address['postcode'])) == trim(strtolower($result['PAYMENTREQUEST_0_SHIPTOZIP']))) {
+ $match = true;
+
+ $this->session->data['payment_address_id'] = $address['address_id'];
+ $this->session->data['payment_country_id'] = $address['country_id'];
+ $this->session->data['payment_zone_id'] = $address['zone_id'];
+
+ $this->session->data['shipping_address_id'] = $address['address_id'];
+ $this->session->data['shipping_country_id'] = $address['country_id'];
+ $this->session->data['shipping_zone_id'] = $address['zone_id'];
+ $this->session->data['shipping_postcode'] = $address['postcode'];
+
+ break;
+ }
+ }
+
+ /**
+ * If there is no address match add the address and set the info.
+ */
+ if ($match == false) {
+
+ $shipping_name = explode(' ', trim($result['PAYMENTREQUEST_0_SHIPTONAME']));
+ $shipping_first_name = $shipping_name[0];
+ unset($shipping_name[0]);
+ $shipping_last_name = implode(' ', $shipping_name);
+
+ $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE']) . "' AND `status` = '1' LIMIT 1")->row;
+
+ if (isset($result['PAYMENTREQUEST_0_SHIPTOSTATE'])) {
+ $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOSTATE']) . "' OR `code` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOSTATE']) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "'")->row;
+ } else {
+ $zone_info = array();
+ }
+
+ $address_data = array(
+ 'firstname' => $shipping_first_name,
+ 'lastname' => $shipping_last_name,
+ 'company' => '',
+ 'company_id' => '',
+ 'tax_id' => '',
+ 'address_1' => $result['PAYMENTREQUEST_0_SHIPTOSTREET'],
+ 'address_2' => (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2']) ? $result['PAYMENTREQUEST_0_SHIPTOSTREET2'] : ''),
+ 'postcode' => $result['PAYMENTREQUEST_0_SHIPTOZIP'],
+ 'city' => $result['PAYMENTREQUEST_0_SHIPTOCITY'],
+ 'zone_id' => (isset($zone_info['zone_id']) ? $zone_info['zone_id'] : 0),
+ 'country_id' => (isset($country_info['country_id']) ? $country_info['country_id'] : 0)
+ );
+
+ $address_id = $this->model_account_address->addAddress($this->customer->getId(), $address_data);
+
+ $this->session->data['payment_address_id'] = $address_id;
+ $this->session->data['payment_country_id'] = $address_data['country_id'];
+ $this->session->data['payment_zone_id'] = $address_data['zone_id'];
+
+ $this->session->data['shipping_address_id'] = $address_id;
+ $this->session->data['shipping_country_id'] = $address_data['country_id'];
+ $this->session->data['shipping_zone_id'] = $address_data['zone_id'];
+ $this->session->data['shipping_postcode'] = $address_data['postcode'];
+ }
+ } else {
+ $this->session->data['payment_address_id'] = '';
+ $this->session->data['payment_country_id'] = '';
+ $this->session->data['payment_zone_id'] = '';
+ }
+ }
+
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true));
+ }
+
+ public function expressConfirm() {
+ $this->load->language('extension/payment/pp_express');
+ $this->load->language('checkout/cart');
+
+ $this->load->model('tool/image');
+
+ // Coupon
+ if (isset($this->request->post['coupon']) && $this->validateCoupon()) {
+ $this->session->data['coupon'] = $this->request->post['coupon'];
+
+ $this->session->data['success'] = $this->language->get('text_coupon');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true));
+ }
+
+ // Voucher
+ if (isset($this->request->post['voucher']) && $this->validateVoucher()) {
+ $this->session->data['voucher'] = $this->request->post['voucher'];
+
+ $this->session->data['success'] = $this->language->get('text_voucher');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true));
+ }
+
+ // Reward
+ if (isset($this->request->post['reward']) && $this->validateReward()) {
+ $this->session->data['reward'] = abs($this->request->post['reward']);
+
+ $this->session->data['success'] = $this->language->get('text_reward');
+
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true));
+ }
+
+ $this->document->setTitle($this->language->get('express_text_title'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home'),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/pp_express/express'),
+ 'text' => $this->language->get('text_title')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('extension/payment/pp_express/expressConfirm'),
+ 'text' => $this->language->get('express_text_title')
+ );
+
+ $points = $this->customer->getRewardPoints();
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ $data['button_shipping'] = $this->language->get('button_express_shipping');
+ $data['button_confirm'] = $this->language->get('button_express_confirm');
+
+ if (isset($this->request->post['next'])) {
+ $data['next'] = $this->request->post['next'];
+ } else {
+ $data['next'] = '';
+ }
+
+ $data['action'] = $this->url->link('extension/payment/pp_express/expressConfirm', '', true);
+
+ $this->load->model('tool/upload');
+
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $data['error_warning'] = sprintf($this->language->get('error_minimum'), $product['name'], $product['minimum']);
+ }
+
+ if ($product['image']) {
+ $image = $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_height'));
+ } else {
+ $image = '';
+ }
+
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ if ($option['type'] != 'file') {
+ $value = $option['value'];
+ } else {
+ $upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
+
+ if ($upload_info) {
+ $value = $upload_info['name'];
+ } else {
+ $value = '';
+ }
+ }
+
+ $option_data[] = array(
+ 'name' => $option['name'],
+ 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
+ );
+ }
+
+ // Display prices
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $unit_price = $this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax'));
+
+ $price = $this->currency->format($unit_price, $this->session->data['currency']);
+ $total = $this->currency->format($unit_price * $product['quantity'], $this->session->data['currency']);
+ } else {
+ $price = false;
+ $total = false;
+ }
+
+ $recurring_description = '';
+
+ if ($product['recurring']) {
+ $frequencies = array(
+ 'day' => $this->language->get('text_day'),
+ 'week' => $this->language->get('text_week'),
+ 'semi_month' => $this->language->get('text_semi_month'),
+ 'month' => $this->language->get('text_month'),
+ 'year' => $this->language->get('text_year'),
+ );
+
+ if ($product['recurring']['trial']) {
+ $recurring_price = $this->currency->format($this->tax->calculate($product['recurring']['trial_price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ $recurring_description = sprintf($this->language->get('text_trial_description'), $recurring_price, $product['recurring']['trial_cycle'], $frequencies[$product['recurring']['trial_frequency']], $product['recurring']['trial_duration']) . ' ';
+ }
+
+ $recurring_price = $this->currency->format($this->tax->calculate($product['recurring']['price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+
+ if ($product['recurring']['duration']) {
+ $recurring_description .= sprintf($this->language->get('text_payment_description'), $recurring_price, $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']);
+ } else {
+ $recurring_description .= sprintf($this->language->get('text_payment_cancel'), $recurring_price, $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']);
+ }
+ }
+
+ $data['products'][] = array(
+ 'cart_id' => $product['cart_id'],
+ 'thumb' => $image,
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'quantity' => $product['quantity'],
+ 'stock' => $product['stock'] ? true : !(!$this->config->get('config_stock_checkout') || $this->config->get('config_stock_warning')),
+ 'reward' => ($product['reward'] ? sprintf($this->language->get('text_points'), $product['reward']) : ''),
+ 'price' => $price,
+ 'total' => $total,
+ 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id']),
+ 'remove' => $this->url->link('checkout/cart', 'remove=' . $product['cart_id']),
+ 'recurring' => $product['recurring'],
+ 'recurring_name' => (isset($product['recurring']['recurring_name']) ? $product['recurring']['recurring_name'] : ''),
+ 'recurring_description' => $recurring_description
+ );
+ }
+
+ $data['vouchers'] = array();
+
+ if ($this->cart->hasShipping()) {
+
+ $data['has_shipping'] = true;
+ /**
+ * Shipping services
+ */
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/address');
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ if (!empty($shipping_address)) {
+ // Shipping Methods
+ $quote_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ if (!empty($results)) {
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($shipping_address);
+
+ if ($quote) {
+ $quote_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ if (!empty($quote_data)) {
+ $sort_order = array();
+
+ foreach ($quote_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $quote_data);
+
+ $this->session->data['shipping_methods'] = $quote_data;
+ $data['shipping_methods'] = $quote_data;
+
+ if (!isset($this->session->data['shipping_method'])) {
+ //default the shipping to the very first option.
+ $key1 = key($quote_data);
+ $key2 = key($quote_data[$key1]['quote']);
+ $this->session->data['shipping_method'] = $quote_data[$key1]['quote'][$key2];
+ }
+
+ $data['code'] = $this->session->data['shipping_method']['code'];
+ $data['action_shipping'] = $this->url->link('extension/payment/pp_express/shipping', '', true);
+ } else {
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['shipping_method']);
+ $data['error_no_shipping'] = $this->language->get('error_no_shipping');
+ }
+ } else {
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['shipping_method']);
+ $data['error_no_shipping'] = $this->language->get('error_no_shipping');
+ }
+ }
+ } else {
+ $data['has_shipping'] = false;
+ }
+
+ // Totals
+ $this->load->model('setting/extension');
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ // Display prices
+ if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) {
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+ }
+
+ $data['totals'] = array();
+
+ foreach ($totals as $total) {
+ $data['totals'][] = array(
+ 'title' => $total['title'],
+ 'text' => $this->currency->format($total['value'], $this->session->data['currency']),
+ );
+ }
+
+ /**
+ * Payment methods
+ */
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $this->load->model('account/address');
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('payment');
+
+ foreach ($results as $result) {
+ if ($this->config->get('payment_' . $result['code'] . '_status')) {
+ $this->load->model('extension/payment/' . $result['code']);
+
+ $method = $this->{'model_extension_payment_' . $result['code']}->getMethod($payment_address, $total);
+
+ if ($method) {
+ $method_data[$result['code']] = $method;
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ if (!isset($method_data['pp_express'])) {
+ $this->session->data['error_warning'] = $this->language->get('error_unavailable');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ $this->session->data['payment_methods'] = $method_data;
+ $this->session->data['payment_method'] = $method_data['pp_express'];
+
+ $data['action_confirm'] = $this->url->link('extension/payment/pp_express/expressComplete', '', true);
+
+ if (isset($this->session->data['error_warning'])) {
+ $data['error_warning'] = $this->session->data['error_warning'];
+ unset($this->session->data['error_warning']);
+ } else {
+ $data['error_warning'] = '';
+ }
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ if (isset($this->session->data['attention'])) {
+ $data['attention'] = $this->session->data['attention'];
+ unset($this->session->data['attention']);
+ } else {
+ $data['attention'] = '';
+ }
+
+ $data['coupon'] = $this->load->controller('extension/total/coupon');
+ $data['voucher'] = $this->load->controller('extension/total/voucher');
+ $data['reward'] = $this->load->controller('extension/total/reward');
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_express_confirm', $data));
+ }
+
+ public function expressComplete() {
+ $this->load->language('extension/payment/pp_express');
+ $redirect = '';
+
+ if ($this->cart->hasShipping()) {
+ // Validate if shipping address has been set.
+ $this->load->model('account/address');
+
+ if ($this->customer->isLogged() && isset($this->session->data['shipping_address_id'])) {
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ if (empty($shipping_address)) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+
+ // Validate if shipping method has been set.
+ if (!isset($this->session->data['shipping_method'])) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+ } else {
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ }
+
+ // Validate if payment address has been set.
+ $this->load->model('account/address');
+
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ // Validate if payment method has been set.
+ if (!isset($this->session->data['payment_method'])) {
+ $redirect = $this->url->link('checkout/checkout', '', true);
+ }
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $redirect = $this->url->link('checkout/cart');
+
+ break;
+ }
+ }
+
+ if ($redirect == '') {
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get('total_' . $result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $this->load->language('checkout/checkout');
+
+ $data = array();
+
+ $data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
+ $data['store_id'] = $this->config->get('config_store_id');
+ $data['store_name'] = $this->config->get('config_name');
+
+ if ($data['store_id']) {
+ $data['store_url'] = $this->config->get('config_url');
+ } else {
+ $data['store_url'] = HTTP_SERVER;
+ }
+
+ if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
+ $data['customer_id'] = $this->customer->getId();
+ $data['customer_group_id'] = $this->config->get('config_customer_group_id');
+ $data['firstname'] = $this->customer->getFirstName();
+ $data['lastname'] = $this->customer->getLastName();
+ $data['email'] = $this->customer->getEmail();
+ $data['telephone'] = $this->customer->getTelephone();
+
+ $this->load->model('account/address');
+
+ $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $data['customer_id'] = 0;
+ $data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
+ $data['firstname'] = $this->session->data['guest']['firstname'];
+ $data['lastname'] = $this->session->data['guest']['lastname'];
+ $data['email'] = $this->session->data['guest']['email'];
+ $data['telephone'] = $this->session->data['guest']['telephone'];
+
+ $payment_address = $this->session->data['guest']['payment'];
+ }
+
+ $data['payment_firstname'] = isset($payment_address['firstname']) ? $payment_address['firstname'] : '';
+ $data['payment_lastname'] = isset($payment_address['lastname']) ? $payment_address['lastname'] : '';
+ $data['payment_company'] = isset($payment_address['company']) ? $payment_address['company'] : '';
+ $data['payment_company_id'] = isset($payment_address['company_id']) ? $payment_address['company_id'] : '';
+ $data['payment_tax_id'] = isset($payment_address['tax_id']) ? $payment_address['tax_id'] : '';
+ $data['payment_address_1'] = isset($payment_address['address_1']) ? $payment_address['address_1'] : '';
+ $data['payment_address_2'] = isset($payment_address['address_2']) ? $payment_address['address_2'] : '';
+ $data['payment_city'] = isset($payment_address['city']) ? $payment_address['city'] : '';
+ $data['payment_postcode'] = isset($payment_address['postcode']) ? $payment_address['postcode'] : '';
+ $data['payment_zone'] = isset($payment_address['zone']) ? $payment_address['zone'] : '';
+ $data['payment_zone_id'] = isset($payment_address['zone_id']) ? $payment_address['zone_id'] : '';
+ $data['payment_country'] = isset($payment_address['country']) ? $payment_address['country'] : '';
+ $data['payment_country_id'] = isset($payment_address['country_id']) ? $payment_address['country_id'] : '';
+ $data['payment_address_format'] = isset($payment_address['address_format']) ? $payment_address['address_format'] : '';
+
+ $data['payment_method'] = '';
+ if (isset($this->session->data['payment_method']['title'])) {
+ $data['payment_method'] = $this->session->data['payment_method']['title'];
+ }
+
+ $data['payment_code'] = '';
+ if (isset($this->session->data['payment_method']['code'])) {
+ $data['payment_code'] = $this->session->data['payment_method']['code'];
+ }
+
+ if ($this->cart->hasShipping()) {
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/address');
+
+ $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
+ } elseif (isset($this->session->data['guest'])) {
+ $shipping_address = $this->session->data['guest']['shipping'];
+ }
+
+ $data['shipping_firstname'] = $shipping_address['firstname'];
+ $data['shipping_lastname'] = $shipping_address['lastname'];
+ $data['shipping_company'] = $shipping_address['company'];
+ $data['shipping_address_1'] = $shipping_address['address_1'];
+ $data['shipping_address_2'] = $shipping_address['address_2'];
+ $data['shipping_city'] = $shipping_address['city'];
+ $data['shipping_postcode'] = $shipping_address['postcode'];
+ $data['shipping_zone'] = $shipping_address['zone'];
+ $data['shipping_zone_id'] = $shipping_address['zone_id'];
+ $data['shipping_country'] = $shipping_address['country'];
+ $data['shipping_country_id'] = $shipping_address['country_id'];
+ $data['shipping_address_format'] = $shipping_address['address_format'];
+
+ $data['shipping_method'] = '';
+ if (isset($this->session->data['shipping_method']['title'])) {
+ $data['shipping_method'] = $this->session->data['shipping_method']['title'];
+ }
+
+ $data['shipping_code'] = '';
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $data['shipping_code'] = $this->session->data['shipping_method']['code'];
+ }
+ } else {
+ $data['shipping_firstname'] = '';
+ $data['shipping_lastname'] = '';
+ $data['shipping_company'] = '';
+ $data['shipping_address_1'] = '';
+ $data['shipping_address_2'] = '';
+ $data['shipping_city'] = '';
+ $data['shipping_postcode'] = '';
+ $data['shipping_zone'] = '';
+ $data['shipping_zone_id'] = '';
+ $data['shipping_country'] = '';
+ $data['shipping_country_id'] = '';
+ $data['shipping_address_format'] = '';
+ $data['shipping_method'] = '';
+ $data['shipping_code'] = '';
+ }
+
+ $product_data = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ $option_data[] = array(
+ 'product_option_id' => $option['product_option_id'],
+ 'product_option_value_id' => $option['product_option_value_id'],
+ 'option_id' => $option['option_id'],
+ 'option_value_id' => $option['option_value_id'],
+ 'name' => $option['name'],
+ 'value' => $option['value'],
+ 'type' => $option['type']
+ );
+ }
+
+ $product_data[] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'download' => $product['download'],
+ 'quantity' => $product['quantity'],
+ 'subtract' => $product['subtract'],
+ 'price' => $product['price'],
+ 'total' => $product['total'],
+ 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
+ 'reward' => $product['reward']
+ );
+ }
+
+ // Gift Voucher
+ $voucher_data = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $voucher) {
+ $voucher_data[] = array(
+ 'description' => $voucher['description'],
+ 'code' => token(10),
+ 'to_name' => $voucher['to_name'],
+ 'to_email' => $voucher['to_email'],
+ 'from_name' => $voucher['from_name'],
+ 'from_email' => $voucher['from_email'],
+ 'voucher_theme_id' => $voucher['voucher_theme_id'],
+ 'message' => $voucher['message'],
+ 'amount' => $voucher['amount']
+ );
+ }
+ }
+
+ $data['products'] = $product_data;
+ $data['vouchers'] = $voucher_data;
+ $data['totals'] = $totals;
+ $data['comment'] = $this->session->data['comment'];
+ $data['total'] = $total;
+
+ if (isset($this->request->cookie['tracking'])) {
+ $data['tracking'] = $this->request->cookie['tracking'];
+
+ $subtotal = $this->cart->getSubTotal();
+
+ // Affiliate
+ $this->load->model('affiliate/affiliate');
+
+ $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
+
+ if ($affiliate_info) {
+ $data['affiliate_id'] = $affiliate_info['affiliate_id'];
+ $data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
+ } else {
+ $data['affiliate_id'] = 0;
+ $data['commission'] = 0;
+ }
+
+ // Marketing
+ $this->load->model('checkout/marketing');
+
+ $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
+
+ if ($marketing_info) {
+ $data['marketing_id'] = $marketing_info['marketing_id'];
+ } else {
+ $data['marketing_id'] = 0;
+ }
+ } else {
+ $data['affiliate_id'] = 0;
+ $data['commission'] = 0;
+ $data['marketing_id'] = 0;
+ $data['tracking'] = '';
+ }
+
+ $data['language_id'] = $this->config->get('config_language_id');
+ $data['currency_id'] = $this->currency->getId($this->session->data['currency']);
+ $data['currency_code'] = $this->session->data['currency'];
+ $data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
+ $data['ip'] = $this->request->server['REMOTE_ADDR'];
+
+ if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
+ $data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
+ } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
+ $data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
+ } else {
+ $data['forwarded_ip'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $data['user_agent'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
+ $data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
+ } else {
+ $data['accept_language'] = '';
+ }
+
+ $this->load->model('account/custom_field');
+ $this->load->model('checkout/order');
+
+ $order_id = $this->model_checkout_order->addOrder($data);
+ $this->session->data['order_id'] = $order_id;
+
+ $this->load->model('extension/payment/pp_express');
+
+ $paypal_data = array(
+ 'TOKEN' => $this->session->data['paypal']['token'],
+ 'PAYERID' => $this->session->data['paypal']['payerid'],
+ 'METHOD' => 'DoExpressCheckoutPayment',
+ 'PAYMENTREQUEST_0_NOTIFYURL' => $this->url->link('extension/payment/pp_express/ipn', '', true),
+ 'RETURNFMFDETAILS' => 1
+ );
+
+ $paypal_data = array_merge($paypal_data, $this->model_extension_payment_pp_express->paymentRequestInfo());
+
+ $result = $this->model_extension_payment_pp_express->call($paypal_data);
+
+ if ($result['ACK'] == 'Success') {
+ //handle order status
+ switch($result['PAYMENTINFO_0_PAYMENTSTATUS']) {
+ case 'Canceled_Reversal':
+ $order_status_id = $this->config->get('payment_pp_express_canceled_reversal_status_id');
+ break;
+ case 'Completed':
+ $order_status_id = $this->config->get('payment_pp_express_completed_status_id');
+ break;
+ case 'Denied':
+ $order_status_id = $this->config->get('payment_pp_express_denied_status_id');
+ break;
+ case 'Expired':
+ $order_status_id = $this->config->get('payment_pp_express_expired_status_id');
+ break;
+ case 'Failed':
+ $order_status_id = $this->config->get('payment_pp_express_failed_status_id');
+ break;
+ case 'Pending':
+ $order_status_id = $this->config->get('payment_pp_express_pending_status_id');
+ break;
+ case 'Processed':
+ $order_status_id = $this->config->get('payment_pp_express_processed_status_id');
+ break;
+ case 'Refunded':
+ $order_status_id = $this->config->get('payment_pp_express_refunded_status_id');
+ break;
+ case 'Reversed':
+ $order_status_id = $this->config->get('payment_pp_express_reversed_status_id');
+ break;
+ case 'Voided':
+ $order_status_id = $this->config->get('payment_pp_express_voided_status_id');
+ break;
+ }
+
+ $this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
+
+ //add order to paypal table
+ $paypal_order_data = array(
+ 'order_id' => $order_id,
+ 'capture_status' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'Complete' : 'NotComplete'),
+ 'currency_code' => $result['PAYMENTINFO_0_CURRENCYCODE'],
+ 'authorization_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
+ 'total' => $result['PAYMENTINFO_0_AMT']
+ );
+
+ $paypal_order_id = $this->model_extension_payment_pp_express->addOrder($paypal_order_data);
+
+ //add transaction to paypal transaction table
+ $paypal_transaction_data = array(
+ 'paypal_order_id' => $paypal_order_id,
+ 'transaction_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
+ 'parent_id' => '',
+ 'note' => '',
+ 'msgsubid' => '',
+ 'receipt_id' => (isset($result['PAYMENTINFO_0_RECEIPTID']) ? $result['PAYMENTINFO_0_RECEIPTID'] : ''),
+ 'payment_type' => $result['PAYMENTINFO_0_PAYMENTTYPE'],
+ 'payment_status' => $result['PAYMENTINFO_0_PAYMENTSTATUS'],
+ 'pending_reason' => $result['PAYMENTINFO_0_PENDINGREASON'],
+ 'transaction_entity' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'payment' : 'auth'),
+ 'amount' => $result['PAYMENTINFO_0_AMT'],
+ 'debug_data' => json_encode($result)
+ );
+
+ $this->model_extension_payment_pp_express->addTransaction($paypal_transaction_data);
+
+ $recurring_products = $this->cart->getRecurringProducts();
+
+ //loop through any products that are recurring items
+ if ($recurring_products) {
+ $this->load->language('extension/payment/pp_express');
+
+ $this->load->model('checkout/recurring');
+
+ $billing_period = array(
+ 'day' => 'Day',
+ 'week' => 'Week',
+ 'semi_month' => 'SemiMonth',
+ 'month' => 'Month',
+ 'year' => 'Year'
+ );
+
+ foreach($recurring_products as $item) {
+ $data = array(
+ 'METHOD' => 'CreateRecurringPaymentsProfile',
+ 'TOKEN' => $this->session->data['paypal']['token'],
+ 'PROFILESTARTDATE' => gmdate("Y-m-d\TH:i:s\Z", gmmktime(gmdate("H"), gmdate("i")+5, gmdate("s"), gmdate("m"), gmdate("d"), gmdate("y"))),
+ 'BILLINGPERIOD' => $billing_period[$item['recurring']['frequency']],
+ 'BILLINGFREQUENCY' => $item['recurring']['cycle'],
+ 'TOTALBILLINGCYCLES' => $item['recurring']['duration'],
+ 'AMT' => $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'],
+ 'CURRENCYCODE' => $this->session->data['currency']
+ );
+
+ //trial information
+ if ($item['recurring']['trial']) {
+ $data_trial = array(
+ 'TRIALBILLINGPERIOD' => $billing_period[$item['recurring']['trial_frequency']],
+ 'TRIALBILLINGFREQUENCY' => $item['recurring']['trial_cycle'],
+ 'TRIALTOTALBILLINGCYCLES' => $item['recurring']['trial_duration'],
+ 'TRIALAMT' => $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity']
+ );
+
+ $trial_amt = $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
+ $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
+
+ $data = array_merge($data, $data_trial);
+ } else {
+ $trial_text = '';
+ }
+
+ $recurring_amt = $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
+ $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
+
+ if ($item['recurring']['duration'] > 0) {
+ $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
+ }
+
+ //create new recurring and set to pending status as no payment has been made yet.
+ $recurring_id = $this->model_checkout_recurring->addRecurring($order_id, $recurring_description, $item['recurring']);
+
+ $data['PROFILEREFERENCE'] = $recurring_id;
+ $data['DESC'] = $recurring_description;
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+
+ if (isset($result['PROFILEID'])) {
+ $this->model_checkout_recurring->addReference($recurring_id, $result['PROFILEID']);
+ } else {
+ // there was an error creating the recurring, need to log and also alert admin / user
+
+ }
+ }
+ }
+
+ $this->response->redirect($this->url->link('checkout/success'));
+
+ if (isset($result['REDIRECTREQUIRED']) && $result['REDIRECTREQUIRED'] == true) {
+ //- handle german redirect here
+ $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_complete-express-checkout&token=' . $this->session->data['paypal']['token']);
+ }
+ } else {
+ if ($result['L_ERRORCODE0'] == '10486') {
+ if (isset($this->session->data['paypal_redirect_count'])) {
+
+ if ($this->session->data['paypal_redirect_count'] == 2) {
+ $this->session->data['paypal_redirect_count'] = 0;
+ $this->session->data['error'] = $this->language->get('error_too_many_failures');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->session->data['paypal_redirect_count']++;
+ }
+ } else {
+ $this->session->data['paypal_redirect_count'] = 1;
+ }
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $this->response->redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
+ } else {
+ $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
+ }
+ }
+
+ $this->session->data['error_warning'] = $result['L_LONGMESSAGE0'];
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true));
+ }
+ } else {
+ $this->response->redirect($redirect);
+ }
+ }
+
+ public function checkout() {
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->response->redirect($this->url->link('checkout/cart'));
+ }
+
+ $this->load->model('extension/payment/pp_express');
+ $this->load->model('tool/image');
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $max_amount = $this->cart->getTotal() * 1.5;
+ $max_amount = $this->currency->format($max_amount, $this->session->data['currency'], '', false);
+
+ if ($this->cart->hasShipping()) {
+ $shipping = 0;
+
+ // PayPal requires some countries to use zone code (not name) to be sent in SHIPTOSTATE
+ $ship_to_state_codes = array(
+ '30', // Brazil
+ '38', // Canada
+ '105', // Italy
+ '138', // Mexico
+ '223', // USA
+ );
+
+ if (in_array($order_info['shipping_country_id'], $ship_to_state_codes)) {
+ $ship_to_state = $order_info['shipping_zone_code'];
+ } else {
+ $ship_to_state = $order_info['shipping_zone'];
+ }
+
+ $data_shipping = array(
+ 'PAYMENTREQUEST_0_SHIPTONAME' => html_entity_decode($order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname'], ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOSTREET' => html_entity_decode($order_info['shipping_address_1'], ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOSTREET2' => html_entity_decode($order_info['shipping_address_2'], ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOCITY' => html_entity_decode($order_info['shipping_city'], ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOSTATE' => html_entity_decode($ship_to_state, ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOZIP' => html_entity_decode($order_info['shipping_postcode'], ENT_QUOTES, 'UTF-8'),
+ 'PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE' => $order_info['shipping_iso_code_2'],
+ 'ADDROVERRIDE' => 1,
+ );
+ } else {
+ $shipping = 1;
+ $data_shipping = array();
+ }
+
+ $data = array(
+ 'METHOD' => 'SetExpressCheckout',
+ 'MAXAMT' => $max_amount,
+ 'RETURNURL' => $this->url->link('extension/payment/pp_express/checkoutReturn', '', true),
+ 'CANCELURL' => $this->url->link('checkout/checkout', '', true),
+ 'REQCONFIRMSHIPPING' => 0,
+ 'NOSHIPPING' => $shipping,
+ 'LANDINGPAGE' => 'Login',
+ 'LOGOIMG' => $this->model_tool_image->resize($this->config->get('payment_pp_express_logo'), 750, 90),
+ 'CHANNELTYPE' => 'Merchant',
+ );
+
+ $data = array_merge($data, $data_shipping);
+
+ if (isset($this->session->data['pp_login']['seamless']['access_token']) && (isset($this->session->data['pp_login']['seamless']['customer_id']) && $this->session->data['pp_login']['seamless']['customer_id'] == $this->customer->getId()) && $this->config->get('module_pp_login_seamless')) {
+ $data['IDENTITYACCESSTOKEN'] = $this->session->data['pp_login']['seamless']['access_token'];
+ }
+
+ $data = array_merge($data, $this->model_extension_payment_pp_express->paymentRequestInfo());
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+
+ /**
+ * If a failed PayPal setup happens, handle it.
+ */
+ if (!isset($result['TOKEN'])) {
+ $this->session->data['error'] = $result['L_LONGMESSAGE0'];
+ /**
+ * Unable to add error message to user as the session errors/success are not
+ * used on the cart or checkout pages - need to be added?
+ * If PayPal debug log is off then still log error to normal error log.
+ */
+ $this->log->write('Unable to create Paypal session' . json_encode($result));
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ $this->session->data['paypal']['token'] = $result['TOKEN'];
+
+ $json = array("token" => $result['TOKEN']);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function checkoutReturn() {
+ $this->load->language('extension/payment/pp_express');
+
+ $this->load->model('extension/payment/pp_express');
+ $this->load->model('checkout/order');
+
+ $data = array(
+ 'METHOD' => 'GetExpressCheckoutDetails',
+ 'TOKEN' => $this->session->data['paypal']['token']
+ );
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+
+ $this->session->data['paypal']['payerid'] = $result['PAYERID'];
+ $this->session->data['paypal']['result'] = $result;
+
+ $order_id = $this->session->data['order_id'];
+
+ $paypal_data = array(
+ 'TOKEN' => $this->session->data['paypal']['token'],
+ 'PAYERID' => $this->session->data['paypal']['payerid'],
+ 'METHOD' => 'DoExpressCheckoutPayment',
+ 'PAYMENTREQUEST_0_NOTIFYURL' => $this->url->link('extension/payment/pp_express/ipn', '', true),
+ 'RETURNFMFDETAILS' => 1
+ );
+
+ $paypal_data = array_merge($paypal_data, $this->model_extension_payment_pp_express->paymentRequestInfo());
+
+ $result = $this->model_extension_payment_pp_express->call($paypal_data);
+
+ if ($result['ACK'] == 'Success') {
+ //handle order status
+ switch($result['PAYMENTINFO_0_PAYMENTSTATUS']) {
+ case 'Canceled_Reversal':
+ $order_status_id = $this->config->get('payment_pp_express_canceled_reversal_status_id');
+ break;
+ case 'Completed':
+ $order_status_id = $this->config->get('payment_pp_express_completed_status_id');
+ break;
+ case 'Denied':
+ $order_status_id = $this->config->get('payment_pp_express_denied_status_id');
+ break;
+ case 'Expired':
+ $order_status_id = $this->config->get('payment_pp_express_expired_status_id');
+ break;
+ case 'Failed':
+ $order_status_id = $this->config->get('payment_pp_express_failed_status_id');
+ break;
+ case 'Pending':
+ $order_status_id = $this->config->get('payment_pp_express_pending_status_id');
+ break;
+ case 'Processed':
+ $order_status_id = $this->config->get('payment_pp_express_processed_status_id');
+ break;
+ case 'Refunded':
+ $order_status_id = $this->config->get('payment_pp_express_refunded_status_id');
+ break;
+ case 'Reversed':
+ $order_status_id = $this->config->get('payment_pp_express_reversed_status_id');
+ break;
+ case 'Voided':
+ $order_status_id = $this->config->get('payment_pp_express_voided_status_id');
+ break;
+ }
+
+ $this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
+
+ //add order to paypal table
+ $paypal_order_data = array(
+ 'order_id' => $order_id,
+ 'capture_status' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'Complete' : 'NotComplete'),
+ 'currency_code' => $result['PAYMENTINFO_0_CURRENCYCODE'],
+ 'authorization_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
+ 'total' => $result['PAYMENTINFO_0_AMT']
+ );
+
+ $paypal_order_id = $this->model_extension_payment_pp_express->addOrder($paypal_order_data);
+
+ //add transaction to paypal transaction table
+ $paypal_transaction_data = array(
+ 'paypal_order_id' => $paypal_order_id,
+ 'transaction_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
+ 'parent_id' => '',
+ 'note' => '',
+ 'msgsubid' => '',
+ 'receipt_id' => (isset($result['PAYMENTINFO_0_RECEIPTID']) ? $result['PAYMENTINFO_0_RECEIPTID'] : ''),
+ 'payment_type' => $result['PAYMENTINFO_0_PAYMENTTYPE'],
+ 'payment_status' => $result['PAYMENTINFO_0_PAYMENTSTATUS'],
+ 'pending_reason' => $result['PAYMENTINFO_0_PENDINGREASON'],
+ 'transaction_entity' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'payment' : 'auth'),
+ 'amount' => $result['PAYMENTINFO_0_AMT'],
+ 'debug_data' => json_encode($result)
+ );
+ $this->model_extension_payment_pp_express->addTransaction($paypal_transaction_data);
+
+ $recurring_products = $this->cart->getRecurringProducts();
+
+ //loop through any products that are recurring items
+ if ($recurring_products) {
+ $this->load->model('checkout/recurring');
+
+ $billing_period = array(
+ 'day' => 'Day',
+ 'week' => 'Week',
+ 'semi_month' => 'SemiMonth',
+ 'month' => 'Month',
+ 'year' => 'Year'
+ );
+
+ foreach ($recurring_products as $item) {
+ $data = array(
+ 'METHOD' => 'CreateRecurringPaymentsProfile',
+ 'TOKEN' => $this->session->data['paypal']['token'],
+ 'PROFILESTARTDATE' => gmdate("Y-m-d\TH:i:s\Z", gmmktime(gmdate('H'), gmdate('i') + 5, gmdate('s'), gmdate('m'), gmdate('d'), gmdate('y'))),
+ 'BILLINGPERIOD' => $billing_period[$item['recurring']['frequency']],
+ 'BILLINGFREQUENCY' => $item['recurring']['cycle'],
+ 'TOTALBILLINGCYCLES' => $item['recurring']['duration'],
+ 'AMT' => $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'],
+ 'CURRENCYCODE' => $this->session->data['currency']
+ );
+
+ //trial information
+ if ($item['recurring']['trial'] == 1) {
+ $data_trial = array(
+ 'TRIALBILLINGPERIOD' => $billing_period[$item['recurring']['trial_frequency']],
+ 'TRIALBILLINGFREQUENCY' => $item['recurring']['trial_cycle'],
+ 'TRIALTOTALBILLINGCYCLES' => $item['recurring']['trial_duration'],
+ 'TRIALAMT' => $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity']
+ );
+
+ $trial_amt = $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
+ $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
+
+ $data = array_merge($data, $data_trial);
+ } else {
+ $trial_text = '';
+ }
+
+ $recurring_amt = $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
+ $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
+
+ if ($item['recurring']['duration'] > 0) {
+ $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
+ }
+
+ //create new recurring and set to pending status as no payment has been made yet.
+ $recurring_id = $this->model_checkout_recurring->addRecurring($order_id, $recurring_description, $item['recurring']);
+
+ $data['PROFILEREFERENCE'] = $recurring_id;
+ $data['DESC'] = $recurring_description;
+
+ $result = $this->model_extension_payment_pp_express->call($data);
+
+ if (isset($result['PROFILEID'])) {
+ $this->model_checkout_recurring->editReference($recurring_id, $result['PROFILEID']);
+ } else {
+ // there was an error creating the recurring, need to log and also alert admin / user
+
+ }
+ }
+ }
+
+ if (isset($result['REDIRECTREQUIRED']) && $result['REDIRECTREQUIRED'] == true) {
+ //- handle german redirect here
+ $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_complete-express-checkout&token=' . $this->session->data['paypal']['token']);
+ } else {
+ $this->response->redirect($this->url->link('checkout/success'));
+ }
+ } else {
+ if ($result['L_ERRORCODE0'] == '10486') {
+ if (isset($this->session->data['paypal_redirect_count'])) {
+
+ if ($this->session->data['paypal_redirect_count'] == 2) {
+ $this->session->data['paypal_redirect_count'] = 0;
+ $this->session->data['error'] = $this->language->get('error_too_many_failures');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->session->data['paypal_redirect_count']++;
+ }
+ } else {
+ $this->session->data['paypal_redirect_count'] = 1;
+ }
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $this->response->redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
+ } else {
+ $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
+ }
+ }
+
+ $this->load->language('extension/payment/pp_express');
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('common/home'),
+ 'text' => $this->language->get('text_home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'href' => $this->url->link('checkout/cart'),
+ 'text' => $this->language->get('text_cart')
+ );
+
+ $data['heading_title'] = $this->language->get('error_heading_title');
+
+ $data['text_error'] = '<div class="warning">' . $result['L_ERRORCODE0'] . ' : ' . $result['L_LONGMESSAGE0'] . '</div>';
+
+ $data['button_continue'] = $this->language->get('button_continue');
+
+ $data['continue'] = $this->url->link('checkout/cart');
+
+ unset($this->session->data['success']);
+
+ $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . ' 404 Not Found');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('error/not_found', $data));
+ }
+ }
+
+ public function ipn() {
+ $this->load->model('extension/payment/pp_express');
+ $this->load->model('account/recurring');
+
+ $request = 'cmd=_notify-validate';
+
+ foreach ($_POST as $key => $value) {
+ $request .= '&' . $key . '=' . urlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
+ }
+
+ if ($this->config->get('payment_pp_express_test') == 1) {
+ $curl = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
+ } else {
+ $curl = curl_init('https://www.paypal.com/cgi-bin/webscr');
+ }
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = trim(curl_exec($curl));
+
+ if (!$response) {
+ $this->model_extension_payment_pp_express->log(array('error' => curl_error($curl),'error_no' => curl_errno($curl)), 'Curl failed');
+ }
+
+ $this->model_extension_payment_pp_express->log(array('request' => $request,'response' => $response), 'IPN data');
+
+ if ((string)$response == "VERIFIED") {
+ if (isset($this->request->post['transaction_entity'])) {
+ $this->log->write($this->request->post['transaction_entity']);
+ }
+
+ if (isset($this->request->post['txn_id'])) {
+ $transaction = $this->model_extension_payment_pp_express->getTransactionRow($this->request->post['txn_id']);
+ } else {
+ $transaction = false;
+ }
+
+ if (isset($this->request->post['parent_txn_id'])) {
+ $parent_transaction = $this->model_extension_payment_pp_express->getTransactionRow($this->request->post['parent_txn_id']);
+ } else {
+ $parent_transaction = false;
+ }
+
+ if ($transaction) {
+ //transaction exists, check for cleared payment or updates etc
+ $this->model_extension_payment_pp_express->log('Transaction exists', 'IPN data');
+
+ //if the transaction is pending but the new status is completed
+ if ($transaction['payment_status'] != $this->request->post['payment_status']) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = '" . $this->db->escape($this->request->post['payment_status']) . "' WHERE `transaction_id` = '" . $this->db->escape($transaction['transaction_id']) . "' LIMIT 1");
+ } elseif ($transaction['payment_status'] == 'Pending' && ($transaction['pending_reason'] != $this->request->post['pending_reason'])) {
+ //payment is still pending but the pending reason has changed, update it.
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `pending_reason` = '" . $this->db->escape($this->request->post['pending_reason']) . "' WHERE `transaction_id` = '" . $this->db->escape($transaction['transaction_id']) . "' LIMIT 1");
+ }
+ } else {
+ $this->model_extension_payment_pp_express->log('Transaction does not exist', 'IPN data');
+
+ if ($parent_transaction) {
+ //parent transaction exists
+ $this->model_extension_payment_pp_express->log('Parent transaction exists', 'IPN data');
+
+ //add new related transaction
+ $transaction = array(
+ 'paypal_order_id' => $parent_transaction['paypal_order_id'],
+ 'transaction_id' => $this->request->post['txn_id'],
+ 'parent_id' => $this->request->post['parent_txn_id'],
+ 'note' => '',
+ 'msgsubid' => '',
+ 'receipt_id' => (isset($this->request->post['receipt_id']) ? $this->request->post['receipt_id'] : ''),
+ 'payment_type' => (isset($this->request->post['payment_type']) ? $this->request->post['payment_type'] : ''),
+ 'payment_status' => (isset($this->request->post['payment_status']) ? $this->request->post['payment_status'] : ''),
+ 'pending_reason' => (isset($this->request->post['pending_reason']) ? $this->request->post['pending_reason'] : ''),
+ 'amount' => $this->request->post['mc_gross'],
+ 'debug_data' => json_encode($this->request->post),
+ 'transaction_entity' => (isset($this->request->post['transaction_entity']) ? $this->request->post['transaction_entity'] : '')
+ );
+
+ $this->model_extension_payment_pp_express->addTransaction($transaction);
+
+ /**
+ * If there has been a refund, log this against the parent transaction.
+ */
+ if (isset($this->request->post['payment_status']) && $this->request->post['payment_status'] == 'Refunded') {
+ if (($this->request->post['mc_gross'] * -1) == $parent_transaction['amount']) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = 'Refunded' WHERE `transaction_id` = '" . $this->db->escape($parent_transaction['transaction_id']) . "' LIMIT 1");
+ } else {
+ $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = 'Partially-Refunded' WHERE `transaction_id` = '" . $this->db->escape($parent_transaction['transaction_id']) . "' LIMIT 1");
+ }
+ }
+
+ /**
+ * If the capture payment is now complete
+ */
+ if (isset($this->request->post['auth_status']) && $this->request->post['auth_status'] == 'Completed' && $parent_transaction['payment_status'] == 'Pending') {
+ $captured = $this->currency->format($this->model_extension_payment_pp_express->getTotalCaptured($parent_transaction['paypal_order_id']), $this->session->data['currency'], false, false);
+ $refunded = $this->currency->format($this->model_extension_payment_pp_express->getRefundedTotal($parent_transaction['paypal_order_id']), $this->session->data['currency'], false, false);
+ $remaining = $this->currency->format($parent_transaction['amount'] - $captured + $refunded, $this->session->data['currency'], false, false);
+
+ $this->model_extension_payment_pp_express->log('Captured: ' . $captured, 'IPN data');
+ $this->model_extension_payment_pp_express->log('Refunded: ' . $refunded, 'IPN data');
+ $this->model_extension_payment_pp_express->log('Remaining: ' . $remaining, 'IPN data');
+
+ if ($remaining > 0.00) {
+ $transaction = array(
+ 'paypal_order_id' => $parent_transaction['paypal_order_id'],
+ 'transaction_id' => '',
+ 'parent_id' => $this->request->post['parent_txn_id'],
+ 'note' => '',
+ 'msgsubid' => '',
+ 'receipt_id' => '',
+ 'payment_type' => '',
+ 'payment_status' => 'Void',
+ 'pending_reason' => '',
+ 'amount' => '',
+ 'debug_data' => 'Voided after capture',
+ 'transaction_entity' => 'auth'
+ );
+
+ $this->model_extension_payment_pp_express->addTransaction($transaction);
+ }
+
+ $this->model_extension_payment_pp_express->updateOrder('Complete', $parent_transaction['order_id']);
+ }
+
+ } else {
+ //parent transaction doesn't exists, need to investigate?
+ $this->model_extension_payment_pp_express->log('Parent transaction not found', 'IPN data');
+ }
+ }
+
+ /*
+ * Subscription payments
+ *
+ * recurring ID should always exist if its a recurring payment transaction.
+ *
+ * also the reference will match a recurring payment ID
+ */
+ if (isset($this->request->post['txn_type'])) {
+ $this->model_extension_payment_pp_express->log($this->request->post['txn_type'], 'IPN data');
+
+ //payment
+ if ($this->request->post['txn_type'] == 'recurring_payment') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ $this->model_extension_payment_pp_express->log($recurring, 'IPN data');
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `amount` = '" . (float)$this->request->post['amount'] . "', `type` = '1'");
+
+ //as there was a payment the recurring is active, ensure it is set to active (may be been suspended before)
+ if ($recurring['status'] != 1) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'");
+ }
+ }
+ }
+
+ //suspend
+ if ($this->request->post['txn_type'] == 'recurring_payment_suspended') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '6'");
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 3 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1");
+ }
+ }
+
+ //suspend due to max failed
+ if ($this->request->post['txn_type'] == 'recurring_payment_suspended_due_to_max_failed_payment') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '7'");
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 3 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1");
+ }
+ }
+
+ //payment failed
+ if ($this->request->post['txn_type'] == 'recurring_payment_failed') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '4'");
+ }
+ }
+
+ //outstanding payment failed
+ if ($this->request->post['txn_type'] == 'recurring_payment_outstanding_payment_failed') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '8'");
+ }
+ }
+
+ //outstanding payment
+ if ($this->request->post['txn_type'] == 'recurring_payment_outstanding_payment') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `amount` = '" . (float)$this->request->post['amount'] . "', `type` = '2'");
+
+ //as there was a payment the recurring is active, ensure it is set to active (may be been suspended before)
+ if ($recurring['status'] != 1) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'");
+ }
+ }
+ }
+
+ //date_added
+ if ($this->request->post['txn_type'] == 'recurring_payment_profile_date_added') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '0'");
+
+ if ($recurring['status'] != 1) {
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'");
+ }
+ }
+ }
+
+ //cancelled
+ if ($this->request->post['txn_type'] == 'recurring_payment_profile_cancel') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false && $recurring['status'] != 3) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '5'");
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 4 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1");
+ }
+ }
+
+ //skipped
+ if ($this->request->post['txn_type'] == 'recurring_payment_skipped') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '3'");
+ }
+ }
+
+ //expired
+ if ($this->request->post['txn_type'] == 'recurring_payment_expired') {
+ $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']);
+
+ if ($recurring != false) {
+ $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '9'");
+ $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 5 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1");
+ }
+ }
+ }
+ } elseif ((string)$response == "INVALID") {
+ $this->model_extension_payment_pp_express->log(array('IPN was invalid'), 'IPN fail');
+ } else {
+ $this->model_extension_payment_pp_express->log('Response string unknown: ' . (string)$response, 'IPN data');
+ }
+
+ header("HTTP/1.1 200 Ok");
+ }
+
+ public function shipping() {
+ $this->shippingValidate($this->request->post['shipping_method']);
+
+ $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm'));
+ }
+
+ protected function shippingValidate($code) {
+ $this->load->language('checkout/cart');
+ $this->load->language('extension/payment/pp_express');
+
+ if (empty($code)) {
+ $this->session->data['error_warning'] = $this->language->get('error_shipping');
+ return false;
+ } else {
+ $shipping = explode('.', $code);
+
+ if (!isset($shipping[0]) || !isset($shipping[1]) || !isset($this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]])) {
+ $this->session->data['error_warning'] = $this->language->get('error_shipping');
+ return false;
+ } else {
+ $this->session->data['shipping_method'] = $this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]];
+ $this->session->data['success'] = $this->language->get('text_shipping_updated');
+ return true;
+ }
+ }
+ }
+
+ protected function validateCoupon() {
+ $this->load->model('extension/total/coupon');
+
+ $coupon_info = $this->model_extension_total_coupon->getCoupon($this->request->post['coupon']);
+
+ if ($coupon_info) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('error_coupon');
+ return false;
+ }
+ }
+
+ protected function validateVoucher() {
+ $this->load->model('extension/total/coupon');
+
+ $voucher_info = $this->model_extension_total_voucher->getVoucher($this->request->post['voucher']);
+
+ if ($voucher_info) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $this->language->get('error_voucher');
+ return false;
+ }
+ }
+
+ protected function validateReward() {
+ $points = $this->customer->getRewardPoints();
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ $error = '';
+
+ if (empty($this->request->post['reward'])) {
+ $error = $this->language->get('error_reward');
+ }
+
+ if ($this->request->post['reward'] > $points) {
+ $error = sprintf($this->language->get('error_points'), $this->request->post['reward']);
+ }
+
+ if ($this->request->post['reward'] > $points_total) {
+ $error = sprintf($this->language->get('error_maximum'), $points_total);
+ }
+
+ if (!$error) {
+ return true;
+ } else {
+ $this->session->data['error_warning'] = $error;
+ return false;
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/pp_payflow.php b/public/catalog/controller/extension/payment/pp_payflow.php
new file mode 100644
index 0000000..6f65897
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_payflow.php
@@ -0,0 +1,191 @@
+<?php
+class ControllerExtensionPaymentPPPayflow extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/pp_payflow');
+
+ $data['text_credit_card'] = $this->language->get('text_credit_card');
+ $data['text_start_date'] = $this->language->get('text_start_date');
+ $data['text_issue'] = $this->language->get('text_issue');
+ $data['text_loading'] = $this->language->get('text_loading');
+
+ $data['entry_cc_owner'] = $this->language->get('entry_cc_owner');
+ $data['entry_cc_type'] = $this->language->get('entry_cc_type');
+ $data['entry_cc_number'] = $this->language->get('entry_cc_number');
+ $data['entry_cc_start_date'] = $this->language->get('entry_cc_start_date');
+ $data['entry_cc_expire_date'] = $this->language->get('entry_cc_expire_date');
+ $data['entry_cc_cvv2'] = $this->language->get('entry_cc_cvv2');
+ $data['entry_cc_issue'] = $this->language->get('entry_cc_issue');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['owner'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+
+ $data['cards'] = array();
+
+ $data['cards'][] = array(
+ 'text' => 'Visa',
+ 'value' => '0'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'MasterCard',
+ 'value' => '1'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Maestro',
+ 'value' => '9'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Solo',
+ 'value' => 'S'
+ );
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_valid'] = array();
+
+ for ($i = $today['year'] - 10; $i < $today['year'] + 1; $i++) {
+ $data['year_valid'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/pp_payflow', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/pp_payflow');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if (!$this->config->get('payment_pp_payflow_transaction')) {
+ $payment_type = 'A';
+ } else {
+ $payment_type = 'S';
+ }
+
+ $request = 'USER=' . urlencode($this->config->get('payment_pp_payflow_user'));
+ $request .= '&VENDOR=' . urlencode($this->config->get('payment_pp_payflow_vendor'));
+ $request .= '&PARTNER=' . urlencode($this->config->get('payment_pp_payflow_partner'));
+ $request .= '&PWD=' . urlencode($this->config->get('payment_pp_payflow_password'));
+ $request .= '&TENDER=C';
+ $request .= '&TRXTYPE=' . $payment_type;
+ $request .= '&AMT=' . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $request .= '&CURRENCY=' . urlencode($order_info['currency_code']);
+ $request .= '&NAME=' . urlencode($this->request->post['cc_owner']);
+ $request .= '&STREET=' . urlencode($order_info['payment_address_1']);
+ $request .= '&CITY=' . urlencode($order_info['payment_city']);
+ $request .= '&STATE=' . urlencode(($order_info['payment_iso_code_2'] != 'US') ? $order_info['payment_zone'] : $order_info['payment_zone_code']);
+ $request .= '&COUNTRY=' . urlencode($order_info['payment_iso_code_2']);
+ $request .= '&ZIP=' . urlencode(str_replace(' ', '', $order_info['payment_postcode']));
+ $request .= '&CLIENTIP=' . urlencode($this->request->server['REMOTE_ADDR']);
+ $request .= '&EMAIL=' . urlencode($order_info['email']);
+ $request .= '&ACCT=' . urlencode(str_replace(' ', '', $this->request->post['cc_number']));
+ $request .= '&ACCTTYPE=' . urlencode($this->request->post['cc_type']);
+ $request .= '&CARDSTART=' . urlencode($this->request->post['cc_start_date_month'] . substr($this->request->post['cc_start_date_year'], - 2, 2));
+ $request .= '&EXPDATE=' . urlencode($this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], - 2, 2));
+ $request .= '&CVV2=' . urlencode($this->request->post['cc_cvv2']);
+ $request .= '&CARDISSUE=' . urlencode($this->request->post['cc_issue']);
+ $request .= '&BUTTONSOURCE=' . urlencode('OpenCart_2.0_PFP');
+
+ if (!$this->config->get('payment_pp_payflow_test')) {
+ $curl = curl_init('https://payflowpro.paypal.com');
+ } else {
+ $curl = curl_init('https://pilot-payflowpro.paypal.com');
+ }
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('X-VPS-REQUEST-ID: ' . md5($this->session->data['order_id'] . mt_rand())));
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ if (!$response) {
+ $this->log->write('DoDirectPayment failed: ' . curl_error($curl) . '(' . curl_errno($curl) . ')');
+ }
+
+ $response_info = array();
+
+ parse_str($response, $response_info);
+
+ $json = array();
+
+ if ($response_info['RESULT'] == '0') {
+ $message = '';
+
+ if (isset($response_info['AVSCODE'])) {
+ $message .= 'AVSCODE: ' . $response_info['AVSCODE'] . "\n";
+ }
+
+ if (isset($response_info['CVV2MATCH'])) {
+ $message .= 'CVV2MATCH: ' . $response_info['CVV2MATCH'] . "\n";
+ }
+
+ if (isset($response_info['TRANSACTIONID'])) {
+ $message .= 'TRANSACTIONID: ' . $response_info['TRANSACTIONID'] . "\n";
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_pp_payflow_order_status_id'), $message, false);
+
+ $json['success'] = $this->url->link('checkout/success');
+ } else {
+ switch ($response_info['RESULT']) {
+ case '1':
+ case '26':
+ $json['error'] = $this->language->get('error_config');
+ break;
+ case '7':
+ $json['error'] = $this->language->get('error_address');
+ break;
+ case '12':
+ $json['error'] = $this->language->get('error_declined');
+ break;
+ case '23':
+ case '24':
+ $json['error'] = $this->language->get('error_invalid');
+ break;
+ default:
+ $json['error'] = $this->language->get('error_general');
+ break;
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pp_payflow_iframe.php b/public/catalog/controller/extension/payment/pp_payflow_iframe.php
new file mode 100644
index 0000000..6a3102b
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_payflow_iframe.php
@@ -0,0 +1,154 @@
+<?php
+class ControllerExtensionPaymentPPPayflowIframe extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pp_payflow_iframe');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($this->config->get('payment_pp_payflow_iframe_test')) {
+ $mode = 'TEST';
+ } else {
+ $mode = 'LIVE';
+ }
+
+ $payflow_url = 'https://payflowlink.paypal.com';
+
+ if ($this->config->get('payment_pp_payflow_iframe_transaction_method') == 'sale') {
+ $transaction_type = 'S';
+ } else {
+ $transaction_type = 'A';
+ }
+
+ $secure_token_id = md5($this->session->data['order_id'] . mt_rand() . microtime());
+
+ $this->model_extension_payment_pp_payflow_iframe->addOrder($order_info['order_id'], $secure_token_id);
+
+ $shipping_country = $this->model_localisation_country->getCountry($order_info['shipping_country_id']);
+ $shipping_zone = $this->model_localisation_zone->getZone($order_info['shipping_zone_id']);
+
+ $payment_country = $this->model_localisation_country->getCountry($order_info['payment_country_id']);
+ $payment_zone = $this->model_localisation_zone->getZone($order_info['payment_zone_id']);
+
+ $url_params = array(
+ 'TENDER' => 'C',
+ 'TRXTYPE' => $transaction_type,
+ 'AMT' => $this->currency->format($order_info['total'], $order_info['currency_code'], false, false),
+ 'CURRENCY' => $order_info['currency_code'],
+ 'CREATESECURETOKEN' => 'Y',
+ 'SECURETOKENID' => $secure_token_id,
+ 'BILLTOFIRSTNAME' => $order_info['payment_firstname'],
+ 'BILLTOLASTNAME' => $order_info['payment_lastname'],
+ 'BILLTOSTREET' => trim($order_info['payment_address_1'] . ' ' . $order_info['payment_address_2']),
+ 'BILLTOCITY' => $order_info['payment_city'],
+ 'BILLTOSTATE' => $payment_zone['code'],
+ 'BILLTOZIP' => $order_info['payment_postcode'],
+ 'BILLTOCOUNTRY' => $payment_country['iso_code_2'],
+ );
+
+ if ($shipping_country) {
+ $url_params['SHIPTOFIRSTNAME'] = $order_info['shipping_firstname'];
+ $url_params['SHIPTOLASTNAME'] = $order_info['shipping_lastname'];
+ $url_params['SHIPTOSTREET'] = trim($order_info['shipping_address_1'] . ' ' . $order_info['shipping_address_2']);
+ $url_params['SHIPTOCITY'] = $order_info['shipping_city'];
+ $url_params['SHIPTOSTATE'] = $shipping_zone['code'];
+ $url_params['SHIPTOZIP'] = $order_info['shipping_postcode'];
+ $url_params['SHIPTOCOUNTRY'] = $shipping_country['iso_code_2'];
+ }
+
+ $response_params = $this->model_extension_payment_pp_payflow_iframe->call($url_params);
+
+ if (isset($response_params['SECURETOKEN'])) {
+ $secure_token = $response_params['SECURETOKEN'];
+ } else {
+ $secure_token = '';
+ }
+
+ $iframe_params = array(
+ 'MODE' => $mode,
+ 'SECURETOKENID' => $secure_token_id,
+ 'SECURETOKEN' => $secure_token,
+ );
+
+ $data['iframe_url'] = $payflow_url . '?' . http_build_query($iframe_params, '', "&");
+ $data['checkout_method'] = $this->config->get('payment_pp_payflow_iframe_checkout_method');
+ $data['button_confirm'] = $this->language->get('button_confirm');
+ $data['create'] = HTTPS_SERVER . 'index.php?route=extension/payment/pp_pro_iframe/create';
+
+ return $this->load->view('extension/payment/pp_payflow_iframe', $data);
+ }
+
+ public function paymentReturn() {
+ $data['url'] = $this->url->link('checkout/success');
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_payflow_iframe_return', $data));
+ }
+
+ public function paymentCancel() {
+ $data['url'] = $this->url->link('checkout/checkout');
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_payflow_iframe_return', $data));
+ }
+
+ public function paymentError() {
+ $data['url'] = $this->url->link('checkout/checkout');
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_payflow_iframe_return', $data));
+ }
+
+ public function paymentIpn() {
+ $this->load->model('extension/payment/pp_payflow_iframe');
+ $this->load->model('checkout/order');
+
+ if ($this->config->get('payment_pp_pro_iframe_debug')) {
+ $log = new Log('pp_pro_iframe.log');
+ $log->write('POST: ' . print_r($this->request->post, 1));
+ }
+
+ $order_id = $this->model_extension_payment_pp_payflow_iframe->getOrderId($this->request->post['SECURETOKENID']);
+
+ if ($order_id) {
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $url_params = array(
+ 'TENDER' => 'C',
+ 'TRXTYPE' => 'I',
+ 'ORIGID' => $this->request->post['PNREF'],
+ );
+
+ $response_params = $this->model_extension_payment_pp_payflow_iframe->call($url_params);
+
+ if ($order_info['order_status_id'] == 0 && $response_params['RESULT'] == '0' && $this->request->post['RESULT'] == 0) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_pp_payflow_iframe_order_status_id'));
+
+ if ($this->request->post['TYPE'] == 'S') {
+ $complete = 1;
+ } else {
+ $complete = 0;
+ }
+
+ $data = array(
+ 'secure_token_id' => $this->request->post['SECURETOKENID'],
+ 'transaction_reference' => $this->request->post['PNREF'],
+ 'transaction_type' => $this->request->post['TYPE'],
+ 'complete' => $complete,
+ );
+
+ $this->model_extension_payment_pp_payflow_iframe->updateOrder($data);
+
+ $data = array(
+ 'order_id' => $order_id,
+ 'type' => $this->request->post['TYPE'],
+ 'transaction_reference' => $this->request->post['PNREF'],
+ 'amount' => $this->request->post['AMT'],
+ );
+
+ $this->model_extension_payment_pp_payflow_iframe->addTransaction($data);
+ }
+ }
+
+ $this->response->setOutput('Ok');
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pp_pro.php b/public/catalog/controller/extension/payment/pp_pro.php
new file mode 100644
index 0000000..cafc44e
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_pro.php
@@ -0,0 +1,182 @@
+<?php
+class ControllerExtensionPaymentPPPro extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/pp_pro');
+
+ $data['cards'] = array();
+
+ $data['cards'][] = array(
+ 'text' => 'Visa',
+ 'value' => 'VISA'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'MasterCard',
+ 'value' => 'MASTERCARD'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Discover Card',
+ 'value' => 'DISCOVER'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'American Express',
+ 'value' => 'AMEX'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Maestro',
+ 'value' => 'SWITCH'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Solo',
+ 'value' => 'SOLO'
+ );
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_valid'] = array();
+
+ for ($i = $today['year'] - 10; $i < $today['year'] + 1; $i++) {
+ $data['year_valid'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/pp_pro', $data);
+ }
+
+ public function send() {
+ if (!$this->config->get('payment_pp_pro_transaction')) {
+ $payment_type = 'Authorization';
+ } else {
+ $payment_type = 'Sale';
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $request = 'METHOD=DoDirectPayment';
+ $request .= '&VERSION=51.0';
+ $request .= '&USER=' . urlencode($this->config->get('payment_pp_pro_username'));
+ $request .= '&PWD=' . urlencode($this->config->get('payment_pp_pro_password'));
+ $request .= '&SIGNATURE=' . urlencode($this->config->get('payment_pp_pro_signature'));
+ $request .= '&CUSTREF=' . (int)$order_info['order_id'];
+ $request .= '&PAYMENTACTION=' . $payment_type;
+ $request .= '&AMT=' . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $request .= '&CREDITCARDTYPE=' . $this->request->post['cc_type'];
+ $request .= '&ACCT=' . urlencode(str_replace(' ', '', $this->request->post['cc_number']));
+ $request .= '&CARDSTART=' . urlencode($this->request->post['cc_start_date_month'] . $this->request->post['cc_start_date_year']);
+ $request .= '&EXPDATE=' . urlencode($this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year']);
+ $request .= '&CVV2=' . urlencode($this->request->post['cc_cvv2']);
+
+ if ($this->request->post['cc_type'] == 'SWITCH' || $this->request->post['cc_type'] == 'SOLO') {
+ $request .= '&ISSUENUMBER=' . urlencode($this->request->post['cc_issue']);
+ }
+
+ $request .= '&FIRSTNAME=' . urlencode($order_info['payment_firstname']);
+ $request .= '&LASTNAME=' . urlencode($order_info['payment_lastname']);
+ $request .= '&EMAIL=' . urlencode($order_info['email']);
+ $request .= '&PHONENUM=' . urlencode($order_info['telephone']);
+ $request .= '&IPADDRESS=' . urlencode($this->request->server['REMOTE_ADDR']);
+ $request .= '&STREET=' . urlencode($order_info['payment_address_1']);
+ $request .= '&CITY=' . urlencode($order_info['payment_city']);
+ $request .= '&STATE=' . urlencode(($order_info['payment_iso_code_2'] != 'US') ? $order_info['payment_zone'] : $order_info['payment_zone_code']);
+ $request .= '&ZIP=' . urlencode($order_info['payment_postcode']);
+ $request .= '&COUNTRYCODE=' . urlencode($order_info['payment_iso_code_2']);
+ $request .= '&CURRENCYCODE=' . urlencode($order_info['currency_code']);
+ $request .= '&BUTTONSOURCE=' . urlencode('OpenCart_2.0_WPP');
+
+ if ($this->cart->hasShipping()) {
+ $request .= '&SHIPTONAME=' . urlencode($order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname']);
+ $request .= '&SHIPTOSTREET=' . urlencode($order_info['shipping_address_1']);
+ $request .= '&SHIPTOCITY=' . urlencode($order_info['shipping_city']);
+ $request .= '&SHIPTOSTATE=' . urlencode(($order_info['shipping_iso_code_2'] != 'US') ? $order_info['shipping_zone'] : $order_info['shipping_zone_code']);
+ $request .= '&SHIPTOCOUNTRYCODE=' . urlencode($order_info['shipping_iso_code_2']);
+ $request .= '&SHIPTOZIP=' . urlencode($order_info['shipping_postcode']);
+ } else {
+ $request .= '&SHIPTONAME=' . urlencode($order_info['payment_firstname'] . ' ' . $order_info['payment_lastname']);
+ $request .= '&SHIPTOSTREET=' . urlencode($order_info['payment_address_1']);
+ $request .= '&SHIPTOCITY=' . urlencode($order_info['payment_city']);
+ $request .= '&SHIPTOSTATE=' . urlencode(($order_info['payment_iso_code_2'] != 'US') ? $order_info['payment_zone'] : $order_info['payment_zone_code']);
+ $request .= '&SHIPTOCOUNTRYCODE=' . urlencode($order_info['payment_iso_code_2']);
+ $request .= '&SHIPTOZIP=' . urlencode($order_info['payment_postcode']);
+ }
+
+ if (!$this->config->get('payment_pp_pro_test')) {
+ $curl = curl_init('https://api-3t.paypal.com/nvp');
+ } else {
+ $curl = curl_init('https://api-3t.sandbox.paypal.com/nvp');
+ }
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ if (!$response) {
+ $this->log->write('DoDirectPayment failed: ' . curl_error($curl) . '(' . curl_errno($curl) . ')');
+ }
+
+ $response_info = array();
+
+ parse_str($response, $response_info);
+
+ $json = array();
+
+ if (($response_info['ACK'] == 'Success') || ($response_info['ACK'] == 'SuccessWithWarning')) {
+ $message = '';
+
+ if (isset($response_info['AVSCODE'])) {
+ $message .= 'AVSCODE: ' . $response_info['AVSCODE'] . "\n";
+ }
+
+ if (isset($response_info['CVV2MATCH'])) {
+ $message .= 'CVV2MATCH: ' . $response_info['CVV2MATCH'] . "\n";
+ }
+
+ if (isset($response_info['TRANSACTIONID'])) {
+ $message .= 'TRANSACTIONID: ' . $response_info['TRANSACTIONID'] . "\n";
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_pp_pro_order_status_id'), $message, false);
+
+ $json['success'] = $this->url->link('checkout/success');
+ } else {
+ $json['error'] = $response_info['L_LONGMESSAGE0'];
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pp_pro_iframe.php b/public/catalog/controller/extension/payment/pp_pro_iframe.php
new file mode 100644
index 0000000..30b6a5d
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_pro_iframe.php
@@ -0,0 +1,302 @@
+<?php
+class ControllerExtensionPaymentPPProIframe extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pp_pro_iframe');
+
+ $this->load->language('extension/payment/pp_pro_iframe');
+
+ if ($this->config->get('payment_pp_pro_iframe_checkout_method') == 'redirect') {
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $hosted_button_id = $this->constructButtonData($order_info);
+
+ if ($this->config->get('payment_pp_pro_iframe_test')) {
+ $data['url'] = 'https://securepayments.sandbox.paypal.com/webapps/HostedSoleSolutionApp/webflow/sparta/hostedSoleSolutionProcess';
+ } else {
+ $data['url'] = 'https://securepayments.paypal.com/webapps/HostedSoleSolutionApp/webflow/sparta/hostedSoleSolutionProcess';
+ }
+
+ if ($hosted_button_id) {
+ $data['code'] = $hosted_button_id;
+ $data['error_connection'] = '';
+ } else {
+ $data['error_connection'] = $this->language->get('error_connection');
+ }
+ }
+
+ $data['create'] = HTTPS_SERVER.'index.php?route=extension/payment/pp_pro_iframe/create';
+
+ $data['checkout_method'] = $this->config->get('payment_pp_pro_iframe_checkout_method');
+
+ return $this->load->view('extension/payment/pp_pro_iframe', $data);
+ }
+
+ public function create() {
+ $this->load->language('extension/payment/pp_pro_iframe');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/pp_pro_iframe');
+
+ $data['text_secure_connection'] = $this->language->get('text_secure_connection');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $hosted_button_id = $this->constructButtonData($order_info);
+
+ if ($hosted_button_id) {
+ $data['code'] = $hosted_button_id;
+
+ if ($this->config->get('payment_pp_pro_iframe_test')) {
+ $data['url'] = 'https://securepayments.sandbox.paypal.com/webapps/HostedSoleSolutionApp/webflow/sparta/hostedSoleSolutionProcess';
+ } else {
+ $data['url'] = 'https://securepayments.paypal.com/webapps/HostedSoleSolutionApp/webflow/sparta/hostedSoleSolutionProcess';
+ }
+
+ $data['error_connection'] = '';
+ } else {
+ $data['error_connection'] = $this->language->get('error_connection');
+ }
+
+ if (file_exists(DIR_APPLICATION . 'view/theme/' . $this->config->get('config_template') . '/stylesheet/stylesheet.css')) {
+ $data['stylesheet'] = '/catalog/view/theme/' . $this->config->get('config_template') . '/stylesheet/stylesheet.css';
+ } else {
+ $data['stylesheet'] = '/catalog/view/theme/default/stylesheet/stylesheet.css';
+ }
+
+ $this->response->setOutput($this->load->view('extension/payment/pp_pro_iframe_body', $data));
+ }
+
+ public function notify() {
+ $this->load->model('extension/payment/pp_pro_iframe');
+
+ if (isset($this->request->post['custom'])) {
+ $order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $this->request->post['custom']);
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $request = 'cmd=_notify-validate';
+
+ foreach ($this->request->post as $key => $value) {
+ $request .= '&' . $key . '=' . urlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
+ }
+
+ if (!$this->config->get('pp_pro_iframe')) {
+ $curl = curl_init('https://www.paypal.com/cgi-bin/webscr');
+ } else {
+ $curl = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
+ }
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = curl_exec($curl);
+
+ if (curl_errno($curl)) {
+ if ($this->config->get('payment_pp_pro_iframe_debug')) {
+ $log = new Log('pp_pro_iframe.log');
+ $log->write('pp_pro_iframe :: CURL failed ' . curl_error($curl) . '(' . curl_errno($curl) . ')');
+ }
+ } else {
+ if ($this->config->get('payment_pp_pro_iframe_debug')) {
+ $log = new Log('pp_pro_iframe.log');
+ $log->write('pp_pro_iframe :: IPN REQUEST: ' . $request);
+ $log->write('pp_pro_iframe :: IPN RESPONSE: ' . $response);
+ }
+
+ if ((strcmp($response, 'VERIFIED') == 0 || strcmp($response, 'UNVERIFIED') == 0) && isset($this->request->post['payment_status'])) {
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_canceled_reversal_status_id');
+
+ switch ($this->request->post['payment_status']) {
+ case 'Canceled_Reversal':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_canceled_reversal_status_id');
+ break;
+ case 'Completed':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_completed_status_id');
+ break;
+ case 'Denied':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_denied_status_id');
+ break;
+ case 'Expired':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_expired_status_id');
+ break;
+ case 'Failed':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_failed_status_id');
+ break;
+ case 'Pending':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_pending_status_id');
+ break;
+ case 'Processed':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_processed_status_id');
+ break;
+ case 'Refunded':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_processed_status_id');
+ break;
+ case 'Reversed':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_reversed_status_id');
+ break;
+ case 'Voided':
+ $order_status_id = $this->config->get('payment_pp_pro_iframe_voided_status_id');
+ break;
+ }
+
+ if (!$order_info['order_status_id']) {
+ $paypal_order_data = array(
+ 'order_id' => $order_id,
+ 'capture_status' => ($this->config->get('payment_pp_pro_iframe_transaction_method') == 'sale' ? 'Complete' : 'NotComplete'),
+ 'currency_code' => $this->request->post['mc_currency'],
+ 'authorization_id' => $this->request->post['txn_id'],
+ 'total' => $this->request->post['mc_gross'],
+ );
+
+ $paypal_iframe_order_id = $this->model_extension_payment_pp_pro_iframe->addOrder($paypal_order_data);
+
+ $paypal_transaction_data = array(
+ 'paypal_iframe_order_id' => $paypal_iframe_order_id,
+ 'transaction_id' => $this->request->post['txn_id'],
+ 'parent_id' => '',
+ 'note' => '',
+ 'msgsubid' => '',
+ 'receipt_id' => $this->request->post['receipt_id'],
+ 'payment_type' => $this->request->post['payment_type'],
+ 'payment_status' => $this->request->post['payment_status'],
+ 'pending_reason' => (isset($this->request->post['pending_reason']) ? $this->request->post['pending_reason'] : ''),
+ 'transaction_entity' => ($this->config->get('payment_pp_pro_iframe_transaction_method') == 'sale' ? 'payment' : 'auth'),
+ 'amount' => $this->request->post['mc_gross'],
+ 'debug_data' => json_encode($this->request->post),
+ );
+
+ $this->model_extension_payment_pp_pro_iframe->addTransaction($paypal_transaction_data);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
+ }
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+ }
+ }
+
+ curl_close($curl);
+ }
+ }
+
+ private function constructButtonData($order_info) {
+ $s_data = array();
+ $s_data['METHOD'] = 'BMCreateButton';
+ $s_data['VERSION'] = '65.2';
+ $s_data['BUTTONCODE'] = 'TOKEN';
+
+ $s_data['BUTTONLANGUAGE'] = 'en';
+ $s_data['BUTTONSOURCE'] = 'OpenCart_2.0_HSS';
+
+ $s_data['USER'] = $this->config->get('payment_pp_pro_iframe_user');
+ $s_data['SIGNATURE'] = $this->config->get('payment_pp_pro_iframe_sig');
+ $s_data['PWD'] = $this->config->get('payment_pp_pro_iframe_password');
+
+ $s_data['BUTTONTYPE'] = 'PAYMENT';
+ $s_data['L_BUTTONVAR0'] = 'subtotal=' . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $s_data['L_BUTTONVAR1'] = 'tax=0.00';
+ $s_data['L_BUTTONVAR2'] = 'shipping=0.00';
+ $s_data['L_BUTTONVAR3'] = 'handling=0.00';
+
+ if ($this->cart->hasShipping()) {
+ $s_data['L_BUTTONVAR4'] = 'first_name=' . urlencode($order_info['shipping_firstname']);
+ $s_data['L_BUTTONVAR5'] = 'last_name=' . urlencode($order_info['shipping_lastname']);
+ $s_data['L_BUTTONVAR6'] = 'address1=' . urlencode($order_info['shipping_address_1']);
+ $s_data['L_BUTTONVAR7'] = 'address2=' . urlencode($order_info['shipping_address_2']);
+ $s_data['L_BUTTONVAR8'] = 'city=' . urlencode($order_info['shipping_city']);
+ $s_data['L_BUTTONVAR9'] = 'state=' . urlencode($order_info['shipping_zone']);
+ $s_data['L_BUTTONVAR10'] = 'zip=' . urlencode($order_info['shipping_postcode']);
+ $s_data['L_BUTTONVAR11'] = 'country=' . urlencode($order_info['shipping_iso_code_2']);
+ } else {
+ $s_data['L_BUTTONVAR4'] = 'first_name=' . urlencode($order_info['payment_firstname']);
+ $s_data['L_BUTTONVAR5'] = 'last_name=' . urlencode($order_info['payment_lastname']);
+ $s_data['L_BUTTONVAR6'] = 'address1=' . urlencode($order_info['payment_address_1']);
+ $s_data['L_BUTTONVAR7'] = 'address2=' . urlencode($order_info['payment_address_2']);
+ $s_data['L_BUTTONVAR8'] = 'city=' . urlencode($order_info['payment_city']);
+ $s_data['L_BUTTONVAR9'] = 'state=' . urlencode($order_info['payment_zone']);
+ $s_data['L_BUTTONVAR10'] = 'zip=' . urlencode($order_info['payment_postcode']);
+ $s_data['L_BUTTONVAR11'] = 'country=' . urlencode($order_info['payment_iso_code_2']);
+ }
+
+ $s_data['L_BUTTONVAR12'] = 'billing_first_name=' . urlencode($order_info['payment_firstname']);
+ $s_data['L_BUTTONVAR13'] = 'billing_last_name=' . urlencode($order_info['payment_lastname']);
+ $s_data['L_BUTTONVAR14'] = 'billing_address1=' . urlencode($order_info['payment_address_1']);
+ $s_data['L_BUTTONVAR15'] = 'billing_address2=' . urlencode($order_info['payment_address_2']);
+ $s_data['L_BUTTONVAR16'] = 'billing_city=' . urlencode($order_info['payment_city']);
+ $s_data['L_BUTTONVAR17'] = 'billing_state=' . urlencode($order_info['payment_zone']);
+ $s_data['L_BUTTONVAR18'] = 'billing_zip=' . urlencode($order_info['payment_postcode']);
+ $s_data['L_BUTTONVAR19'] = 'billing_country=' . urlencode($order_info['payment_iso_code_2']);
+
+ $s_data['L_BUTTONVAR20'] = 'notify_url=' . $this->url->link('extension/payment/pp_pro_iframe/notify', '', true);
+ $s_data['L_BUTTONVAR21'] = 'cancel_return=' . $this->url->link('checkout/checkout', '', true);
+ $s_data['L_BUTTONVAR22'] = 'paymentaction=' . $this->config->get('payment_pp_pro_iframe_transaction_method');
+ $s_data['L_BUTTONVAR23'] = 'currency_code=' . urlencode($order_info['currency_code']);
+ $s_data['L_BUTTONVAR26'] = 'showBillingAddress=false';
+ $s_data['L_BUTTONVAR27'] = 'showShippingAddress=false';
+ $s_data['L_BUTTONVAR28'] = 'showBillingEmail=false';
+ $s_data['L_BUTTONVAR29'] = 'showBillingPhone=false';
+ $s_data['L_BUTTONVAR30'] = 'showCustomerName=true';
+ $s_data['L_BUTTONVAR31'] = 'showCardInfo=true';
+ $s_data['L_BUTTONVAR32'] = 'showHostedThankyouPage=false';
+ $s_data['L_BUTTONVAR33'] = 'bn=GBD';
+ $s_data['L_BUTTONVAR35'] = 'address_override=true';
+ $s_data['L_BUTTONVAR36'] = 'cpp_header_image=Red';
+ $s_data['L_BUTTONVAR44'] = 'bodyBgColor=#AEAEAE';
+ $s_data['L_BUTTONVAR47'] = 'PageTitleTextColor=Blue';
+ $s_data['L_BUTTONVAR48'] = 'PageCollapseBgColor=#AEAEAE';
+ $s_data['L_BUTTONVAR49'] = 'PageCollapseTextColor=#AEAEAE';
+ $s_data['L_BUTTONVAR50'] = 'PageButtonBgColor=#AEAEAE';
+ $s_data['L_BUTTONVAR51'] = 'orderSummaryBgColor=#AEAEAE';
+ $s_data['L_BUTTONVAR55'] = 'template=templateD';
+ $s_data['L_BUTTONVAR56'] = 'return=' . $this->url->link('checkout/success', '', true);
+ $s_data['L_BUTTONVAR57'] = 'custom=' . $this->encryption->encrypt($this->config->get('config_encryption'), $order_info['order_id']);
+
+ if ($this->config->get('payment_pp_pro_iframe_test')) {
+ $url = 'https://api-3t.sandbox.paypal.com/nvp';
+ } else {
+ $url = 'https://api-3t.paypal.com/nvp';
+ }
+
+ $curl = curl_init($url);
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($s_data, '', "&"));
+ curl_setopt($curl, CURLOPT_HTTPHEADER, array('X-VPS-REQUEST-ID: ' . md5($order_info['order_id'] . mt_rand())));
+
+ $response = curl_exec($curl);
+
+ $response_data = array();
+
+ parse_str($response, $response_data);
+
+ if ($this->config->get('payment_pp_pro_iframe_debug')) {
+ $log = new Log('pp_pro_iframe.log');
+ $log->write(print_r(json_encode($response_data), 1));
+ }
+
+ curl_close($curl);
+
+ if (!$response || !isset($response_data['HOSTEDBUTTONID'])) {
+ return false;
+ } else {
+ return $response_data['HOSTEDBUTTONID'];
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/pp_standard.php b/public/catalog/controller/extension/payment/pp_standard.php
new file mode 100644
index 0000000..c055672
--- /dev/null
+++ b/public/catalog/controller/extension/payment/pp_standard.php
@@ -0,0 +1,203 @@
+<?php
+class ControllerExtensionPaymentPPStandard extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/pp_standard');
+
+ $data['text_testmode'] = $this->language->get('text_testmode');
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $data['testmode'] = $this->config->get('payment_pp_standard_test');
+
+ if (!$this->config->get('payment_pp_standard_test')) {
+ $data['action'] = 'https://www.paypal.com/cgi-bin/webscr&pal=V4T754QB63XXL';
+ } else {
+ $data['action'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr&pal=V4T754QB63XXL';
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $data['business'] = $this->config->get('payment_pp_standard_email');
+ $data['item_name'] = html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8');
+
+ $data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ if ($option['type'] != 'file') {
+ $value = $option['value'];
+ } else {
+ $upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
+
+ if ($upload_info) {
+ $value = $upload_info['name'];
+ } else {
+ $value = '';
+ }
+ }
+
+ $option_data[] = array(
+ 'name' => $option['name'],
+ 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
+ );
+ }
+
+ $data['products'][] = array(
+ 'name' => htmlspecialchars($product['name']),
+ 'model' => htmlspecialchars($product['model']),
+ 'price' => $this->currency->format($product['price'], $order_info['currency_code'], false, false),
+ 'quantity' => $product['quantity'],
+ 'option' => $option_data,
+ 'weight' => $product['weight']
+ );
+ }
+
+ $data['discount_amount_cart'] = 0;
+
+ $total = $this->currency->format($order_info['total'] - $this->cart->getSubTotal(), $order_info['currency_code'], false, false);
+
+ if ($total > 0) {
+ $data['products'][] = array(
+ 'name' => $this->language->get('text_total'),
+ 'model' => '',
+ 'price' => $total,
+ 'quantity' => 1,
+ 'option' => array(),
+ 'weight' => 0
+ );
+ } else {
+ $data['discount_amount_cart'] -= $total;
+ }
+
+ $data['currency_code'] = $order_info['currency_code'];
+ $data['first_name'] = $order_info['payment_firstname'];
+ $data['last_name'] = $order_info['payment_lastname'];
+ $data['address1'] = $order_info['payment_address_1'];
+ $data['address2'] = $order_info['payment_address_2'];
+ $data['city'] = $order_info['payment_city'];
+ $data['zip'] = $order_info['payment_postcode'];
+ $data['country'] = $order_info['payment_iso_code_2'];
+ $data['email'] = $order_info['email'];
+ $data['invoice'] = $this->session->data['order_id'] . ' - ' . $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+ $data['lc'] = $this->session->data['language'];
+ $data['return'] = $this->url->link('checkout/success');
+ $data['notify_url'] = $this->url->link('extension/payment/pp_standard/callback', '', true);
+ $data['cancel_return'] = $this->url->link('checkout/checkout', '', true);
+
+ if (!$this->config->get('payment_pp_standard_transaction')) {
+ $data['paymentaction'] = 'authorization';
+ } else {
+ $data['paymentaction'] = 'sale';
+ }
+
+ $data['custom'] = $this->session->data['order_id'];
+
+ return $this->load->view('extension/payment/pp_standard', $data);
+ }
+ }
+
+ public function callback() {
+ if (isset($this->request->post['custom'])) {
+ $order_id = $this->request->post['custom'];
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $request = 'cmd=_notify-validate';
+
+ foreach ($this->request->post as $key => $value) {
+ $request .= '&' . $key . '=' . urlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
+ }
+
+ if (!$this->config->get('payment_pp_standard_test')) {
+ $curl = curl_init('https://www.paypal.com/cgi-bin/webscr');
+ } else {
+ $curl = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
+ }
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = curl_exec($curl);
+
+ if (!$response) {
+ $this->log->write('PP_STANDARD :: CURL failed ' . curl_error($curl) . '(' . curl_errno($curl) . ')');
+ }
+
+ if ($this->config->get('payment_pp_standard_debug')) {
+ $this->log->write('PP_STANDARD :: IPN REQUEST: ' . $request);
+ $this->log->write('PP_STANDARD :: IPN RESPONSE: ' . $response);
+ }
+
+ if ((strcmp($response, 'VERIFIED') == 0 || strcmp($response, 'UNVERIFIED') == 0) && isset($this->request->post['payment_status'])) {
+ $order_status_id = $this->config->get('config_order_status_id');
+
+ switch($this->request->post['payment_status']) {
+ case 'Canceled_Reversal':
+ $order_status_id = $this->config->get('payment_pp_standard_canceled_reversal_status_id');
+ break;
+ case 'Completed':
+ $receiver_match = (strtolower($this->request->post['receiver_email']) == strtolower($this->config->get('payment_pp_standard_email')));
+
+ $total_paid_match = ((float)$this->request->post['mc_gross'] == $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false));
+
+ if ($receiver_match && $total_paid_match) {
+ $order_status_id = $this->config->get('payment_pp_standard_completed_status_id');
+ }
+
+ if (!$receiver_match) {
+ $this->log->write('PP_STANDARD :: RECEIVER EMAIL MISMATCH! ' . strtolower($this->request->post['receiver_email']));
+ }
+
+ if (!$total_paid_match) {
+ $this->log->write('PP_STANDARD :: TOTAL PAID MISMATCH! ' . $this->request->post['mc_gross']);
+ }
+ break;
+ case 'Denied':
+ $order_status_id = $this->config->get('payment_pp_standard_denied_status_id');
+ break;
+ case 'Expired':
+ $order_status_id = $this->config->get('payment_pp_standard_expired_status_id');
+ break;
+ case 'Failed':
+ $order_status_id = $this->config->get('payment_pp_standard_failed_status_id');
+ break;
+ case 'Pending':
+ $order_status_id = $this->config->get('payment_pp_standard_pending_status_id');
+ break;
+ case 'Processed':
+ $order_status_id = $this->config->get('payment_pp_standard_processed_status_id');
+ break;
+ case 'Refunded':
+ $order_status_id = $this->config->get('payment_pp_standard_refunded_status_id');
+ break;
+ case 'Reversed':
+ $order_status_id = $this->config->get('payment_pp_standard_reversed_status_id');
+ break;
+ case 'Voided':
+ $order_status_id = $this->config->get('payment_pp_standard_voided_status_id');
+ break;
+ }
+
+ $this->model_checkout_order->addOrderHistory($order_id, $order_status_id);
+ } else {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+ }
+
+ curl_close($curl);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/realex.php b/public/catalog/controller/extension/payment/realex.php
new file mode 100644
index 0000000..62da983
--- /dev/null
+++ b/public/catalog/controller/extension/payment/realex.php
@@ -0,0 +1,258 @@
+<?php
+class ControllerExtensionPaymentRealex extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/realex');
+
+ $data['entry_cc_type'] = $this->language->get('entry_cc_type');
+
+ $data['help_select_card'] = $this->language->get('help_select_card');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($this->config->get('payment_realex_live_demo') == 1) {
+ $data['action'] = $this->config->get('payment_realex_live_url');
+ } else {
+ $data['action'] = $this->config->get('payment_realex_demo_url');
+ }
+
+ if ($this->config->get('payment_realex_card_select') == 1) {
+ $card_types = array(
+ 'visa' => $this->language->get('text_card_visa'),
+ 'mc' => $this->language->get('text_card_mc'),
+ 'amex' => $this->language->get('text_card_amex'),
+ 'switch' => $this->language->get('text_card_switch'),
+ 'laser' => $this->language->get('text_card_laser'),
+ 'diners' => $this->language->get('text_card_diners'),
+ );
+
+ $data['cards'] = array();
+
+ $accounts = $this->config->get('payment_realex_account');
+
+ foreach ($accounts as $card => $account) {
+ if (isset($account['enabled']) && $account['enabled'] == 1) {
+ $data['cards'][] = array(
+ 'type' => $card_types[$card],
+ 'account' => (isset($account['default']) && $account['default'] == 1 ? $this->config->get('payment_realex_merchant_id') : $account['merchant_id']),
+ );
+ }
+ }
+
+ $data['card_select'] = true;
+ } else {
+ $data['card_select'] = false;
+ }
+
+ if ($this->config->get('payment_realex_auto_settle') == 0) {
+ $data['settle'] = 0;
+ } elseif ($this->config->get('payment_realex_auto_settle') == 1) {
+ $data['settle'] = 1;
+ } elseif ($this->config->get('payment_realex_auto_settle') == 2) {
+ $data['settle'] = 'MULTI';
+ }
+
+ $data['tss'] = (int)$this->config->get('payment_realex_tss_check');
+ $data['merchant_id'] = $this->config->get('payment_realex_merchant_id');
+
+ $data['timestamp'] = strftime("%Y%m%d%H%M%S");
+ $data['order_id'] = $this->session->data['order_id'] . 'T' . $data['timestamp'] . mt_rand(1, 999);
+
+ $data['amount'] = round($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) * 100);
+ $data['currency'] = $order_info['currency_code'];
+
+ $tmp = $data['timestamp'] . '.' . $data['merchant_id'] . '.' . $data['order_id'] . '.' . $data['amount'] . '.' . $data['currency'];
+ $hash = sha1($tmp);
+ $tmp = $hash . '.' . $this->config->get('payment_realex_secret');
+ $data['hash'] = sha1($tmp);
+
+ $data['billing_code'] = filter_var(str_replace('-', '', $order_info['payment_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['payment_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['payment_country'] = $order_info['payment_iso_code_2'];
+
+ if ($this->cart->hasShipping()) {
+ $data['shipping_code'] = filter_var(str_replace('-', '', $order_info['shipping_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['shipping_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['shipping_country'] = $order_info['shipping_iso_code_2'];
+ } else {
+ $data['shipping_code'] = filter_var(str_replace('-', '', $order_info['payment_postcode']), FILTER_SANITIZE_NUMBER_INT) . '|' . filter_var(str_replace('-', '', $order_info['payment_address_1']), FILTER_SANITIZE_NUMBER_INT);
+ $data['shipping_country'] = $order_info['payment_iso_code_2'];
+ }
+
+ $data['response_url'] = HTTPS_SERVER . 'index.php?route=extension/payment/realex/notify';
+
+ return $this->load->view('extension/payment/realex', $data);
+ }
+
+ public function notify() {
+ $this->load->model('extension/payment/realex');
+
+ $this->model_extension_payment_realex->logger(print_r($this->request->post, 1));
+
+ $this->load->language('extension/payment/realex');
+
+ $hash = sha1($this->request->post['TIMESTAMP'] . '.' . $this->config->get('payment_realex_merchant_id') . '.' . $this->request->post['ORDER_ID'] . '.' . $this->request->post['RESULT'] . '.' . $this->request->post['MESSAGE'] . '.' . $this->request->post['PASREF'] . '.' . $this->request->post['AUTHCODE']);
+ $tmp = $hash . '.' . $this->config->get('payment_realex_secret');
+ $hash = sha1($tmp);
+
+ //Check to see if hashes match or not
+ if ($hash != $this->request->post['SHA1HASH']) {
+ $data['text_response'] = $this->language->get('text_hash_failed');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->load->model('checkout/order');
+
+ $order_id_parts = explode('T', $this->request->post['ORDER_ID']);
+ $order_id = (int)$order_id_parts[0];
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $auto_settle = (int)$this->config->get('payment_realex_auto_settle');
+ $tss = (int)$this->config->get('payment_realex_tss_check');
+
+ $message = '<strong>' . $this->language->get('text_result') . ':</strong> ' . $this->request->post['RESULT'];
+ $message .= '<br /><strong>' . $this->language->get('text_message') . ':</strong> ' . $this->request->post['MESSAGE'];
+
+ if (isset($this->request->post['ORDER_ID'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_order_ref') . ':</strong> ' . $this->request->post['ORDER_ID'];
+ }
+
+ if (isset($this->request->post['CVNRESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_cvn_result') . ':</strong> ' . $this->request->post['CVNRESULT'];
+ }
+
+ if (isset($this->request->post['AVSPOSTCODERESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_avs_postcode') . ':</strong> ' . $this->request->post['AVSPOSTCODERESULT'];
+ }
+
+ if (isset($this->request->post['AVSADDRESSRESULT'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_avs_address') . ':</strong> ' . $this->request->post['AVSADDRESSRESULT'];
+ }
+
+ //3D Secure message
+ if (isset($this->request->post['ECI']) && isset($this->request->post['CAVV']) && isset($this->request->post['XID'])) {
+ $eci = $this->request->post['ECI'];
+
+ if (($this->request->post['ECI'] == 6 || $this->request->post['ECI'] == 1) && empty($this->request->post['CAVV']) && empty($this->request->post['XID'])) {
+ $scenario_id = 1;
+ }
+
+ if (($this->request->post['ECI'] == 5 || $this->request->post['ECI'] == 0) && !empty($this->request->post['CAVV']) && !empty($this->request->post['XID'])) {
+ $scenario_id = 5;
+ }
+
+ if (($this->request->post['ECI'] == 6 || $this->request->post['ECI'] == 1) && !empty($this->request->post['CAVV']) && !empty($this->request->post['XID'])) {
+ $scenario_id = 6;
+ }
+
+ if (isset($scenario_id)) {
+ $scenario_message = $this->language->get('text_3d_s' . $scenario_id);
+ } else {
+ if (isset($this->request->post['CARDTYPE'])) {
+ if ($this->request->post['CARDTYPE'] == 'VISA') {
+ $eci = 7;
+ } else {
+ $eci = 2;
+ }
+ }
+
+ $scenario_message = $this->language->get('text_3d_liability');
+ }
+
+ $message .= '<br /><strong>' . $this->language->get('text_eci') . ':</strong> (' . $eci . ') ' . $scenario_message;
+ }
+
+ if ($tss == 1 && isset($this->request->post['TSS'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_tss') . ':</strong> ' . $this->request->post['TSS'];
+ }
+
+ if (isset($this->request->post['TIMESTAMP'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_timestamp') . ':</strong> ' . $this->request->post['TIMESTAMP'];
+ }
+
+ if (isset($this->request->post['CARDDIGITS'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_digits') . ':</strong> ' . $this->request->post['CARDDIGITS'];
+ }
+
+ if (isset($this->request->post['CARDTYPE'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_type') . ':</strong> ' . $this->request->post['CARDTYPE'];
+ }
+
+ if (isset($this->request->post['EXPDATE'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_exp') . ':</strong> ' . $this->request->post['EXPDATE'];
+ }
+
+ if (isset($this->request->post['CARDNAME'])) {
+ $message .= '<br /><strong>' . $this->language->get('text_card_name') . ':</strong> ' . $this->request->post['CARDNAME'];
+ }
+
+ if (isset($this->request->post['DCCAUTHCARDHOLDERAMOUNT']) && isset($this->request->post['DCCAUTHRATE'])) {
+ $message .= '<br /><strong>DCCAUTHCARDHOLDERAMOUNT:</strong> ' . $this->request->post['DCCAUTHCARDHOLDERAMOUNT'];
+ $message .= '<br /><strong>DCCAUTHRATE:</strong> ' . $this->request->post['DCCAUTHRATE'];
+ $message .= '<br /><strong>DCCAUTHCARDHOLDERCURRENCY:</strong> ' . $this->request->post['DCCAUTHCARDHOLDERCURRENCY'];
+ $message .= '<br /><strong>DCCAUTHMERCHANTCURRENCY:</strong> ' . $this->request->post['DCCAUTHMERCHANTCURRENCY'];
+ $message .= '<br /><strong>DCCAUTHMERCHANTAMOUNT:</strong> ' . $this->request->post['DCCAUTHMERCHANTAMOUNT'];
+ $message .= '<br /><strong>DCCCCP:</strong> ' . $this->request->post['DCCCCP'];
+ $message .= '<br /><strong>DCCRATE:</strong> ' . $this->request->post['DCCRATE'];
+ $message .= '<br /><strong>DCCMARGINRATEPERCENTAGE:</strong> ' . $this->request->post['DCCMARGINRATEPERCENTAGE'];
+ $message .= '<br /><strong>DCCEXCHANGERATESOURCENAME:</strong> ' . $this->request->post['DCCEXCHANGERATESOURCENAME'];
+ $message .= '<br /><strong>DCCCOMMISSIONPERCENTAGE:</strong> ' . $this->request->post['DCCCOMMISSIONPERCENTAGE'];
+ $message .= '<br /><strong>DCCEXCHANGERATESOURCETIMESTAMP:</strong> ' . $this->request->post['DCCEXCHANGERATESOURCETIMESTAMP'];
+ $message .= '<br /><strong>DCCCHOICE:</strong> ' . $this->request->post['DCCCHOICE'];
+ }
+
+ if ($this->request->post['RESULT'] == "00") {
+ $realex_order_id = $this->model_extension_payment_realex->addOrder($order_info, $this->request->post['PASREF'], $this->request->post['AUTHCODE'], $this->request->post['ACCOUNT'], $this->request->post['ORDER_ID']);
+
+ if ($auto_settle == 1) {
+ $this->model_extension_payment_realex->addTransaction($realex_order_id, 'payment', $order_info);
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_realex_order_status_success_settled_id'), $message, false);
+ } else {
+ $this->model_extension_payment_realex->addTransaction($realex_order_id, 'auth', 0.00);
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_realex_order_status_success_unsettled_id'), $message, false);
+ }
+
+ $data['text_response'] = $this->language->get('text_success');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/success', '', true));
+ } elseif ($this->request->post['RESULT'] == "101") {
+ // Decline
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "102") {
+ // Referal B
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_pending_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "103") {
+ // Referal A
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_stolen_id'), $message);
+ $data['text_response'] = $this->language->get('text_decline');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "200") {
+ // Error Connecting to Bank
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "204") {
+ // Error Connecting to Bank
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } elseif ($this->request->post['RESULT'] == "205") {
+ // Comms Error
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_bank_id'), $message);
+ $data['text_response'] = $this->language->get('text_bank_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ } else {
+ // Other error
+ $this->model_extension_payment_realex->addHistory($order_id, $this->config->get('payment_realex_order_status_decline_id'), $message);
+ $data['text_response'] = $this->language->get('text_generic_error');
+ $data['text_link'] = sprintf($this->language->get('text_link'), $this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ $this->response->setOutput($this->load->view('extension/payment/realex_response', $data));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/realex_remote.php b/public/catalog/controller/extension/payment/realex_remote.php
new file mode 100644
index 0000000..ba08fd3
--- /dev/null
+++ b/public/catalog/controller/extension/payment/realex_remote.php
@@ -0,0 +1,349 @@
+<?php
+class ControllerExtensionPaymentRealexRemote extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/realex_remote');
+
+ $data['text_credit_card'] = $this->language->get('text_credit_card');
+ $data['text_loading'] = $this->language->get('text_loading');
+ $data['text_wait'] = $this->language->get('text_wait');
+ $data['entry_cc_type'] = $this->language->get('entry_cc_type');
+ $data['entry_cc_number'] = $this->language->get('entry_cc_number');
+ $data['entry_cc_name'] = $this->language->get('entry_cc_name');
+ $data['entry_cc_expire_date'] = $this->language->get('entry_cc_expire_date');
+ $data['entry_cc_cvv2'] = $this->language->get('entry_cc_cvv2');
+ $data['entry_cc_issue'] = $this->language->get('entry_cc_issue');
+ $data['help_start_date'] = $this->language->get('help_start_date');
+ $data['help_issue'] = $this->language->get('help_issue');
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $accounts = $this->config->get('payment_realex_remote_account');
+
+ $card_types = array(
+ 'visa' => $this->language->get('text_card_visa'),
+ 'mc' => $this->language->get('text_card_mc'),
+ 'amex' => $this->language->get('text_card_amex'),
+ 'switch' => $this->language->get('text_card_switch'),
+ 'laser' => $this->language->get('text_card_laser'),
+ 'diners' => $this->language->get('text_card_diners'),
+ );
+
+ $data['cards'] = array();
+
+ foreach ($accounts as $card => $account) {
+ if (isset($account['enabled']) && $account['enabled'] == 1) {
+ $data['cards'][] = array(
+ 'code' => $card,
+ 'text' => $card_types[$card],
+ );
+ }
+ }
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/realex_remote', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/realex_remote');
+
+ $this->load->language('extension/payment/realex_remote');
+
+ if ($this->request->post['cc_number'] == '') {
+ $json['error'] = $this->language->get('error_card_number');
+ }
+
+ if ($this->request->post['cc_name'] == '') {
+ $json['error'] = $this->language->get('error_card_name');
+ }
+
+ if (strlen($this->request->post['cc_cvv2']) != 3 && strlen($this->request->post['cc_cvv2']) != 4) {
+ $json['error'] = $this->language->get('error_card_cvv');
+ }
+
+ if (isset($json['error'])) {
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ }
+
+ $order_id = $this->session->data['order_id'];
+
+ $order_ref = $order_id . 'T' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $amount = round($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) * 100);
+ $currency = $order_info['currency_code'];
+
+ $accounts = $this->config->get('payment_realex_remote_account');
+
+ if (isset($accounts[$this->request->post['cc_type']]['default']) && $accounts[$this->request->post['cc_type']]['default'] == 1) {
+ $account = $this->config->get('payment_realex_remote_merchant_id');
+ } else {
+ $account = $accounts[$this->request->post['cc_type']]['merchant_id'];
+ }
+
+ $eci_ref = '';
+ $eci = '';
+ $cavv = '';
+ $xid = '';
+
+ if ($this->config->get('payment_realex_remote_3d') == 1) {
+ if ($this->request->post['cc_type'] == 'visa' || $this->request->post['cc_type'] == 'mc' || $this->request->post['cc_type'] == 'amex') {
+ $verify_3ds = $this->model_extension_payment_realex_remote->checkEnrollment($account, $amount, $currency, $order_ref);
+
+ $this->model_extension_payment_realex_remote->logger('Verify 3DS result:\r\n' . print_r($verify_3ds, 1));
+
+ // Proceed to 3D secure
+ if (isset($verify_3ds->result) && $verify_3ds->result == '00') {
+ $enc_data = array(
+ 'account' => $account,
+ 'amount' => $amount,
+ 'currency' => $currency,
+ 'order_id' => $order_id,
+ 'order_ref' => $order_ref,
+ 'cc_number' => $this->request->post['cc_number'],
+ 'cc_expire' => $this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year'],
+ 'cc_name' => $this->request->post['cc_name'],
+ 'cc_type' => $this->request->post['cc_type'],
+ 'cc_cvv2' => $this->request->post['cc_cvv2'],
+ 'cc_issue' => $this->request->post['cc_issue']
+ );
+
+ $md = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode($enc_data));
+
+ $json = array();
+ $json['ACSURL'] = (string)$verify_3ds->url;
+ $json['MD'] = $md;
+ $json['PaReq'] = (string)$verify_3ds->pareq;
+ $json['TermUrl'] = $this->url->link('extension/payment/realex_remote/acsReturn', '', true);
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ }
+
+ // Cardholder Not Enrolled. Shift in liability. ECI = 6
+ if (isset($verify_3ds->result) && $verify_3ds->result == '110' && isset($verify_3ds->enrolled) && $verify_3ds->enrolled == 'N') {
+ $eci_ref = 1;
+ $xid = '';
+ $cavv = '';
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 1;
+ } else {
+ $eci = 6;
+ }
+ }
+
+ // Unable to Verify Enrollment. No shift in liability. ECI = 7
+ if (isset($verify_3ds->result) && $verify_3ds->result == '110' && isset($verify_3ds->enrolled) && $verify_3ds->enrolled == 'U') {
+ if ($this->config->get('payment_realex_remote_liability') != 1) {
+ $this->load->language('extension/payment/realex_remote');
+
+ $json['error'] = $this->language->get('error_3d_unable');
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ } else {
+ $eci_ref = 2;
+ $xid = '';
+ $cavv = '';
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+ }
+ }
+
+ // Invalid response from Enrollment Server. No shift in liability. ECI = 7
+ if (isset($verify_3ds->result) && $verify_3ds->result >= 500 && $verify_3ds->result < 600) {
+ if ($this->config->get('payment_realex_remote_liability') != 1) {
+ $this->load->language('extension/payment/realex_remote');
+
+ $json['error'] = (string)$verify_3ds->message;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ $this->response->output();
+ die();
+ } else {
+ $eci_ref = 3;
+ if ($this->request->post['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+ }
+ }
+ }
+ }
+
+ $capture_result = $this->model_extension_payment_realex_remote->capturePayment(
+ $account,
+ $amount,
+ $currency,
+ $order_id,
+ $order_ref,
+ $this->request->post['cc_number'],
+ $this->request->post['cc_expire_date_month'] . $this->request->post['cc_expire_date_year'],
+ $this->request->post['cc_name'],
+ $this->request->post['cc_type'],
+ $this->request->post['cc_cvv2'],
+ $this->request->post['cc_issue'],
+ $eci_ref,
+ $eci,
+ $cavv,
+ $xid
+ );
+
+ $this->model_extension_payment_realex_remote->logger('Capture result:\r\n' . print_r($capture_result, 1));
+
+ if ($capture_result->result != '00') {
+ $json['error'] = (string)$capture_result->message . ' (' . (int)$capture_result->result . ')';
+ } else {
+ $json['success'] = $this->url->link('checkout/success');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function acsReturn() {
+ if (isset($this->session->data['order_id'])) {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/realex_remote');
+
+ $post = $this->request->post;
+
+ $md = json_decode($this->encryption->decrypt($this->config->get('config_encryption'), $post['MD']), true);
+
+ $signature_result = $this->model_extension_payment_realex_remote->enrollmentSignature($md['account'], $md['amount'], $md['currency'], $md['order_ref'], $md['cc_number'], $md['cc_expire'], $md['cc_type'], $md['cc_name'], $post['PaRes']);
+
+ $this->model_extension_payment_realex_remote->logger('Signature result:\r\n' . print_r($signature_result, 1));
+
+ if ($signature_result->result == '00' && (strtoupper($signature_result->threedsecure->status) == 'Y' || strtoupper($signature_result->threedsecure->status) == 'A')) {
+ if (strtoupper($signature_result->threedsecure->status) == 'Y') {
+ $eci_ref = 5;
+ } else {
+ $eci_ref = 6;
+ }
+
+ $eci = (string)$signature_result->threedsecure->eci;
+ $cavv = (string)$signature_result->threedsecure->cavv;
+ $xid = (string)$signature_result->threedsecure->xid;
+ } else {
+ if ($md['cc_type'] == 'mc') {
+ $eci = 0;
+ } else {
+ $eci = 7;
+ }
+
+ // Enrolled but invalid response from ACS. No shift in liability. ECI = 7
+ if ($signature_result->result == '110' && strtoupper($signature_result->threedsecure->status) == 'Y') {
+ $eci_ref = 4;
+ $cavv = (string)$signature_result->threedsecure->cavv;
+ $xid = (string)$signature_result->threedsecure->xid;
+ }
+
+ // Incorrect password entered. No shift in liability. ECI = 7
+ if ($signature_result->result == '00' && strtoupper($signature_result->threedsecure->status) == 'N') {
+ $eci_ref = 7;
+ $xid = (string)$signature_result->threedsecure->xid;
+ $cavv = '';
+ }
+
+ // Authentication Unavailable. No shift in liability. ECI = 7
+ if ($signature_result->result == '00' && strtoupper($signature_result->threedsecure->status) == 'U') {
+ $eci_ref = 8;
+ $xid = (string)$signature_result->threedsecure->xid;
+ $cavv = '';
+ }
+
+ // Invalid response from ACS. No shift in liability. ECI = 7
+ if (isset($signature_result->result) && $signature_result->result >= 500 && $signature_result->result < 600) {
+ $eci_ref = 9;
+ $xid = '';
+ $cavv = '';
+ }
+
+ if ($this->config->get('payment_realex_remote_liability') != 1) {
+ // this is the check for liability shift - if the merchant does not want to accept, redirect to checkout with message
+ $this->load->language('extension/payment/realex_remote');
+
+ $message = $this->language->get('error_3d_unsuccessful');
+ $message .= '<br /><strong>' . $this->language->get('text_eci') . ':</strong> (' . $eci . ') ' . $this->language->get('text_3d_s' . (int)$eci_ref);
+ $message .= '<br /><strong>' . $this->language->get('text_timestamp') . ':</strong> ' . (string)strftime("%Y%m%d%H%M%S");
+ $message .= '<br /><strong>' . $this->language->get('text_order_ref') . ':</strong> ' . (string)$md['order_ref'];
+
+ if ($this->config->get('payment_realex_remote_card_data_status') == 1) {
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_type') . ':</strong> ' . (string)$md['cc_type'];
+ $message .= '<br /><strong>' . $this->language->get('text_last_digits') . ':</strong> ' . (string)substr($md['cc_number'], -4);
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_expire_date') . ':</strong> ' . (string)$md['cc_expire'];
+ $message .= '<br /><strong>' . $this->language->get('entry_cc_name') . ':</strong> ' . (string)$md['cc_name'];
+ }
+
+ $this->model_extension_payment_realex_remote->addHistory($md['order_id'], $this->config->get('payment_realex_remote_order_status_decline_id'), $message);
+
+ $this->session->data['error'] = $this->language->get('error_3d_unsuccessful');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ die();
+ }
+ }
+
+ $capture_result = $this->model_extension_payment_realex_remote->capturePayment(
+ $md['account'],
+ $md['amount'],
+ $md['currency'],
+ $md['order_id'],
+ $md['order_ref'],
+ $md['cc_number'],
+ $md['cc_expire'],
+ $md['cc_name'],
+ $md['cc_type'],
+ $md['cc_cvv2'],
+ $md['cc_issue'],
+ $eci_ref,
+ $eci,
+ $cavv,
+ $xid
+ );
+
+ $this->model_extension_payment_realex_remote->logger('Capture result:\r\n' . print_r($capture_result, 1));
+
+ if ($capture_result->result != '00') {
+ $this->session->data['error'] = (string)$capture_result->message . ' (' . (int)$capture_result->result . ')';
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ } else {
+ $this->response->redirect($this->url->link('checkout/success'));
+ }
+ } else {
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/sagepay_direct.php b/public/catalog/controller/extension/payment/sagepay_direct.php
new file mode 100644
index 0000000..3462a1e
--- /dev/null
+++ b/public/catalog/controller/extension/payment/sagepay_direct.php
@@ -0,0 +1,470 @@
+<?php
+class ControllerExtensionPaymentSagepayDirect extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/sagepay_direct');
+
+ if (isset($this->session->data['success'])) {
+ $data['success'] = $this->session->data['success'];
+ unset($this->session->data['success']);
+ } else {
+ $data['success'] = '';
+ }
+
+ $data['cards'] = array();
+
+ $data['cards'][] = array(
+ 'text' => 'Visa',
+ 'value' => 'VISA'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'MasterCard',
+ 'value' => 'MC'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Visa Delta/Debit',
+ 'value' => 'DELTA'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Solo',
+ 'value' => 'SOLO'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Maestro',
+ 'value' => 'MAESTRO'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Visa Electron UK Debit',
+ 'value' => 'UKE'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'American Express',
+ 'value' => 'AMEX'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Diners Club',
+ 'value' => 'DC'
+ );
+
+ $data['cards'][] = array(
+ 'text' => 'Japan Credit Bureau',
+ 'value' => 'JCB'
+ );
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_valid'] = array();
+
+ for ($i = $today['year'] - 10; $i < $today['year'] + 1; $i++) {
+ $data['year_valid'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ if ($this->config->get('payment_sagepay_direct_card') == '1') {
+ $data['sagepay_direct_card'] = true;
+ } else {
+ $data['sagepay_direct_card'] = false;
+ }
+
+ $data['existing_cards'] = array();
+ if ($this->customer->isLogged() && $data['sagepay_direct_card']) {
+ $this->load->model('extension/payment/sagepay_direct');
+ $data['existing_cards'] = $this->model_extension_payment_sagepay_direct->getCards($this->customer->getId());
+ }
+
+ return $this->load->view('extension/payment/sagepay_direct', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/sagepay_direct');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_direct');
+ $this->load->model('account/order');
+
+ $payment_data = array();
+
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/vspdirect-register.vsp';
+ $payment_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/vspdirect-register.vsp';
+ $payment_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPDirectGateway.asp';
+ $payment_data['VPSProtocol'] = '2.23';
+ }
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $payment_data['ReferrerID'] = 'E511AF91-E4A0-42DE-80B0-09C981A3FB61';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $payment_data['VendorTxCode'] = $this->session->data['order_id'] . 'SD' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
+ $payment_data['Amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $payment_data['Currency'] = $this->session->data['currency'];
+ $payment_data['Description'] = substr($this->config->get('config_name'), 0, 100);
+ $payment_data['TxType'] = $this->config->get('payment_sagepay_direct_transaction');
+
+ $payment_data['CV2'] = $this->request->post['cc_cvv2'];
+
+ if (isset($this->request->post['Token'])) {
+ $payment_data['Token'] = $this->request->post['Token'];
+ $payment_data['StoreToken'] = 1;
+ } else {
+ $payment_data['CardHolder'] = $this->request->post['cc_owner'];
+ $payment_data['CardNumber'] = $this->request->post['cc_number'];
+ $payment_data['ExpiryDate'] = $this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], 2);
+ $payment_data['CardType'] = $this->request->post['cc_type'];
+ }
+
+ if (isset($this->request->post['CreateToken'])) {
+ $payment_data['CreateToken'] = $this->request->post['CreateToken'];
+ $payment_data['StoreToken'] = 1;
+ }
+
+ $payment_data['BillingSurname'] = substr($order_info['payment_lastname'], 0, 20);
+ $payment_data['BillingFirstnames'] = substr($order_info['payment_firstname'], 0, 20);
+ $payment_data['BillingAddress1'] = substr($order_info['payment_address_1'], 0, 100);
+
+ if ($order_info['payment_address_2']) {
+ $payment_data['BillingAddress2'] = $order_info['payment_address_2'];
+ }
+
+ $payment_data['BillingCity'] = substr($order_info['payment_city'], 0, 40);
+ $payment_data['BillingPostCode'] = substr($order_info['payment_postcode'], 0, 10);
+ $payment_data['BillingCountry'] = $order_info['payment_iso_code_2'];
+
+ if ($order_info['payment_iso_code_2'] == 'US') {
+ $payment_data['BillingState'] = $order_info['payment_zone_code'];
+ }
+
+ $payment_data['BillingPhone'] = substr($order_info['telephone'], 0, 20);
+
+ if ($this->cart->hasShipping()) {
+ $payment_data['DeliverySurname'] = substr($order_info['shipping_lastname'], 0, 20);
+ $payment_data['DeliveryFirstnames'] = substr($order_info['shipping_firstname'], 0, 20);
+ $payment_data['DeliveryAddress1'] = substr($order_info['shipping_address_1'], 0, 100);
+
+ if ($order_info['shipping_address_2']) {
+ $payment_data['DeliveryAddress2'] = $order_info['shipping_address_2'];
+ }
+
+ $payment_data['DeliveryCity'] = substr($order_info['shipping_city'], 0, 40);
+ $payment_data['DeliveryPostCode'] = substr($order_info['shipping_postcode'], 0, 10);
+ $payment_data['DeliveryCountry'] = $order_info['shipping_iso_code_2'];
+
+ if ($order_info['shipping_iso_code_2'] == 'US') {
+ $payment_data['DeliveryState'] = $order_info['shipping_zone_code'];
+ }
+
+ $payment_data['CustomerName'] = substr($order_info['firstname'] . ' ' . $order_info['lastname'], 0, 100);
+ $payment_data['DeliveryPhone'] = substr($order_info['telephone'], 0, 20);
+ } else {
+ $payment_data['DeliveryFirstnames'] = $order_info['payment_firstname'];
+ $payment_data['DeliverySurname'] = $order_info['payment_lastname'];
+ $payment_data['DeliveryAddress1'] = $order_info['payment_address_1'];
+
+ if ($order_info['payment_address_2']) {
+ $payment_data['DeliveryAddress2'] = $order_info['payment_address_2'];
+ }
+
+ $payment_data['DeliveryCity'] = $order_info['payment_city'];
+ $payment_data['DeliveryPostCode'] = $order_info['payment_postcode'];
+ $payment_data['DeliveryCountry'] = $order_info['payment_iso_code_2'];
+
+ if ($order_info['payment_iso_code_2'] == 'US') {
+ $payment_data['DeliveryState'] = $order_info['payment_zone_code'];
+ }
+
+ $payment_data['DeliveryPhone'] = $order_info['telephone'];
+ }
+
+ $order_products = $this->model_account_order->getOrderProducts($this->session->data['order_id']);
+ $cart_rows = 0;
+ $str_basket = "";
+ foreach ($order_products as $product) {
+ $str_basket .=
+ ":" . str_replace(":", " ", $product['name'] . " " . $product['model']) .
+ ":" . $product['quantity'] .
+ ":" . $this->currency->format($product['price'], $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format($product['tax'], $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format(($product['price'] + $product['tax']), $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format(($product['price'] + $product['tax']) * $product['quantity'], $order_info['currency_code'], false, false);
+ $cart_rows++;
+ }
+
+ $order_totals = $this->model_account_order->getOrderTotals($this->session->data['order_id']);
+ foreach ($order_totals as $total) {
+ $str_basket .= ":" . str_replace(":", " ", $total['title']) . ":::::" . $this->currency->format($total['value'], $order_info['currency_code'], false, false);
+ $cart_rows++;
+ }
+ $str_basket = $cart_rows . $str_basket;
+
+ $payment_data['Basket'] = $str_basket;
+
+ $payment_data['CustomerEMail'] = substr($order_info['email'], 0, 255);
+ $payment_data['Apply3DSecure'] = '0';
+
+ $response_data = $this->model_extension_payment_sagepay_direct->sendCurl($url, $payment_data);
+
+ $json = array();
+
+ if ($response_data['Status'] == '3DAUTH') {
+ $json['ACSURL'] = $response_data['ACSURL'];
+ $json['MD'] = $response_data['MD'];
+ $json['PaReq'] = $response_data['PAReq'];
+
+ $response_data['VPSTxId'] = '';
+ $response_data['SecurityKey'] = '';
+ $response_data['TxAuthNo'] = '';
+
+ $card_id = '';
+ if (!empty($payment_data['CreateToken']) && $this->customer->isLogged()) {
+ $card_data = array();
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Token'] = '';
+ $card_data['Last4Digits'] = substr(str_replace(' ', '', $payment_data['CardNumber']), -4, 4);
+ $card_data['ExpiryDate'] = $this->request->post['cc_expire_date_month'] . '/' . substr($this->request->post['cc_expire_date_year'], 2);
+ $card_data['CardType'] = $payment_data['CardType'];
+ $card_id = $this->model_extension_payment_sagepay_direct->addCard($card_data);
+ } elseif (isset($payment_data['Token'])) {
+ $card = $this->model_extension_payment_sagepay_direct->getCard(false, $payment_data['Token']);
+ $card_id = $card['card_id'];
+ }
+
+ $this->model_extension_payment_sagepay_direct->addOrder($this->session->data['order_id'], $response_data, $payment_data, $card_id);
+ $this->model_extension_payment_sagepay_direct->logger('Response data', $response_data);
+ $this->model_extension_payment_sagepay_direct->logger('$payment_data', $payment_data);
+ $this->model_extension_payment_sagepay_direct->logger('order_id', $this->session->data['order_id']);
+
+ $json['TermUrl'] = $this->url->link('extension/payment/sagepay_direct/callback', '', true);
+ } elseif ($response_data['Status'] == 'OK' || $response_data['Status'] == 'AUTHENTICATED' || $response_data['Status'] == 'REGISTERED') {
+ $message = '';
+
+ if (isset($response_data['TxAuthNo'])) {
+ $message .= 'TxAuthNo: ' . $response_data['TxAuthNo'] . "\n";
+ } else {
+ $response_data['TxAuthNo'] = '';
+ }
+
+ if (isset($response_data['AVSCV2'])) {
+ $message .= 'AVSCV2: ' . $response_data['AVSCV2'] . "\n";
+ }
+
+ if (isset($response_data['AddressResult'])) {
+ $message .= 'AddressResult: ' . $response_data['AddressResult'] . "\n";
+ }
+
+ if (isset($response_data['PostCodeResult'])) {
+ $message .= 'PostCodeResult: ' . $response_data['PostCodeResult'] . "\n";
+ }
+
+ if (isset($response_data['CV2Result'])) {
+ $message .= 'CV2Result: ' . $response_data['CV2Result'] . "\n";
+ }
+
+ if (isset($response_data['3DSecureStatus'])) {
+ $message .= '3DSecureStatus: ' . $response_data['3DSecureStatus'] . "\n";
+ }
+
+ if (isset($response_data['CAVV'])) {
+ $message .= 'CAVV: ' . $response_data['CAVV'] . "\n";
+ }
+
+ $card_id = '';
+ if (!empty($payment_data['CreateToken']) && !empty($response_data['Token']) && $this->customer->isLogged()) {
+ $card_data = array();
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Token'] = $response_data['Token'];
+ $card_data['Last4Digits'] = substr(str_replace(' ', '', $payment_data['CardNumber']), -4, 4);
+ $card_data['ExpiryDate'] = $this->request->post['cc_expire_date_month'] . '/' . substr($this->request->post['cc_expire_date_year'], 2);
+ $card_data['CardType'] = $payment_data['CardType'];
+ $card_id = $this->model_extension_payment_sagepay_direct->addCard($card_data);
+ } elseif (isset($payment_data['Token'])) {
+ $card = $this->model_extension_payment_sagepay_direct->getCard(false, $payment_data['Token']);
+ $card_id = $card['card_id'];
+ }
+
+ $sagepay_direct_order_id = $this->model_extension_payment_sagepay_direct->addOrder($order_info['order_id'], $response_data, $payment_data, $card_id);
+ $this->model_extension_payment_sagepay_direct->logger('Response data', $response_data);
+ $this->model_extension_payment_sagepay_direct->logger('$payment_data', $payment_data);
+ $this->model_extension_payment_sagepay_direct->logger('order_id', $this->session->data['order_id']);
+
+ $this->model_extension_payment_sagepay_direct->addTransaction($sagepay_direct_order_id, $this->config->get('payment_sagepay_direct_transaction'), $order_info);
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_sagepay_direct_order_status_id'), $message, false);
+
+ if ($this->config->get('payment_sagepay_direct_transaction') == 'PAYMENT') {
+ $recurring_products = $this->cart->getRecurringProducts();
+ //loop through any products that are recurring items
+ foreach ($recurring_products as $item) {
+ $this->model_extension_payment_sagepay_direct->recurringPayment($item, $payment_data['VendorTxCode']);
+ }
+ }
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ } else {
+ $json['error'] = $response_data['Status'] . ': ' . $response_data['StatusDetail'];
+ $this->model_extension_payment_sagepay_direct->logger('Response data', $json['error']);
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function callback() {
+ $this->load->model('extension/payment/sagepay_direct');
+ $this->load->language('extension/payment/sagepay_direct');
+ $this->load->model('checkout/order');
+
+ if (isset($this->session->data['order_id'])) {
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/direct3dcallback.vsp';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/direct3dcallback.vsp';
+ } elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPDirectCallback.asp';
+ }
+
+ $response_data = $this->model_extension_payment_sagepay_direct->sendCurl($url, $this->request->post);
+ $this->model_extension_payment_sagepay_direct->logger('$response_data', $response_data);
+
+ if ($response_data['Status'] == 'OK' || $response_data['Status'] == 'AUTHENTICATED' || $response_data['Status'] == 'REGISTERED') {
+ $message = '';
+
+ if (isset($response_data['TxAuthNo'])) {
+ $message .= 'TxAuthNo: ' . $response_data['TxAuthNo'] . "\n";
+ } else {
+ $response_data['TxAuthNo'] = '';
+ }
+
+ if (isset($response_data['AVSCV2'])) {
+ $message .= 'AVSCV2: ' . $response_data['AVSCV2'] . "\n";
+ }
+
+ if (isset($response_data['AddressResult'])) {
+ $message .= 'AddressResult: ' . $response_data['AddressResult'] . "\n";
+ }
+
+ if (isset($response_data['PostCodeResult'])) {
+ $message .= 'PostCodeResult: ' . $response_data['PostCodeResult'] . "\n";
+ }
+
+ if (isset($response_data['CV2Result'])) {
+ $message .= 'CV2Result: ' . $response_data['CV2Result'] . "\n";
+ }
+
+ if (isset($response_data['3DSecureStatus'])) {
+ $message .= '3DSecureStatus: ' . $response_data['3DSecureStatus'] . "\n";
+ }
+
+ if (isset($response_data['CAVV'])) {
+ $message .= 'CAVV: ' . $response_data['CAVV'] . "\n";
+ }
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+ $sagepay_order_info = $this->model_extension_payment_sagepay_direct->getOrder($this->session->data['order_id']);
+
+ $this->model_extension_payment_sagepay_direct->logger('$order_info', $order_info);
+ $this->model_extension_payment_sagepay_direct->logger('$sagepay_order_info', $sagepay_order_info);
+
+ $this->model_extension_payment_sagepay_direct->updateOrder($order_info, $response_data);
+ $this->model_extension_payment_sagepay_direct->addTransaction($sagepay_order_info['sagepay_direct_order_id'], $this->config->get('payment_sagepay_direct_transaction'), $order_info);
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_sagepay_direct_order_status_id'), $message, false);
+
+ if (!empty($response_data['Token']) && $this->customer->isLogged()) {
+ $this->model_extension_payment_sagepay_direct->updateCard($sagepay_order_info['card_id'], $response_data['Token']);
+ } else {
+ $this->model_extension_payment_sagepay_direct->deleteCard($sagepay_order_info['card_id']);
+ }
+
+ if ($this->config->get('payment_sagepay_direct_transaction') == 'PAYMENT') {
+ $recurring_products = $this->cart->getRecurringProducts();
+ //loop through any products that are recurring items
+ foreach ($recurring_products as $item) {
+ $this->model_extension_payment_sagepay_direct->recurringPayment($item, $sagepay_order_info['VendorTxCode']);
+ }
+ }
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->session->data['error'] = $response_data['StatusDetail'];
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+ }
+
+ public function delete() {
+
+ $this->load->language('account/sagepay_direct_cards');
+
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $card = $this->model_extension_payment_sagepay_direct->getCard(false, $this->request->post['Token']);
+
+ if (!empty($card['token'])) {
+ if ($this->config->get('payment_sagepay_direct_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/removetoken.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/removetoken.vsp';
+ }
+ $payment_data['VPSProtocol'] = '3.00';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
+ $payment_data['TxType'] = 'REMOVETOKEN';
+ $payment_data['Token'] = $card['token'];
+
+ $response_data = $this->model_extension_payment_sagepay_direct->sendCurl($url, $payment_data);
+ if ($response_data['Status'] == 'OK') {
+ $this->model_extension_payment_sagepay_direct->deleteCard($card['card_id']);
+ $this->session->data['success'] = $this->language->get('text_success_card');
+ $json['success'] = true;
+ } else {
+ $json['error'] = $this->language->get('text_fail_card');
+ }
+ } else {
+ $json['error'] = $this->language->get('text_fail_card');
+ }
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function cron() {
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_sagepay_direct_cron_job_token'), $this->request->get['token'])) {
+ $this->load->model('extension/payment/sagepay_direct');
+
+ $orders = $this->model_extension_payment_sagepay_direct->cronPayment();
+
+ $this->model_extension_payment_sagepay_direct->updateCronJobRunTime();
+
+ $this->model_extension_payment_sagepay_direct->logger('Repeat Orders', $orders);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/sagepay_server.php b/public/catalog/controller/extension/payment/sagepay_server.php
new file mode 100644
index 0000000..9f886a2
--- /dev/null
+++ b/public/catalog/controller/extension/payment/sagepay_server.php
@@ -0,0 +1,503 @@
+<?php
+class ControllerExtensionPaymentSagepayServer extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/sagepay_server');
+ $data['text_credit_card'] = $this->language->get('text_credit_card');
+ $data['text_card_name'] = $this->language->get('text_card_name');
+ $data['text_card_type'] = $this->language->get('text_card_type');
+ $data['text_card_digits'] = $this->language->get('text_card_digits');
+ $data['text_card_expiry'] = $this->language->get('text_card_expiry');
+ $data['text_loading'] = $this->language->get('text_loading');
+ $data['text_confirm_delete'] = $this->language->get('text_confirm_delete');
+
+ $data['entry_card'] = $this->language->get('entry_card');
+ $data['entry_card_existing'] = $this->language->get('entry_card_existing');
+ $data['entry_card_new'] = $this->language->get('entry_card_new');
+ $data['entry_card_save'] = $this->language->get('entry_card_save');
+ $data['entry_cc_choice'] = $this->language->get('entry_cc_choice');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+ $data['button_delete_card'] = $this->language->get('button_delete_card');
+
+ $data['action'] = $this->url->link('extension/payment/sagepay_server/send', '', true);
+
+ if ($this->config->get('payment_sagepay_server_card') == '1') {
+ $data['sagepay_server_card'] = true;
+ } else {
+ $data['sagepay_server_card'] = false;
+ }
+
+ $data['cards'] = array();
+
+ if ($this->customer->isLogged() && $data['sagepay_server_card']) {
+ $this->load->model('extension/payment/sagepay_server');
+
+ $data['cards'] = $this->model_extension_payment_sagepay_server->getCards($this->customer->getId());
+ }
+
+ return $this->load->view('extension/payment/sagepay_server', $data);
+ }
+
+ public function send() {
+
+ $payment_data = array();
+
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/vspserver-register.vsp';
+
+ $payment_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'test') {
+ $url = 'https://test.sagepay.com/gateway/service/vspserver-register.vsp';
+
+ $payment_data['VPSProtocol'] = '3.00';
+ } elseif ($this->config->get('payment_sagepay_server_test') == 'sim') {
+ $url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRegisterTx';
+
+ $payment_data['VPSProtocol'] = '2.23';
+ }
+
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_server');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $payment_data['ReferrerID'] = 'E511AF91-E4A0-42DE-80B0-09C981A3FB61';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $payment_data['VendorTxCode'] = $this->session->data['order_id'] . 'T' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
+ $payment_data['Amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
+ $payment_data['Currency'] = $this->session->data['currency'];
+ $payment_data['Description'] = substr($this->config->get('config_name'), 0, 100);
+ $payment_data['NotificationURL'] = $this->url->link('extension/payment/sagepay_server/callback', '', true);
+ $payment_data['TxType'] = $this->config->get('payment_sagepay_server_transaction');
+
+ $payment_data['BillingSurname'] = substr($order_info['payment_lastname'], 0, 20);
+ $payment_data['BillingFirstnames'] = substr($order_info['payment_firstname'], 0, 20);
+ $payment_data['BillingAddress1'] = substr($order_info['payment_address_1'], 0, 100);
+
+ if ($order_info['payment_address_2']) {
+ $payment_data['BillingAddress2'] = $order_info['payment_address_2'];
+ }
+
+ $payment_data['BillingCity'] = substr($order_info['payment_city'], 0, 40);
+ $payment_data['BillingPostCode'] = substr($order_info['payment_postcode'], 0, 10);
+ $payment_data['BillingCountry'] = $order_info['payment_iso_code_2'];
+
+ if ($order_info['payment_iso_code_2'] == 'US') {
+ $payment_data['BillingState'] = $order_info['payment_zone_code'];
+ }
+
+ $payment_data['BillingPhone'] = substr($order_info['telephone'], 0, 20);
+
+ if ($this->cart->hasShipping()) {
+ $payment_data['DeliverySurname'] = substr($order_info['shipping_lastname'], 0, 20);
+ $payment_data['DeliveryFirstnames'] = substr($order_info['shipping_firstname'], 0, 20);
+ $payment_data['DeliveryAddress1'] = substr($order_info['shipping_address_1'], 0, 100);
+
+ if ($order_info['shipping_address_2']) {
+ $payment_data['DeliveryAddress2'] = $order_info['shipping_address_2'];
+ }
+
+ $payment_data['DeliveryCity'] = substr($order_info['shipping_city'], 0, 40);
+ $payment_data['DeliveryPostCode'] = substr($order_info['shipping_postcode'], 0, 10);
+ $payment_data['DeliveryCountry'] = $order_info['shipping_iso_code_2'];
+
+ if ($order_info['shipping_iso_code_2'] == 'US') {
+ $payment_data['DeliveryState'] = $order_info['shipping_zone_code'];
+ }
+
+ $payment_data['CustomerName'] = substr($order_info['firstname'] . ' ' . $order_info['lastname'], 0, 100);
+ $payment_data['DeliveryPhone'] = substr($order_info['telephone'], 0, 20);
+ } else {
+ $payment_data['DeliveryFirstnames'] = $order_info['payment_firstname'];
+ $payment_data['DeliverySurname'] = $order_info['payment_lastname'];
+ $payment_data['DeliveryAddress1'] = $order_info['payment_address_1'];
+
+ if ($order_info['payment_address_2']) {
+ $payment_data['DeliveryAddress2'] = $order_info['payment_address_2'];
+ }
+
+ $payment_data['DeliveryCity'] = $order_info['payment_city'];
+ $payment_data['DeliveryPostCode'] = $order_info['payment_postcode'];
+ $payment_data['DeliveryCountry'] = $order_info['payment_iso_code_2'];
+
+ if ($order_info['payment_iso_code_2'] == 'US') {
+ $payment_data['DeliveryState'] = $order_info['payment_zone_code'];
+ }
+
+ $payment_data['DeliveryPhone'] = $order_info['telephone'];
+ }
+
+ $order_products = $this->model_checkout_order->getOrderProducts($this->session->data['order_id']);
+ $cart_rows = 0;
+ $str_basket = "";
+ foreach ($order_products as $product) {
+ $str_basket .=
+ ":" . str_replace(":", " ", $product['name'] . " " . $product['model']) .
+ ":" . $product['quantity'] .
+ ":" . $this->currency->format($product['price'], $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format($product['tax'], $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format(($product['price'] + $product['tax']), $order_info['currency_code'], false, false) .
+ ":" . $this->currency->format(($product['price'] + $product['tax']) * $product['quantity'], $order_info['currency_code'], false, false);
+ $cart_rows++;
+ }
+
+ $order_totals = $this->model_checkout_order->getOrderTotals($this->session->data['order_id']);
+
+ foreach ($order_totals as $total) {
+ $str_basket .= ":" . str_replace(":", " ", $total['title']) . ":::::" . $this->currency->format($total['value'], $order_info['currency_code'], false, false);
+ $cart_rows++;
+ }
+
+ $str_basket = $cart_rows . $str_basket;
+
+ $payment_data['Basket'] = $str_basket;
+
+ $payment_data['CustomerEMail'] = substr($order_info['email'], 0, 255);
+ $payment_data['Apply3DSecure'] = '0';
+
+ if (isset($this->request->post['CreateToken'])) {
+ $payment_data['CreateToken'] = $this->request->post['CreateToken'];
+ $payment_data['StoreToken'] = 1;
+ }
+
+ if (isset($this->request->post['Token'])) {
+ $payment_data['Token'] = $this->request->post['Token'];
+ $payment_data['StoreToken'] = 1;
+ }
+
+ $response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
+
+ $json = array();
+
+ if ((substr($response_data['Status'], 0, 2) == "OK") || $response_data['Status'] == 'AUTHENTICATED' || $response_data['Status'] == 'REGISTERED') {
+ $json['redirect'] = $response_data['NextURL'];
+ $json['Status'] = $response_data['Status'];
+ $json['StatusDetail'] = $response_data['StatusDetail'];
+
+ $response_data['order_id'] = $this->session->data['order_id'];
+ $response_data['VendorTxCode'] = $payment_data['VendorTxCode'];
+
+ $order_info = array_merge($order_info, $response_data);
+
+ $this->model_extension_payment_sagepay_server->addOrder($order_info);
+
+ if ($this->config->get('payment_sagepay_server_transaction') == 'PAYMENT') {
+ $recurring_products = $this->cart->getRecurringProducts();
+
+ //loop through any products that are recurring items
+ foreach ($recurring_products as $item) {
+ $this->model_extension_payment_sagepay_server->addRecurringPayment($item, $payment_data['VendorTxCode']);
+ }
+ }
+ } else {
+ $json['error'] = $response_data['StatusDetail'];
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function callback() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_server');
+
+ $success_page = $this->url->link('extension/payment/sagepay_server/success', '', true);
+ $error_page = $this->url->link('extension/payment/sagepay_server/failure', '', true);
+ $end_ln = chr(13) . chr(10);
+
+ if (isset($this->request->post['VendorTxCode'])) {
+ $vendor_tx_code = $this->request->post['VendorTxCode'];
+ $order_id_parts = explode('T', $this->request->post['VendorTxCode']);
+ $order_id = (int)$order_id_parts[0];
+ } else {
+ $vendor_tx_code = '';
+ $order_id = '';
+ }
+
+ if (isset($this->request->post['Status'])) {
+ $str_status = $this->request->post['Status'];
+ } else {
+ $str_status = '';
+ }
+
+ if (isset($this->request->post['VPSSignature'])) {
+ $str_vps_signature = $this->request->post['VPSSignature'];
+ } else {
+ $str_vps_signature = '';
+ }
+ if (isset($this->request->post['StatusDetail'])) {
+ $str_status_detail = $this->request->post['StatusDetail'];
+ } else {
+ $str_status_detail = '';
+ }
+
+ if (isset($this->request->post['VPSTxId'])) {
+ $str_vps_tx_id = $this->request->post['VPSTxId'];
+ } else {
+ $str_vps_tx_id = '';
+ }
+
+ if (isset($this->request->post['TxAuthNo'])) {
+ $str_tx_auth_no = $this->request->post['TxAuthNo'];
+ } else {
+ $str_tx_auth_no = '';
+ }
+
+ if (isset($this->request->post['AVSCV2'])) {
+ $str_avs_cv2 = $this->request->post['AVSCV2'];
+ } else {
+ $str_avs_cv2 = '';
+ }
+
+ if (isset($this->request->post['AddressResult'])) {
+ $str_address_result = $this->request->post['AddressResult'];
+ } else {
+ $str_address_result = '';
+ }
+
+ if (isset($this->request->post['PostCodeResult'])) {
+ $str_postcode_result = $this->request->post['PostCodeResult'];
+ } else {
+ $str_postcode_result = '';
+ }
+
+ if (isset($this->request->post['CV2Result'])) {
+ $str_cv2_result = $this->request->post['CV2Result'];
+ } else {
+ $str_cv2_result = '';
+ }
+
+ if (isset($this->request->post['GiftAid'])) {
+ $str_gift_aid = $this->request->post['GiftAid'];
+ } else {
+ $str_gift_aid = '';
+ }
+
+ if (isset($this->request->post['3DSecureStatus'])) {
+ $str_3d_secure_status = $this->request->post['3DSecureStatus'];
+ } else {
+ $str_3d_secure_status = '';
+ }
+
+ if (isset($this->request->post['CAVV'])) {
+ $str_cavv = $this->request->post['CAVV'];
+ } else {
+ $str_cavv = '';
+ }
+
+ if (isset($this->request->post['AddressStatus'])) {
+ $str_address_status = $this->request->post['AddressStatus'];
+ } else {
+ $str_address_status = '';
+ }
+
+ if (isset($this->request->post['PayerStatus'])) {
+ $str_payer_status = $this->request->post['PayerStatus'];
+ } else {
+ $str_payer_status = '';
+ }
+
+ if (isset($this->request->post['CardType'])) {
+ $str_card_type = $this->request->post['CardType'];
+ } else {
+ $str_card_type = '';
+ }
+
+ if (isset($this->request->post['Last4Digits'])) {
+ $str_last_4_digits = $this->request->post['Last4Digits'];
+ } else {
+ $str_last_4_digits = '';
+ }
+
+ if (isset($this->request->post['ExpiryDate'])) {
+ $str_expiry_date = $this->request->post['ExpiryDate'];
+ } else {
+ $str_expiry_date = '';
+ }
+
+ if (isset($this->request->post['Token'])) {
+ $str_token = $this->request->post['Token'];
+ } else {
+ $str_token = '';
+ }
+
+ if (isset($this->request->post['DeclineCode'])) {
+ $str_decline_code = $this->request->post['DeclineCode'];
+ } else {
+ $str_decline_code = '';
+ }
+
+ if (isset($this->request->post['BankAuthCode'])) {
+ $str_bank_auth_code = $this->request->post['BankAuthCode'];
+ } else {
+ $str_bank_auth_code = '';
+ }
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ $transaction_info = $this->model_extension_payment_sagepay_server->getOrder($order_id);
+
+ $this->model_extension_payment_sagepay_server->logger('$order_id', $order_id);
+ $this->model_extension_payment_sagepay_server->logger('$order_info', $order_info);
+ $this->model_extension_payment_sagepay_server->logger('$transaction_info', $transaction_info);
+ $this->model_extension_payment_sagepay_server->logger('$strStatus', $str_status);
+
+ //Check if order we have saved in database maches with callback sagepay does
+ if (!isset($transaction_info['order_id']) || $transaction_info['order_id'] != $order_id) {
+ echo "Status=INVALID" . $end_ln;
+ echo "StatusDetail= Order IDs could not be matched. Order might be tampered with." . $end_ln;
+ echo "RedirectURL=" . $error_page . $end_ln;
+
+ $this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Order IDs could not be matched. Order might be tampered with');
+
+ exit;
+ }
+
+ if (isset($transaction_info['SecurityKey'])) {
+ $str_security_key = $transaction_info['SecurityKey'];
+ } else {
+ $str_security_key = '';
+ }
+
+ /** Now we rebuilt the POST message, including our security key, and use the MD5 Hash **
+ * * component that is included to create our own signature to compare with **
+ * * the contents of the VPSSignature field in the POST. Check the Sage Pay Server protocol **
+ * * if you need clarification on this process * */
+ $str_message = $str_vps_tx_id . $vendor_tx_code . $str_status . $str_tx_auth_no . $this->config->get('payment_sagepay_server_vendor') . urldecode($str_avs_cv2) . $str_security_key
+ . $str_address_result . $str_postcode_result . $str_cv2_result . $str_gift_aid . $str_3d_secure_status . $str_cavv
+ . $str_address_status . $str_payer_status . $str_card_type . $str_last_4_digits . $str_decline_code . $str_expiry_date . $str_bank_auth_code;
+
+ $str_my_signature = strtoupper(md5($str_message));
+
+ /** We can now compare our MD5 Hash signature with that from Sage Pay Server * */
+ if ($str_my_signature != $str_vps_signature) {
+ $this->model_extension_payment_sagepay_server->deleteOrder($order_id);
+
+ echo "Status=INVALID" . $end_ln;
+ echo "StatusDetail= Cannot match the MD5 Hash. Order might be tampered with." . $end_ln;
+ echo "RedirectURL=" . $error_page . $end_ln;
+
+ $this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Cannot match the MD5 Hash. Order might be tampered with');
+ exit;
+ }
+
+ if (($str_status != "OK" && $str_status != "REGISTERED" && $str_status != "AUTHENTICATED") || !$order_info) {
+ $this->model_extension_payment_sagepay_server->deleteOrder($order_id);
+
+ echo "Status=INVALID" . $end_ln;
+ echo "StatusDetail= Either status invalid or order info was not found.";
+ echo "RedirectURL=" . $error_page . $end_ln;
+
+ $this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Either status invalid or order info was not found');
+ exit;
+ }
+
+ $comment = "Paid with Sagepay Server<br><br>";
+ $comment .= "<b>Transaction details</b><br>";
+ $comment .= "Status: " . $str_status . "<br>";
+ $comment .= "AVS and CV2 checks: " . $str_avs_cv2 . "<br>";
+ $comment .= "3D Secure checks: " . $str_3d_secure_status . "<br>";
+ $comment .= "Card type: " . $str_card_type . "<br>";
+
+ if ($str_card_type == "PAYPAL") {
+ $comment .= "Paypal address status: " . $str_address_status . "<br>";
+ $comment .= "Paypal payer status: " . $str_payer_status . "<br>";
+ }
+ $comment .= "Last 4 digits: " . $str_last_4_digits . "<br>";
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_sagepay_server_order_status_id'), $comment);
+
+ $this->model_extension_payment_sagepay_server->updateOrder($order_info, $str_vps_tx_id, $str_tx_auth_no);
+
+ $this->model_extension_payment_sagepay_server->addTransaction($transaction_info['sagepay_server_order_id'], $this->config->get('payment_sagepay_server_transaction'), $order_info);
+
+ if (!empty($str_token)) {
+ $data['customer_id'] = $order_info['customer_id'];
+ $data['ExpiryDate'] = substr($str_expiry_date, -4, 2) . '/' . substr($str_expiry_date, 2);
+ $data['Token'] = $str_token;
+ $data['CardType'] = $str_card_type;
+ $data['Last4Digits'] = $str_last_4_digits;
+
+ $this->model_extension_payment_sagepay_server->addCard($data);
+ }
+
+ echo "Status=OK" . $end_ln;
+ echo "RedirectURL=" . $success_page . $end_ln;
+ }
+
+ public function success() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/sagepay_server');
+ $this->load->model('checkout/recurring');
+
+ if (isset($this->session->data['order_id'])) {
+ $order_details = $this->model_extension_payment_sagepay_server->getOrder($this->session->data['order_id']);
+
+ if ($this->config->get('payment_sagepay_server_transaction') == 'PAYMENT') {
+ $recurring_products = $this->model_extension_payment_sagepay_server->getRecurringOrders($this->session->data['order_id']);
+
+ //loop through any products that are recurring items
+ foreach ($recurring_products as $item) {
+ $this->model_extension_payment_sagepay_server->updateRecurringPayment($item, $order_details);
+ }
+ }
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->response->redirect($this->url->link('account/login', '', true));
+ }
+ }
+
+ public function failure() {
+ $this->load->language('extension/payment/sagepay_server');
+
+ $this->session->data['error'] = $this->language->get('text_generic_error');
+
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+
+ public function delete() {
+ $this->load->language('account/sagepay_server_cards');
+
+ $this->load->model('extension/payment/sagepay_server');
+
+ $card = $this->model_extension_payment_sagepay_server->getCard(false, $this->request->post['Token']);
+
+ if (!empty($card['token'])) {
+ if ($this->config->get('payment_sagepay_server_test') == 'live') {
+ $url = 'https://live.sagepay.com/gateway/service/removetoken.vsp';
+ } else {
+ $url = 'https://test.sagepay.com/gateway/service/removetoken.vsp';
+ }
+ $payment_data['VPSProtocol'] = '3.00';
+ $payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
+ $payment_data['TxType'] = 'REMOVETOKEN';
+ $payment_data['Token'] = $card['token'];
+
+ $response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
+ if ($response_data['Status'] == 'OK') {
+ $this->model_extension_payment_sagepay_server->deleteCard($card['card_id']);
+ $this->session->data['success'] = $this->language->get('text_success_card');
+ $json['success'] = true;
+ } else {
+ $json['error'] = $this->language->get('text_fail_card');
+ }
+ } else {
+ $json['error'] = $this->language->get('text_fail_card');
+ }
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function cron() {
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_sagepay_server_cron_job_token'), $this->request->get['token'])) {
+ $this->load->model('extension/payment/sagepay_server');
+
+ $orders = $this->model_extension_payment_sagepay_server->cronPayment();
+
+ $this->model_extension_payment_sagepay_server->updateCronJobRunTime();
+
+ $this->model_extension_payment_sagepay_server->logger('Repeat Orders', $orders);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/sagepay_us.php b/public/catalog/controller/extension/payment/sagepay_us.php
new file mode 100644
index 0000000..366ddf1
--- /dev/null
+++ b/public/catalog/controller/extension/payment/sagepay_us.php
@@ -0,0 +1,95 @@
+<?php
+class ControllerExtensionPaymentSagepayUS extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/sagepay_us');
+
+ $data['text_credit_card'] = $this->language->get('text_credit_card');
+ $data['text_loading'] = $this->language->get('text_loading');
+
+ $data['entry_cc_owner'] = $this->language->get('entry_cc_owner');
+ $data['entry_cc_number'] = $this->language->get('entry_cc_number');
+ $data['entry_cc_expire_date'] = $this->language->get('entry_cc_expire_date');
+ $data['entry_cc_cvv2'] = $this->language->get('entry_cc_cvv2');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/sagepay_us', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $url = 'https://www.sagepayments.net/cgi-bin/eftbankcard.dll?transaction';
+
+ $data = 'm_id=' . $this->config->get('payment_sagepay_us_merchant_id');
+ $data .= '&m_key=' . $this->config->get('payment_sagepay_us_merchant_key');
+ $data .= '&T_amt=' . urlencode($this->currency->format($order_info['total'], $order_info['currency_code'], 1.00000, false));
+ $data .= '&T_ordernum=' . $this->session->data['order_id'];
+ $data .= '&C_name=' . urlencode($this->request->post['cc_owner']);
+ $data .= '&C_address=' . urlencode($order_info['payment_address_1']);
+ $data .= '&C_state=' . urlencode($order_info['payment_zone']);
+ $data .= '&C_city=' . urlencode($order_info['payment_city']);
+ $data .= '&C_cardnumber=' . urlencode($this->request->post['cc_number']);
+ $data .= '&C_exp=' . urlencode($this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], '2'));
+ $data .= '&C_cvv=' . urlencode($this->request->post['cc_cvv2']);
+ $data .= '&C_zip=' . urlencode($order_info['payment_postcode']);
+ $data .= '&C_email=' . urlencode($order_info['email']);
+ $data .= '&T_code=02';
+
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ $response = curl_exec($ch);
+
+ curl_close($ch);
+
+ $json = array();
+
+ if ($response[1] == 'A') {
+ $message = 'Approval Indicator: ' . $response[1] . "\n";
+ $message .= 'Approval/Error Code: ' . substr($response, 2, 6) . "\n";
+ $message .= 'Approval/Error Message: ' . substr($response, 8, 32) . "\n";
+ $message .= 'Front-End Indicator: ' . substr($response, 40, 2) . "\n";
+ $message .= 'CVV Indicator: ' . $response[42] . "\n";
+ $message .= 'AVS Indicator: ' . $response[43] . "\n";
+ $message .= 'Risk Indicator: ' . substr($response, 44, 2) . "\n";
+ $message .= 'Reference: ' . substr($response, 46, 10) . "\n";
+ $message .= 'Order Number: ' . substr($response, strpos($response, chr(28)) + 1, strrpos($response, chr(28) - 1)) . "\n";
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_sagepay_us_order_status_id'), $message, false);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ } else {
+ $json['error'] = substr($response, 8, 32);
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/securetrading_pp.php b/public/catalog/controller/extension/payment/securetrading_pp.php
new file mode 100644
index 0000000..823a161
--- /dev/null
+++ b/public/catalog/controller/extension/payment/securetrading_pp.php
@@ -0,0 +1,170 @@
+<?php
+class ControllerExtensionPaymentSecureTradingPp extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+ $this->load->language('extension/payment/securetrading_pp');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $data['order_info'] = $order_info;
+ $data['site_reference'] = $this->config->get('payment_securetrading_pp_site_reference');
+ $data['parent_css'] = $this->config->get('payment_securetrading_pp_parent_css');
+ $data['child_css'] = $this->config->get('payment_securetrading_pp_child_css');
+ $data['currency'] = $order_info['currency_code'];
+ $data['total'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['settle_due_date'] = date('Y-m-d', strtotime(date('Y-m-d') . ' +' . $this->config->get('payment_securetrading_pp_settle_due_date') . ' days'));
+ $data['settle_status'] = $this->config->get('payment_securetrading_pp_settle_status');
+
+ $payment_country = $this->model_localisation_country->getCountry($order_info['payment_country_id']);
+ $payment_zone = $this->model_localisation_zone->getZone($order_info['payment_zone_id']);
+
+ $shipping_country = $this->model_localisation_country->getCountry($order_info['shipping_country_id']);
+ $shipping_zone = $this->model_localisation_zone->getZone($order_info['shipping_zone_id']);
+
+ if ($payment_country['iso_code_3'] == 'USA') {
+ $data['billing_county'] = $payment_zone['code'];
+ } else {
+ $data['billing_county'] = $order_info['payment_zone'];
+ }
+
+ if (isset($shipping_country['iso_code_3']) && $shipping_country['iso_code_3'] == 'USA') {
+ $data['shipping_county'] = $shipping_zone['code'];
+ } else {
+ $data['shipping_county'] = $order_info['shipping_zone'];
+ }
+
+ if (!isset($shipping_country['iso_code_2'])) {
+ $shipping_country['iso_code_2'] = $payment_country['iso_code_2'];
+ }
+
+ $data['payment_country'] = $payment_country;
+ $data['shipping_country'] = $shipping_country;
+
+ if ($this->config->get('payment_securetrading_pp_site_security_status')) {
+ $data['site_security'] = hash('sha256', $order_info['currency_code'] . $data['total'] . $data['site_reference'] . $data['settle_status'] . $data['settle_due_date'] . $order_info['order_id'] . $this->config->get('payment_securetrading_pp_site_security_password'));
+ } else {
+ $data['site_security'] = false;
+ }
+
+ $cards = array(
+ 'AMEX' => 'American Express',
+ 'VISA' => 'Visa',
+ 'DELTA' => 'Visa Debit',
+ 'ELECTRON' => 'Visa Electron',
+ 'PURCHASING' => 'Visa Purchasing',
+ 'VPAY' => 'V Pay',
+ 'MASTERCARD' => 'MasterCard',
+ 'MASTERCARDDEBIT' => 'MasterCard Debit',
+ 'MAESTRO' => 'Maestro',
+ 'PAYPAL' => 'PayPal',
+ );
+
+ $data['cards'] = array();
+
+ foreach ($cards as $key => $value) {
+ if (in_array($key, $this->config->get('payment_securetrading_pp_cards_accepted'))) {
+ $data['cards'][$key] = $value;
+ }
+ }
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+ $data['text_payment_details'] = $this->language->get('text_payment_details');
+ $data['entry_card_type'] = $this->language->get('entry_card_type');
+
+ return $this->load->view('extension/payment/securetrading_pp', $data);
+ }
+ }
+
+ public function ipn() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/securetrading_pp');
+ $this->load->language('extension/payment/securetrading_pp');
+
+ $keys = array_keys($this->request->post);
+ sort($keys);
+
+ $keys_ignore = array('notificationreference', 'responsesitesecurity');
+
+ $string_to_hash = '';
+
+ foreach ($keys as $key) {
+ if (!in_array($key, $keys_ignore)) {
+ $string_to_hash .= $this->request->post[$key];
+ }
+ }
+
+ $string_to_hash .= $this->config->get('payment_securetrading_pp_notification_password');
+
+ if (hash_equals(hash('sha256', $string_to_hash), $this->request->post['responsesitesecurity']) && $this->request->post['sitereference'] == $this->config->get('payment_securetrading_pp_site_reference')) {
+ $order_info = $this->model_checkout_order->getOrder($this->request->post['orderreference']);
+
+ if ($order_info) {
+ $order_total = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+
+ if ($order_total == $this->request->post['mainamount'] && $order_info['currency_code'] == $this->request->post['currencyiso3a'] && $order_info['payment_code'] == 'securetrading_pp') {
+ $status_code_mapping = array(
+ 0 => $this->language->get('text_not_given'),
+ 1 => $this->language->get('text_not_checked'),
+ 2 => $this->language->get('text_match'),
+ 4 => $this->language->get('text_not_match'),
+ );
+ $shipping_country = $this->model_extension_payment_securetrading_pp->getCountry($this->request->post['customercountryiso2a']);
+ $payment_country = $this->model_extension_payment_securetrading_pp->getCountry($this->request->post['billingcountryiso2a']);
+
+ $order_info['payment_firstname'] = $this->request->post['billingfirstname'];
+ $order_info['payment_lastname'] = $this->request->post['billinglastname'];
+ $order_info['payment_address_1'] = $this->request->post['billingpremise'];
+ $order_info['payment_address_2'] = $this->request->post['billingstreet'];
+ $order_info['payment_city'] = $this->request->post['billingtown'];
+ $order_info['payment_zone'] = $this->request->post['billingcounty'];
+ $order_info['payment_zone_id'] = 0;
+ $order_info['payment_country'] = $payment_country['name'];
+ $order_info['payment_country_id'] = $payment_country['country_id'];
+ $order_info['payment_postcode'] = $this->request->post['billingpostcode'];
+
+ $order_info['shipping_firstname'] = $this->request->post['customerfirstname'];
+ $order_info['shipping_lastname'] = $this->request->post['customerlastname'];
+ $order_info['shipping_address_1'] = $this->request->post['customerpremise'];
+ $order_info['shipping_address_2'] = $this->request->post['customerstreet'];
+ $order_info['shipping_city'] = $this->request->post['customertown'];
+ $order_info['shipping_zone'] = $this->request->post['customercounty'];
+ $order_info['shipping_zone_id'] = 0;
+ $order_info['shipping_country'] = $shipping_country['name'];
+ $order_info['shipping_country_id'] = $shipping_country['country_id'];
+ $order_info['shipping_postcode'] = $this->request->post['customerpostcode'];
+
+ $this->model_extension_payment_securetrading_pp->editOrder($order_info['order_id'], $order_info);
+
+ $postcode_status = $this->request->post['securityresponsepostcode'];
+ $security_code_status = $this->request->post['securityresponsesecuritycode'];
+ $address_status = $this->request->post['securityresponseaddress'];
+
+ $message = sprintf($this->language->get('text_postcode_check'), $status_code_mapping[$postcode_status]) . "\n";
+ $message .= sprintf($this->language->get('text_security_code_check'), $status_code_mapping[$security_code_status]) . "\n";
+ $message .= sprintf($this->language->get('text_address_check'), $status_code_mapping[$address_status]) . "\n";
+
+ if (isset($this->request->post['transactionreference'])) {
+ $transactionreference = $this->request->post['transactionreference'];
+ } else {
+ $transactionreference = '';
+ }
+ $this->model_extension_payment_securetrading_pp->addReference($order_info['order_id'], $transactionreference);
+
+ if ($this->request->post['errorcode'] == '0') {
+ $order_status_id = $this->config->get('payment_securetrading_pp_order_status_id');
+
+ $this->model_extension_payment_securetrading_pp->confirmOrder($order_info['order_id'], $order_status_id);
+ $this->model_extension_payment_securetrading_pp->updateOrder($order_info['order_id'], $order_status_id, $message);
+ } elseif ($this->request->post['errorcode'] == '70000') {
+ $order_status_id = $this->config->get('payment_securetrading_pp_declined_order_status_id');
+
+ $this->model_extension_payment_securetrading_pp->updateOrder($order_info['order_id'], $order_status_id, $message);
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/securetrading_ws.php b/public/catalog/controller/extension/payment/securetrading_ws.php
new file mode 100644
index 0000000..82d8bbc
--- /dev/null
+++ b/public/catalog/controller/extension/payment/securetrading_ws.php
@@ -0,0 +1,359 @@
+<?php
+class ControllerExtensionPaymentSecureTradingWs extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+ $this->load->language('extension/payment/securetrading_ws');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ $data['entry_type'] = $this->language->get('entry_type');
+ $data['entry_number'] = $this->language->get('entry_number');
+ $data['entry_expire_date'] = $this->language->get('entry_expire_date');
+ $data['entry_cvv2'] = $this->language->get('entry_cvv2');
+
+ $data['text_card_details'] = $this->language->get('text_card_details');
+ $data['text_wait'] = $this->language->get('text_wait');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $cards = array(
+ 'AMEX' => 'American Express',
+ 'VISA' => 'Visa',
+ 'DELTA' => 'Visa Debit',
+ 'ELECTRON' => 'Visa Electron',
+ 'PURCHASING' => 'Visa Purchasing',
+ 'VPAY' => 'V Pay',
+ 'MASTERCARD' => 'MasterCard',
+ 'MASTERCARDDEBIT' => 'MasterCard Debit',
+ 'MAESTRO' => 'Maestro',
+ 'PAYPAL' => 'PayPal',
+ );
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ $data['cards'] = array();
+
+ foreach ($this->config->get('payment_securetrading_ws_cards_accepted') as $card_type) {
+ $data['cards'][$card_type] = $cards[$card_type];
+ }
+
+ return $this->load->view('extension/payment/securetrading_ws', $data);
+ }
+ }
+
+ public function process() {
+ $this->load->model('checkout/order');
+ $this->load->model('localisation/country');
+ $this->load->model('extension/payment/securetrading_ws');
+ $this->load->language('extension/payment/securetrading_ws');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ if ($order_info) {
+ if ($this->config->get('payment_securetrading_ws_3d_secure')) {
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'THREEDQUERY');
+
+ $merchant_node = $request_node->addChild('merchant');
+ $merchant_node->addChild('orderreference', $order_info['order_id']);
+ $merchant_node->addChild('termurl', $this->url->link('extension/payment/securetrading_ws/threedreturn', '', true));
+
+ $settlement_node = $request_node->addChild('settlement');
+ $settlement_date = date('Y-m-d', strtotime(date('Y-m-d') . ' +' . $this->config->get('payment_securetrading_ws_settle_due_date') . ' days'));
+ $settlement_node->addChild('settleduedate', $settlement_date);
+ $settlement_node->addChild('settlestatus', $this->config->get('payment_securetrading_ws_settle_status'));
+
+ $customer_node = $request_node->addChild('customer');
+ $customer_node->addChild('useragent', $order_info['user_agent']);
+ $customer_node->addChild('accept', $this->request->server['HTTP_ACCEPT']);
+
+ $billing_node = $request_node->addChild('billing');
+ $amount_node = $billing_node->addChild('amount', str_replace('.', '', $this->model_extension_payment_securetrading_ws->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'])));
+ $amount_node->addAttribute('currencycode', $order_info['currency_code']);
+
+ $billing_node->addChild('premise', $order_info['payment_address_1']);
+ $billing_node->addChild('postcode', $order_info['payment_postcode']);
+
+ $name_node = $billing_node->addChild('name');
+ $name_node->addChild('first', $order_info['payment_firstname']);
+ $name_node->addChild('last', $order_info['payment_lastname']);
+
+ $payment_node = $billing_node->addChild('payment');
+ $payment_node->addAttribute('type', $this->request->post['type']);
+ $payment_node->addChild('pan', $this->request->post['number']);
+ $payment_node->addChild('expirydate', $this->request->post['expire_month'] . '/' . $this->request->post['expire_year']);
+ $payment_node->addChild('securitycode', $this->request->post['cvv2']);
+
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+ $operation_node->addChild('accounttypedescription', 'ECOM');
+
+ $response = $this->model_extension_payment_securetrading_ws->call($requestblock_xml->asXML());
+
+ if ($response !== false) {
+ $response_xml = simplexml_load_string($response);
+
+ if ($response_xml->response['type'] == 'THREEDQUERY') {
+ $error_code = (int)$response_xml->response->error->code;
+
+ if ($error_code == 0) {
+ $enrolled = (string)$response_xml->response->threedsecure->enrolled;
+
+ if ($enrolled == 'Y') {
+ $acs_url = (string)$response_xml->response->threedsecure->acsurl;
+ $md = (string)$response_xml->response->threedsecure->md;
+ $pareq = (string)$response_xml->response->threedsecure->pareq;
+
+ $this->model_extension_payment_securetrading_ws->addMd($order_info['order_id'], $md);
+
+ $json['status'] = 1;
+ $json['acs_url'] = $acs_url;
+ $json['md'] = $md;
+ $json['pareq'] = $pareq;
+ $json['term_url'] = $this->url->link('extension/payment/securetrading_ws/threedreturn', '', true);
+ } else {
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'AUTH');
+
+ $request_node->addChild('merchant')->addChild('orderreference', $order_info['order_id']);
+
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('parenttransactionreference', (string)$response_xml->response->transactionreference);
+ $operation_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+
+ $response = $this->model_extension_payment_securetrading_ws->call($requestblock_xml->asXML());
+
+ $json = $this->processAuthResponse($response, $order_info['order_id']);
+ }
+ } else {
+ $json['message'] = $this->language->get('text_transaction_declined');
+ $json['status'] = 0;
+ }
+ } else {
+ $json['message'] = $this->language->get('text_transaction_failed');
+ $json['status'] = 0;
+ }
+ } else {
+ $json['message'] = $this->language->get('text_connection_error');
+ $json['status'] = 0;
+ }
+ } else {
+ $country = $this->model_localisation_country->getCountry($order_info['payment_country_id']);
+
+ $json = array();
+
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'AUTH');
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('sitereference', $this->config->get('payment_securetrading_ws_site_reference'));
+ $operation_node->addChild('accounttypedescription', 'ECOM');
+
+ $merchant_node = $request_node->addChild('merchant');
+ $merchant_node->addChild('orderreference', $order_info['order_id']);
+
+ $settlement_node = $request_node->addChild('settlement');
+ $settlement_date = date('Y-m-d', strtotime(date('Y-m-d') . ' +' . $this->config->get('payment_securetrading_ws_settle_due_date') . ' days'));
+ $settlement_node->addChild('settleduedate', $settlement_date);
+ $settlement_node->addChild('settlestatus', $this->config->get('payment_securetrading_ws_settle_status'));
+
+ $billing_node = $request_node->addChild('billing');
+ $billing_node->addChild('premise', $order_info['payment_address_1']);
+ $billing_node->addChild('street', $order_info['payment_address_2']);
+ $billing_node->addChild('town', $order_info['payment_city']);
+ $billing_node->addChild('county', $order_info['payment_zone']);
+ $billing_node->addChild('country', $country['iso_code_2']);
+ $billing_node->addChild('postcode', $order_info['payment_postcode']);
+ $billing_node->addChild('email', $order_info['email']);
+ $name_node = $billing_node->addChild('name');
+
+ $name_node->addChild('first', $order_info['payment_firstname']);
+ $name_node->addChild('last', $order_info['payment_lastname']);
+
+ $amount_node = $billing_node->addChild('amount', str_replace('.', '', $this->model_extension_payment_securetrading_ws->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'])));
+ $amount_node->addAttribute('currencycode', $order_info['currency_code']);
+
+ $payment_node = $billing_node->addChild('payment');
+ $payment_node->addAttribute('type', $this->request->post['type']);
+ $payment_node->addChild('pan', $this->request->post['number']);
+ $payment_node->addChild('expirydate', $this->request->post['expire_month'] . '/' . $this->request->post['expire_year']);
+ $payment_node->addChild('securitycode', $this->request->post['cvv2']);
+
+ $response = $this->model_extension_payment_securetrading_ws->call($requestblock_xml->asXML());
+
+ $json = $this->processAuthResponse($response, $order_info['order_id']);
+ }
+ $this->response->setOutput(json_encode($json));
+ }
+ }
+
+ public function threedreturn() {
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/securetrading_ws');
+ $this->load->language('extension/payment/securetrading_ws');
+
+ // Using unmodified $_POST to access values as per Secure Trading's requirements
+ if (isset($_POST['PaRes']) && !empty($_POST['PaRes']) && isset($_POST['MD']) && !empty($_POST['MD'])) {
+ $md = $_POST['MD'];
+ $pares = $_POST['PaRes'];
+
+ $order_id = $this->model_extension_payment_securetrading_ws->getOrderId($md);
+
+ if ($order_id) {
+ $requestblock_xml = new SimpleXMLElement('<requestblock></requestblock>');
+ $requestblock_xml->addAttribute('version', '3.67');
+ $requestblock_xml->addChild('alias', $this->config->get('payment_securetrading_ws_username'));
+
+ $request_node = $requestblock_xml->addChild('request');
+ $request_node->addAttribute('type', 'AUTH');
+
+ $request_node->addChild('merchant')->addChild('orderreference', $order_id);
+
+ $operation_node = $request_node->addChild('operation');
+ $operation_node->addChild('md', $md);
+ $operation_node->addChild('pares', $pares);
+
+ $response = $this->model_extension_payment_securetrading_ws->call($requestblock_xml->asXML());
+
+ if ($response) {
+ $response_xml = simplexml_load_string($response);
+
+ $error_code = (int)$response_xml->response->error->code;
+
+ if ($error_code == 0) {
+ $postcode_status = (int)$response_xml->response->security->postcode;
+ $security_code_status = (int)$response_xml->response->security->securitycode;
+ $address_status = (int)$response_xml->response->security->address;
+ $authcode = (string)$response_xml->response->authcode;
+ $threed_status = (string)$response_xml->response->threedsecure->status;
+
+ $status_code_mapping = array(
+ 0 => $this->language->get('text_not_given'),
+ 1 => $this->language->get('text_not_checked'),
+ 2 => $this->language->get('text_match'),
+ 4 => $this->language->get('text_not_match'),
+ );
+
+ $threed_status_mapping = array(
+ 'Y' => $this->language->get('text_authenticated'),
+ 'N' => $this->language->get('text_not_authenticated'),
+ 'A' => $this->language->get('text_authentication_not_completed'),
+ 'U' => $this->language->get('text_unable_to_perform'),
+ );
+
+ $message = sprintf($this->language->get('text_auth_code'), $authcode) . "\n";
+ $message .= sprintf($this->language->get('text_postcode_check'), $status_code_mapping[$postcode_status]) . "\n";
+ $message .= sprintf($this->language->get('text_security_code_check'), $status_code_mapping[$security_code_status]) . "\n";
+ $message .= sprintf($this->language->get('text_address_check'), $status_code_mapping[$address_status]) . "\n";
+ $message .= sprintf($this->language->get('text_3d_secure_check'), $threed_status_mapping[$threed_status]) . "\n";
+
+ $transaction_reference = (string)$response_xml->response->transactionreference;
+ $this->model_extension_payment_securetrading_ws->updateReference($order_id, $transaction_reference);
+
+ $this->model_extension_payment_securetrading_ws->confirmOrder($order_id, $this->config->get('payment_securetrading_ws_order_status_id'));
+ $this->model_extension_payment_securetrading_ws->updateOrder($order_id, $this->config->get('payment_securetrading_ws_order_status_id'), $message);
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+ $this->model_extension_payment_securetrading_ws->updateOrder($order_id, $this->config->get('payment_securetrading_ws_declined_order_status_id'));
+
+ $this->session->data['error'] = $this->language->get('text_transaction_declined');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->session->data['error'] = $this->language->get('error_failure');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->session->data['error'] = $this->language->get('error_failure');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ } else {
+ $this->session->data['error'] = $this->language->get('error_failure');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ private function processAuthResponse($response, $order_id) {
+ $json = array();
+
+ if ($response !== false) {
+ $response_xml = simplexml_load_string($response);
+
+ if ($response_xml->response['type'] == 'AUTH') {
+ $error_code = (int)$response_xml->response->error->code;
+
+ if ($error_code == 0) {
+ $postcode_status = (int)$response_xml->response->security->postcode;
+ $security_code_status = (int)$response_xml->response->security->securitycode;
+ $address_status = (int)$response_xml->response->security->address;
+ $authcode = (string)$response_xml->response->authcode;
+
+ $status_code_mapping = array(
+ 0 => $this->language->get('text_not_given'),
+ 1 => $this->language->get('text_not_checked'),
+ 2 => $this->language->get('text_match'),
+ 4 => $this->language->get('text_not_match'),
+ );
+
+ $message = sprintf($this->language->get('text_auth_code'), $authcode) . "\n";
+ $message .= sprintf($this->language->get('text_postcode_check'), $status_code_mapping[$postcode_status]) . "\n";
+ $message .= sprintf($this->language->get('text_security_code_check'), $status_code_mapping[$security_code_status]) . "\n";
+ $message .= sprintf($this->language->get('text_address_check'), $status_code_mapping[$address_status]) . "\n";
+
+ $transaction_reference = (string)$response_xml->response->transactionreference;
+ $this->model_extension_payment_securetrading_ws->updateReference($order_id, $transaction_reference);
+
+ $this->model_extension_payment_securetrading_ws->confirmOrder($order_id, $this->config->get('payment_securetrading_ws_order_status_id'));
+ $this->model_extension_payment_securetrading_ws->updateOrder($order_id, $this->config->get('payment_securetrading_ws_order_status_id'), $message);
+
+ $json['redirect'] = $this->url->link('checkout/success');
+ $json['status'] = 1;
+ } else {
+ $this->model_extension_payment_securetrading_ws->updateOrder($order_id, $this->config->get('payment_securetrading_ws_declined_order_status_id'));
+
+ $json['message'] = $this->language->get('text_transaction_declined');
+ $json['status'] = 0;
+ }
+ } else {
+ $this->model_extension_payment_securetrading_ws->updateOrder($order_id, $this->config->get('payment_securetrading_ws_failed_order_status_id'));
+
+ $json['message'] = $this->language->get('text_transaction_failed');
+ $json['status'] = 0;
+ }
+ } else {
+ $json['message'] = $this->language->get('text_connection_error');
+ $json['status'] = 0;
+ }
+
+ return $json;
+ }
+}
diff --git a/public/catalog/controller/extension/payment/skrill.php b/public/catalog/controller/extension/payment/skrill.php
new file mode 100644
index 0000000..1038ee9
--- /dev/null
+++ b/public/catalog/controller/extension/payment/skrill.php
@@ -0,0 +1,106 @@
+<?php
+class ControllerExtensionPaymentSkrill extends Controller {
+ public function index() {
+ $this->load->model('checkout/order');
+
+ $this->load->language('extension/payment/skrill');
+
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $data['action'] = 'https://www.moneybookers.com/app/payment.pl?p=OpenCart';
+
+ $data['pay_to_email'] = $this->config->get('payment_skrill_email');
+ $data['platform'] = '31974336';
+ $data['description'] = $this->config->get('config_name');
+ $data['transaction_id'] = $this->session->data['order_id'];
+ $data['return_url'] = $this->url->link('checkout/success');
+ $data['cancel_url'] = $this->url->link('checkout/checkout', '', true);
+ $data['status_url'] = $this->url->link('extension/payment/skrill/callback');
+ $data['language'] = $this->session->data['language'];
+ $data['logo'] = $this->config->get('config_url') . 'image/' . $this->config->get('config_logo');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['pay_from_email'] = $order_info['email'];
+ $data['firstname'] = $order_info['payment_firstname'];
+ $data['lastname'] = $order_info['payment_lastname'];
+ $data['address'] = $order_info['payment_address_1'];
+ $data['address2'] = $order_info['payment_address_2'];
+ $data['phone_number'] = $order_info['telephone'];
+ $data['postal_code'] = $order_info['payment_postcode'];
+ $data['city'] = $order_info['payment_city'];
+ $data['state'] = $order_info['payment_zone'];
+ $data['country'] = $order_info['payment_iso_code_3'];
+ $data['amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['currency'] = $order_info['currency_code'];
+
+ $products = '';
+
+ foreach ($this->cart->getProducts() as $product) {
+ $products .= $product['quantity'] . ' x ' . $product['name'] . ', ';
+ }
+
+ $data['detail1_text'] = $products;
+
+ $data['order_id'] = $this->session->data['order_id'];
+
+ return $this->load->view('extension/payment/skrill', $data);
+ }
+
+ public function callback() {
+ if (isset($this->request->post['order_id'])) {
+ $order_id = $this->request->post['order_id'];
+ } else {
+ $order_id = 0;
+ }
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+
+ $verified = true;
+
+ // md5sig validation
+ if ($this->config->get('payment_skrill_secret')) {
+ $hash = $this->request->post['merchant_id'];
+ $hash .= $this->request->post['transaction_id'];
+ $hash .= strtoupper(md5($this->config->get('payment_skrill_secret')));
+ $hash .= $this->request->post['mb_amount'];
+ $hash .= $this->request->post['mb_currency'];
+ $hash .= $this->request->post['status'];
+
+ $md5hash = strtoupper(md5($hash));
+ $md5sig = $this->request->post['md5sig'];
+
+ if (($md5hash != $md5sig) || (strtolower($this->request->post['pay_to_email']) != strtolower($this->config->get('config_moneybookers_email'))) || ((float)$this->request->post['amount'] != $this->currency->format((float)$order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false))) {
+ $verified = false;
+ }
+ }
+
+ if ($verified) {
+ switch($this->request->post['status']) {
+ case '2':
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_skrill_order_status_id'), '', true);
+ break;
+ case '0':
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_skrill_pending_status_id'), '', true);
+ break;
+ case '-1':
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_skrill_canceled_status_id'), '', true);
+ break;
+ case '-2':
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_skrill_failed_status_id'), '', true);
+ break;
+ case '-3':
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_skrill_chargeback_status_id'), '', true);
+ break;
+ }
+ } else {
+ $this->log->write('md5sig returned (' + $md5sig + ') does not match generated (' + $md5hash + '). Verify Manually. Current order state: ' . $this->config->get('config_order_status_id'));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/squareup.php b/public/catalog/controller/extension/payment/squareup.php
new file mode 100644
index 0000000..0b7205e
--- /dev/null
+++ b/public/catalog/controller/extension/payment/squareup.php
@@ -0,0 +1,251 @@
+<?php
+
+class ControllerExtensionPaymentSquareup extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/squareup');
+
+ $this->load->library('squareup');
+
+ $data['action'] = $this->url->link('extension/payment/squareup/checkout', '', true);
+ $data['squareup_js_api'] = Squareup::PAYMENT_FORM_URL;
+
+ if (!empty($this->session->data['payment_address']['postcode'])) {
+ $data['payment_zip'] = $this->session->data['payment_address']['postcode'];
+ } else {
+ $data['payment_zip'] = '';
+ }
+
+ if ($this->config->get('payment_squareup_enable_sandbox')) {
+ $data['app_id'] = $this->config->get('payment_squareup_sandbox_client_id');
+ $data['sandbox_message'] = $this->language->get('warning_test_mode');
+ } else {
+ $data['app_id'] = $this->config->get('payment_squareup_client_id');
+ $data['sandbox_message'] = '';
+ }
+
+ $data['cards'] = array();
+
+ if ($this->customer->isLogged()) {
+ $data['is_logged'] = true;
+
+ $this->load->model('extension/credit_card/squareup');
+
+ $cards = $this->model_extension_credit_card_squareup->getCards($this->customer->getId(), $this->config->get('payment_squareup_enable_sandbox'));
+
+ foreach ($cards as $card) {
+ $data['cards'][] = array(
+ 'id' => $card['squareup_token_id'],
+ 'text' => sprintf($this->language->get('text_card_ends_in'), $card['brand'], $card['ends_in'])
+ );
+ }
+ } else {
+ $data['is_logged'] = false;
+ }
+
+ return $this->load->view('extension/payment/squareup', $data);
+ }
+
+ public function checkout() {
+ $this->load->language('extension/payment/squareup');
+
+ $this->load->model('extension/payment/squareup');
+ $this->load->model('extension/credit_card/squareup');
+ $this->load->model('checkout/order');
+ $this->load->model('localisation/country');
+
+ $this->load->library('squareup');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $shipping_country_info = $this->model_localisation_country->getCountry($order_info['shipping_country_id']);
+
+ $billing_country_info = $this->model_localisation_country->getCountry($order_info['payment_country_id']);
+
+ if (!empty($billing_country_info)) {
+ $billing_address = array(
+ 'first_name' => $order_info['payment_firstname'],
+ 'last_name' => $order_info['payment_lastname'],
+ 'address_line_1' => $order_info['payment_address_1'],
+ 'address_line_2' => $order_info['payment_address_2'],
+ 'locality' => $order_info['payment_city'],
+ 'sublocality' => $order_info['payment_zone'],
+ 'postal_code' => $order_info['payment_postcode'],
+ 'country' => $billing_country_info['iso_code_2'],
+ 'organization' => $order_info['payment_company']
+ );
+ } else {
+ $billing_address = array();
+ }
+
+ if (!empty($shipping_country_info)) {
+ $shipping_address = array(
+ 'first_name' => $order_info['shipping_firstname'],
+ 'last_name' => $order_info['shipping_lastname'],
+ 'address_line_1' => $order_info['shipping_address_1'],
+ 'address_line_2' => $order_info['shipping_address_2'],
+ 'locality' => $order_info['shipping_city'],
+ 'sublocality' => $order_info['shipping_zone'],
+ 'postal_code' => $order_info['shipping_postcode'],
+ 'country' => $shipping_country_info['iso_code_2'],
+ 'organization' => $order_info['shipping_company']
+ );
+ } else {
+ $shipping_address = array();
+ }
+
+ $json = array();
+
+ try {
+ // Ensure we have registered the customer with Square
+ $square_customer = $this->model_extension_credit_card_squareup->getCustomer($this->customer->getId(), $this->config->get('payment_squareup_enable_sandbox'));
+
+ if (!$square_customer && $this->customer->isLogged()) {
+ $square_customer = $this->squareup->addLoggedInCustomer();
+
+ $this->model_extension_credit_card_squareup->addCustomer($square_customer);
+ }
+
+ $use_saved = false;
+ $square_card_id = null;
+
+ // check if user is logged in and wanted to save this card
+ if ($this->customer->isLogged() && !empty($this->request->post['squareup_select_card'])) {
+ $card_verified = $this->model_extension_credit_card_squareup->verifyCardCustomer($this->request->post['squareup_select_card'], $this->customer->getId());
+
+ if (!$card_verified) {
+ throw new \Squareup\Exception($this->registry, $this->language->get('error_card_invalid'));
+ }
+
+ $card = $this->model_extension_credit_card_squareup->getCard($this->request->post['squareup_select_card']);
+
+ $use_saved = true;
+ $square_card_id = $card['token'];
+ } else if ($this->customer->isLogged() && isset($this->request->post['squareup_save_card'])) {
+ // Save the card
+ $card_data = array(
+ 'card_nonce' => $this->request->post['squareup_nonce'],
+ 'billing_address' => $billing_address,
+ 'cardholder_name' => $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname']
+ );
+
+ $square_card = $this->squareup->addCard($square_customer['square_customer_id'], $card_data);
+
+ if (!$this->model_extension_credit_card_squareup->cardExists($this->customer->getId(), $square_card)) {
+ $this->model_extension_credit_card_squareup->addCard($this->customer->getId(), $this->config->get('payment_squareup_enable_sandbox'), $square_card);
+ }
+
+ $use_saved = true;
+ $square_card_id = $square_card['id'];
+ }
+
+ // Prepare Transaction
+ $transaction_data = array(
+ 'idempotency_key' => uniqid(),
+ 'amount_money' => array(
+ 'amount' => $this->squareup->lowestDenomination($order_info['total'], $order_info['currency_code']),
+ 'currency' => $order_info['currency_code']
+ ),
+ 'billing_address' => $billing_address,
+ 'buyer_email_address' => $order_info['email'],
+ 'delay_capture' => !$this->cart->hasRecurringProducts() && $this->config->get('payment_squareup_delay_capture'),
+ 'integration_id' => Squareup::SQUARE_INTEGRATION_ID
+ );
+
+ if (!empty($shipping_address)) {
+ $transaction_data['shipping_address'] = $shipping_address;
+ }
+
+ if ($use_saved) {
+ $transaction_data['customer_card_id'] = $square_card_id;
+ $transaction_data['customer_id'] = $square_customer['square_customer_id'];
+ } else {
+ $transaction_data['card_nonce'] = $this->request->post['squareup_nonce'];
+ }
+
+ $transaction = $this->squareup->addTransaction($transaction_data);
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $user_agent = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $user_agent = '';
+ }
+
+ if (isset($this->request->server['REMOTE_ADDR'])) {
+ $ip = $this->request->server['REMOTE_ADDR'];
+ } else {
+ $ip = '';
+ }
+
+ $this->model_extension_payment_squareup->addTransaction($transaction, $this->config->get('payment_squareup_merchant_id'), $billing_address, $this->session->data['order_id'], $user_agent, $ip);
+
+ if (!empty($transaction['tenders'][0]['card_details']['status'])) {
+ $transaction_status = strtolower($transaction['tenders'][0]['card_details']['status']);
+ } else {
+ $transaction_status = '';
+ }
+
+ $order_status_id = $this->config->get('payment_squareup_status_' . $transaction_status);
+
+ if ($order_status_id) {
+ if ($this->cart->hasRecurringProducts() && $transaction_status == 'captured') {
+ foreach ($this->cart->getRecurringProducts() as $item) {
+ if ($item['recurring']['trial']) {
+ $trial_price = $this->tax->calculate($item['recurring']['trial_price'] * $item['quantity'], $item['tax_class_id']);
+ $trial_amt = $this->currency->format($trial_price, $this->session->data['currency']);
+ $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
+
+ $item['recurring']['trial_price'] = $trial_price;
+ } else {
+ $trial_text = '';
+ }
+
+ $recurring_price = $this->tax->calculate($item['recurring']['price'] * $item['quantity'], $item['tax_class_id']);
+ $recurring_amt = $this->currency->format($recurring_price, $this->session->data['currency']);
+ $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
+
+ $item['recurring']['price'] = $recurring_price;
+
+ if ($item['recurring']['duration'] > 0) {
+ $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
+ }
+
+ if (!$item['recurring']['trial']) {
+ // We need to override this value for the proper calculation in updateRecurringExpired
+ $item['recurring']['trial_duration'] = 0;
+ }
+
+
+ $this->model_extension_payment_squareup->createRecurring($item, $this->session->data['order_id'], $recurring_description, $transaction['id']);
+ }
+ }
+
+ $order_status_comment = $this->language->get('squareup_status_comment_' . $transaction_status);
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $order_status_id, $order_status_comment, true);
+ }
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ } catch (\Squareup\Exception $e) {
+ if ($e->isCurlError()) {
+ $json['error'] = $this->language->get('text_token_issue_customer_error');
+ } else if ($e->isAccessTokenRevoked()) {
+ // Send reminder e-mail to store admin to refresh the token
+ $this->model_extension_payment_squareup->tokenRevokedEmail();
+
+ $json['error'] = $this->language->get('text_token_issue_customer_error');
+ } else if ($e->isAccessTokenExpired()) {
+ // Send reminder e-mail to store admin to refresh the token
+ $this->model_extension_payment_squareup->tokenExpiredEmail();
+
+ $json['error'] = $this->language->get('text_token_issue_customer_error');
+ } else {
+ $json['error'] = $e->getMessage();
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+
+}
diff --git a/public/catalog/controller/extension/payment/twocheckout.php b/public/catalog/controller/extension/payment/twocheckout.php
new file mode 100644
index 0000000..140a68f
--- /dev/null
+++ b/public/catalog/controller/extension/payment/twocheckout.php
@@ -0,0 +1,114 @@
+<?php
+class ControllerExtensionPaymentTwoCheckout extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $data['action'] = 'https://www.2checkout.com/checkout/purchase';
+
+ $data['sid'] = $this->config->get('payment_twocheckout_account');
+ $data['currency_code'] = $order_info['currency_code'];
+ $data['total'] = $this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false);
+ $data['cart_order_id'] = $this->session->data['order_id'];
+ $data['card_holder_name'] = $order_info['payment_firstname'] . ' ' . $order_info['payment_lastname'];
+ $data['street_address'] = $order_info['payment_address_1'];
+ $data['city'] = $order_info['payment_city'];
+
+ if ($order_info['payment_iso_code_2'] == 'US' || $order_info['payment_iso_code_2'] == 'CA') {
+ $data['state'] = $order_info['payment_zone'];
+ } else {
+ $data['state'] = 'XX';
+ }
+
+ $data['zip'] = $order_info['payment_postcode'];
+ $data['country'] = $order_info['payment_country'];
+ $data['email'] = $order_info['email'];
+ $data['phone'] = $order_info['telephone'];
+
+ if ($this->cart->hasShipping()) {
+ $data['ship_street_address'] = $order_info['shipping_address_1'];
+ $data['ship_city'] = $order_info['shipping_city'];
+ $data['ship_state'] = $order_info['shipping_zone'];
+ $data['ship_zip'] = $order_info['shipping_postcode'];
+ $data['ship_country'] = $order_info['shipping_country'];
+ } else {
+ $data['ship_street_address'] = $order_info['payment_address_1'];
+ $data['ship_city'] = $order_info['payment_city'];
+ $data['ship_state'] = $order_info['payment_zone'];
+ $data['ship_zip'] = $order_info['payment_postcode'];
+ $data['ship_country'] = $order_info['payment_country'];
+ }
+
+ $data['products'] = array();
+
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $data['products'][] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'description' => $product['name'],
+ 'quantity' => $product['quantity'],
+ 'price' => $this->currency->format($product['price'], $order_info['currency_code'], $order_info['currency_value'], false)
+ );
+ }
+
+ if ($this->config->get('payment_twocheckout_test')) {
+ $data['demo'] = 'Y';
+ } else {
+ $data['demo'] = '';
+ }
+
+ if ($this->config->get('payment_twocheckout_display')) {
+ $data['display'] = 'Y';
+ } else {
+ $data['display'] = '';
+ }
+
+ $data['lang'] = $this->session->data['language'];
+
+ $data['return_url'] = $this->url->link('extension/payment/twocheckout/callback', '', true);
+
+ return $this->load->view('extension/payment/twocheckout', $data);
+ }
+
+ public function callback() {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->request->post['cart_order_id']);
+
+ if (!$this->config->get('payment_twocheckout_test')) {
+ $order_number = $this->request->post['order_number'];
+ } else {
+ $order_number = '1';
+ }
+
+ if (strtoupper(md5($this->config->get('payment_twocheckout_secret') . $this->config->get('payment_twocheckout_account') . $order_number . $this->request->post['total'])) == $this->request->post['key']) {
+ if ($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false) == $this->request->post['total']) {
+ $this->model_checkout_order->addOrderHistory($this->request->post['cart_order_id'], $this->config->get('payment_twocheckout_order_status_id'));
+ } else {
+ $this->model_checkout_order->addOrderHistory($this->request->post['cart_order_id'], $this->config->get('config_order_status_id'));// Ugh. Some one've faked the sum. What should we do? Probably drop a mail to the shop owner?
+ }
+
+ // We can't use $this->response->redirect() here, because of 2CO behavior. It fetches this page
+ // on behalf of the user and thus user (and his browser) see this as located at 2checkout.com
+ // domain. So user's cookies are not here and he will see empty basket and probably other
+ // weird things.
+
+ echo '<html>' . "\n";
+ echo '<head>' . "\n";
+ echo ' <meta http-equiv="Refresh" content="0; url=' . $this->url->link('checkout/success') . '">' . "\n";
+ echo '</head>' . "\n";
+ echo '<body>' . "\n";
+ echo ' <p>Please follow <a href="' . $this->url->link('checkout/success') . '">link</a>!</p>' . "\n";
+ echo '</body>' . "\n";
+ echo '</html>' . "\n";
+ exit();
+ } else {
+ echo 'The response from 2checkout.com can\'t be parsed. Contact site administrator, please!';
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/web_payment_software.php b/public/catalog/controller/extension/payment/web_payment_software.php
new file mode 100644
index 0000000..958e90d
--- /dev/null
+++ b/public/catalog/controller/extension/payment/web_payment_software.php
@@ -0,0 +1,134 @@
+<?php
+class ControllerExtensionPaymentWebPaymentSoftware extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/web_payment_software');
+
+ $data['months'] = array();
+
+ for ($i = 1; $i <= 12; $i++) {
+ $data['months'][] = array(
+ 'text' => strftime('%B', mktime(0, 0, 0, $i, 1, 2000)),
+ 'value' => sprintf('%02d', $i)
+ );
+ }
+
+ $today = getdate();
+
+ $data['year_expire'] = array();
+
+ for ($i = $today['year']; $i < $today['year'] + 11; $i++) {
+ $data['year_expire'][] = array(
+ 'text' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i)),
+ 'value' => strftime('%Y', mktime(0, 0, 0, 1, 1, $i))
+ );
+ }
+
+ return $this->load->view('extension/payment/web_payment_software', $data);
+ }
+
+ public function send() {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $request = 'MERCHANT_ID=' . urlencode($this->config->get('payment_web_payment_software_merchant_name'));
+ $request .= '&MERCHANT_KEY=' . urlencode($this->config->get('payment_web_payment_software_merchant_key'));
+ $request .= '&TRANS_TYPE=' . urlencode($this->config->get('payment_web_payment_software_method') == 'capture' ? 'AuthCapture' : 'AuthOnly');
+ $request .= '&AMOUNT=' . urlencode($this->currency->format($order_info['total'], $order_info['currency_code'], 1.00000, false));
+ $request .= '&CC_NUMBER=' . urlencode(str_replace(' ', '', $this->request->post['cc_number']));
+ $request .= '&CC_EXP=' . urlencode($this->request->post['cc_expire_date_month'] . substr($this->request->post['cc_expire_date_year'], 2));
+ $request .= '&CC_CVV=' . urlencode($this->request->post['cc_cvv2']);
+ $request .= '&CC_NAME=' . urlencode($order_info['payment_firstname'] . ' ' . $order_info['payment_lastname']);
+ $request .= '&CC_COMPANY=' . urlencode($order_info['payment_company']);
+ $request .= '&CC_ADDRESS=' . urlencode($order_info['payment_address_1']);
+ $request .= '&CC_CITY=' . urlencode($order_info['payment_city']);
+ $request .= '&CC_STATE=' . urlencode($order_info['payment_iso_code_2'] != 'US' ? $order_info['payment_zone'] : $order_info['payment_zone_code']);
+ $request .= '&CC_ZIP=' . urlencode($order_info['payment_postcode']);
+ $request .= '&CC_COUNTRY=' . urlencode($order_info['payment_country']);
+ $request .= '&CC_PHONE=' . urlencode($order_info['telephone']);
+ $request .= '&CC_EMAIL=' . urlencode($order_info['email']);
+ $request .= '&INVOICE_NUM=' . urlencode($this->session->data['order_id']);
+
+ if ($this->config->get('payment_web_payment_software_mode') == 'test') {
+ $request .= '&TEST_MODE=1';
+ }
+
+ $curl = curl_init('https://secure.web-payment-software.com/gateway');
+
+ curl_setopt($curl, CURLOPT_PORT, 443);
+ curl_setopt($curl, CURLOPT_HEADER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
+ curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
+ curl_setopt($curl, CURLOPT_POST, 1);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+
+ $response = curl_exec($curl);
+
+ curl_close($curl);
+
+ //If in test mode strip results to only contain xml data
+ if ($this->config->get('payment_web_payment_software_mode') == 'test') {
+ $end_index = strpos($response, '</WebPaymentSoftwareResponse>');
+ $debug = substr($response, $end_index + 30);
+ $response = substr($response, 0, $end_index) . '</WebPaymentSoftwareResponse>';
+ }
+
+ //get response xml
+ $xml = simplexml_load_string($response);
+
+ //create object to use as json
+ $json = array();
+
+ //If successful log transaction in opencart system
+ if ('00' === (string)$xml->response_code) {
+ $message = '';
+
+ $message .= 'Response Code: ';
+
+ if (isset($xml->response_code)) {
+ $message .= (string)$xml->response_code . "\n";
+ }
+
+ $message .= 'Approval Code: ';
+
+ if (isset($xml->approval_code)) {
+ $message .= (string)$xml->approval_code . "\n";
+ }
+
+ $message .= 'AVS Result Code: ';
+
+ if (isset($xml->avs_result_code)) {
+ $message .= (string)$xml->avs_result_code . "\n";
+ }
+
+ $message .= 'Transaction ID (web payment software order id): ';
+
+ if (isset($xml->order_id)) {
+ $message .= (string)$xml->order_id . "\n";
+ }
+
+ $message .= 'CVV Result Code: ';
+
+ if (isset($xml->cvv_result_code)) {
+ $message .= (string)$xml->cvv_result_code . "\n";
+ }
+
+ $message .= 'Response Text: ';
+
+ if (isset($xml->response_text)) {
+ $message .= (string)$xml->response_text . "\n";
+ }
+
+ $this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('payment_web_payment_software_order_status_id'), $message, false);
+
+ $json['redirect'] = $this->url->link('checkout/success', '', true);
+ } else {
+ $json['error'] = (string)$xml->response_text;
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/payment/wechat_pay.php b/public/catalog/controller/extension/payment/wechat_pay.php
new file mode 100644
index 0000000..0affd0c
--- /dev/null
+++ b/public/catalog/controller/extension/payment/wechat_pay.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * @package OpenCart
+ * @author Meng Wenbin
+ * @copyright Copyright (c) 2010 - 2017, Chengdu Guangda Network Technology Co. Ltd. (https://www.opencart.cn/)
+ * @license https://opensource.org/licenses/GPL-3.0
+ * @link https://www.opencart.cn
+ */
+
+class ControllerExtensionPaymentWechatPay extends Controller {
+ public function index() {
+ $data['button_confirm'] = $this->language->get('button_confirm');
+
+ $data['redirect'] = $this->url->link('extension/payment/wechat_pay/qrcode');
+
+ return $this->load->view('extension/payment/wechat_pay', $data);
+ }
+
+ public function qrcode() {
+ $this->load->language('extension/payment/wechat_pay');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+ $this->document->addScript('catalog/view/javascript/qrcode.js');
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_checkout'),
+ 'href' => $this->url->link('checkout/checkout', '', true)
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_qrcode'),
+ 'href' => $this->url->link('extension/payment/wechat_pay/qrcode')
+ );
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $order_id = trim($order_info['order_id']);
+ $data['order_id'] = $order_id;
+ $subject = trim($this->config->get('config_name'));
+ $currency = $this->config->get('payment_wechat_pay_currency');
+ $total_amount = trim($this->currency->format($order_info['total'], $currency, '', false));
+ $notify_url = HTTPS_SERVER . "payment_callback/wechat_pay"; //$this->url->link('wechat_pay/callback');
+
+ $options = array(
+ 'appid' => $this->config->get('payment_wechat_pay_app_id'),
+ 'appsecret' => $this->config->get('payment_wechat_pay_app_secret'),
+ 'mch_id' => $this->config->get('payment_wechat_pay_mch_id'),
+ 'partnerkey' => $this->config->get('payment_wechat_pay_api_secret')
+ );
+
+ \Wechat\Loader::config($options);
+ $pay = new \Wechat\WechatPay();
+
+ $result = $pay->getPrepayId(NULL, $subject, $order_id, $total_amount * 100, $notify_url, $trade_type = "NATIVE", NULL, $currency);
+
+ $data['error'] = '';
+ $data['code_url'] = '';
+ if($result === FALSE){
+ $data['error_warning'] = $pay->errMsg;
+ } else {
+ $data['code_url'] = $result;
+ }
+
+ $data['action_success'] = $this->url->link('checkout/success');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/wechat_pay_qrcode', $data));
+ }
+
+ public function isOrderPaid() {
+ $json = array();
+
+ $json['result'] = false;
+
+ if (isset($this->request->get['order_id'])) {
+ $order_id = $this->request->get['order_id'];
+
+ $this->load->model('checkout/order');
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info['order_status_id'] == $this->config->get('payment_wechat_pay_completed_status_id')) {
+ $json['result'] = true;
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function callback() {
+ $options = array(
+ 'appid' => $this->config->get('payment_wechat_pay_app_id'),
+ 'appsecret' => $this->config->get('payment_wechat_pay_app_secret'),
+ 'mch_id' => $this->config->get('payment_wechat_pay_mch_id'),
+ 'partnerkey' => $this->config->get('payment_wechat_pay_api_secret')
+ );
+
+ \Wechat\Loader::config($options);
+ $pay = new \Wechat\WechatPay();
+ $notifyInfo = $pay->getNotify();
+
+ if ($notifyInfo === FALSE) {
+ $this->log->write('Wechat Pay Error: ' . $pay->errMsg);
+ } else {
+ if ($notifyInfo['result_code'] == 'SUCCESS' && $notifyInfo['return_code'] == 'SUCCESS') {
+ $order_id = $notifyInfo['out_trade_no'];
+ $this->load->model('checkout/order');
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+ if ($order_info) {
+ $order_status_id = $order_info["order_status_id"];
+ if (!$order_status_id) {
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_wechat_pay_completed_status_id'));
+ }
+ }
+ return xml(['return_code' => 'SUCCESS', 'return_msg' => 'DEAL WITH SUCCESS']);
+ }
+ }
+ }
+}
diff --git a/public/catalog/controller/extension/payment/worldpay.php b/public/catalog/controller/extension/payment/worldpay.php
new file mode 100644
index 0000000..eae4c20
--- /dev/null
+++ b/public/catalog/controller/extension/payment/worldpay.php
@@ -0,0 +1,201 @@
+<?php
+class ControllerExtensionPaymentWorldpay extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/worldpay');
+
+ $data['worldpay_script'] = 'https://cdn.worldpay.com/v1/worldpay.js';
+
+ $data['worldpay_client_key'] = $this->config->get('payment_worldpay_client_key');
+
+ $data['form_submit'] = $this->url->link('extension/payment/worldpay/send', '', true);
+
+ if ($this->config->get('payment_worldpay_card') == '1' && $this->customer->isLogged()) {
+ $data['payment_worldpay_card'] = true;
+ } else {
+ $data['payment_worldpay_card'] = false;
+ }
+
+ $data['existing_cards'] = array();
+
+ if ($this->customer->isLogged() && $data['payment_worldpay_card']) {
+ $this->load->model('extension/payment/worldpay');
+ $data['existing_cards'] = $this->model_extension_payment_worldpay->getCards($this->customer->getId());
+ }
+
+ $recurring_products = $this->cart->getRecurringProducts();
+
+ if (!empty($recurring_products)) {
+ $data['recurring_products'] = true;
+ }
+
+ return $this->load->view('extension/payment/worldpay', $data);
+ }
+
+ public function send() {
+ $this->load->language('extension/payment/worldpay');
+ $this->load->model('checkout/order');
+ $this->load->model('localisation/country');
+ $this->load->model('extension/payment/worldpay');
+
+ $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
+
+ $recurring_products = $this->cart->getRecurringProducts();
+
+ if (empty($recurring_products)) {
+ $order_type = 'ECOM';
+ } else {
+ $order_type = 'RECURRING';
+ }
+
+ $country_info = $this->model_localisation_country->getCountry($order_info['payment_country_id']);
+
+ $billing_address = array(
+ "address1" => $order_info['payment_address_1'],
+ "address2" => $order_info['payment_address_2'],
+ "address3" => '',
+ "postalCode" => $order_info['payment_postcode'],
+ "city" => $order_info['payment_city'],
+ "state" => $order_info['payment_zone'],
+ "countryCode" => $country_info['iso_code_2'],
+ );
+
+ $order = array(
+ "token" => $this->request->post['token'],
+ "orderType" => $order_type,
+ "amount" => round($this->currency->format($order_info['total'], $order_info['currency_code'], $order_info['currency_value'], false)*100),
+ "currencyCode" => $order_info['currency_code'],
+ "name" => $order_info['firstname'] . ' ' . $order_info['lastname'],
+ "orderDescription" => $order_info['store_name'] . ' - ' . date('Y-m-d H:i:s'),
+ "customerOrderCode" => $order_info['order_id'],
+ "billingAddress" => $billing_address
+ );
+
+ $this->model_extension_payment_worldpay->logger($order);
+
+ $response_data = $this->model_extension_payment_worldpay->sendCurl('orders', $order);
+
+ $this->model_extension_payment_worldpay->logger($response_data);
+
+ if (isset($response_data->paymentStatus) && $response_data->paymentStatus == 'SUCCESS') {
+ $this->model_checkout_order->addOrderHistory($order_info['order_id'], $this->config->get('config_order_status_id'));
+
+ $worldpay_order_id = $this->model_extension_payment_worldpay->addOrder($order_info, $response_data->orderCode);
+
+ $this->model_extension_payment_worldpay->addTransaction($worldpay_order_id, 'payment', $order_info);
+
+ if (isset($this->request->post['save-card'])) {
+ $response = $this->model_extension_payment_worldpay->sendCurl('tokens/' . $this->request->post['token']);
+
+ $this->model_extension_payment_worldpay->logger($response);
+
+ $expiry_date = mktime(0, 0, 0, 0, (string)$response->paymentMethod->expiryMonth, (string)$response->paymentMethod->expiryYear);
+
+ if (isset($response->paymentMethod)) {
+ $card_data = array();
+ $card_data['customer_id'] = $this->customer->getId();
+ $card_data['Token'] = $response->token;
+ $card_data['Last4Digits'] = (string)$response->paymentMethod->maskedCardNumber;
+ $card_data['ExpiryDate'] = date("m/y", $expiry_date);
+ $card_data['CardType'] = (string)$response->paymentMethod->cardType;
+ $this->model_extension_payment_worldpay->addCard($this->session->data['order_id'], $card_data);
+ }
+ }
+
+ //loop through any products that are recurring items
+ foreach ($recurring_products as $item) {
+ $this->model_extension_payment_worldpay->recurringPayment($item, $this->session->data['order_id'] . rand(), $this->request->post['token']);
+ }
+
+ $this->response->redirect($this->url->link('checkout/success', '', true));
+ } else {
+
+ $this->session->data['error'] = $this->language->get('error_process_order');
+ $this->response->redirect($this->url->link('checkout/checkout', '', true));
+ }
+ }
+
+ public function deleteCard() {
+ $this->load->language('extension/payment/worldpay');
+ $this->load->model('extension/payment/worldpay');
+
+ if (isset($this->request->post['token'])) {
+ if ($this->model_extension_payment_worldpay->deleteCard($this->request->post['token'])) {
+ $json['success'] = $this->language->get('text_card_success');
+ } else {
+ $json['error'] = $this->language->get('text_card_error');
+ }
+
+ if (count($this->model_extension_payment_worldpay->getCards($this->customer->getId()))) {
+ $json['existing_cards'] = true;
+ }
+ } else {
+ $json['error'] = $this->language->get('text_error');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function webhook() {
+ if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_worldpay_secret_token'), $this->request->get['token'])) {
+ $this->load->model('extension/payment/worldpay');
+ $message = json_decode(file_get_contents('php://input'), true);
+
+ if (isset($message['orderCode'])) {
+ $order = $this->model_extension_payment_worldpay->getWorldpayOrder($message['orderCode']);
+ $this->model_extension_payment_worldpay->logger($order);
+ switch ($message['paymentStatus']) {
+ case 'SUCCESS':
+ $order_status_id = $this->config->get('payment_worldpay_success_status_id');
+ break;
+ case 'FAILED':
+ $order_status_id = $this->config->get('payment_worldpay_failed_status_id');
+ break;
+ case 'SETTLED':
+ $order_status_id = $this->config->get('payment_worldpay_settled_status_id');
+ break;
+ case 'REFUNDED':
+ $order_status_id = $this->config->get('payment_worldpay_refunded_status_id');
+ break;
+ case 'PARTIALLY_REFUNDED':
+ $order_status_id = $this->config->get('payment_worldpay_partially_refunded_status_id');
+ break;
+ case 'CHARGED_BACK':
+ $order_status_id = $this->config->get('payment_worldpay_charged_back_status_id');
+ break;
+ case 'INFORMATION_REQUESTED':
+ $order_status_id = $this->config->get('payment_worldpay_information_requested_status_id');
+ break;
+ case 'INFORMATION_SUPPLIED':
+ $order_status_id = $this->config->get('payment_worldpay_information_supplied_status_id');
+ break;
+ case 'CHARGEBACK_REVERSED':
+ $order_status_id = $this->config->get('payment_worldpay_chargeback_reversed_status_id');
+ break;
+ }
+
+ $this->model_extension_payment_worldpay->logger($order_status_id);
+ if (isset($order['order_id'])) {
+ $this->load->model('checkout/order');
+ $this->model_checkout_order->addOrderHistory($order['order_id'], $order_status_id);
+ }
+ }
+ }
+
+ $this->response->addHeader('HTTP/1.1 200 OK');
+ $this->response->addHeader('Content-Type: application/json');
+ }
+
+ public function cron() {
+ if ($this->request->get['token'] == $this->config->get('payment_worldpay_secret_token')) {
+ $this->load->model('extension/payment/worldpay');
+
+ $orders = $this->model_extension_payment_worldpay->cronPayment();
+
+ $this->model_extension_payment_worldpay->updateCronJobRunTime();
+
+ $this->model_extension_payment_worldpay->logger($orders);
+ }
+ }
+
+}
diff --git a/public/catalog/controller/extension/recurring/pp_express.php b/public/catalog/controller/extension/recurring/pp_express.php
new file mode 100644
index 0000000..0124770
--- /dev/null
+++ b/public/catalog/controller/extension/recurring/pp_express.php
@@ -0,0 +1,106 @@
+<?php
+class ControllerExtensionRecurringPPExpress extends Controller {
+ public function index() {
+ $this->load->language('extension/recurring/pp_express');
+
+ if (isset($this->request->get['order_recurring_id'])) {
+ $order_recurring_id = $this->request->get['order_recurring_id'];
+ } else {
+ $order_recurring_id = 0;
+ }
+
+ $this->load->model('account/recurring');
+
+ $recurring_info = $this->model_account_recurring->getOrderRecurring($order_recurring_id);
+
+ if ($recurring_info) {
+ $data['continue'] = $this->url->link('account/recurring', '', true);
+
+ if ($recurring_info['status'] == 2 || $recurring_info['status'] == 3) {
+ $data['order_recurring_id'] = $order_recurring_id;
+ } else {
+ $data['order_recurring_id'] = '';
+ }
+
+ return $this->load->view('extension/recurring/pp_express', $data);
+ }
+ }
+
+ public function cancel() {
+ $json = array();
+
+ $this->load->language('extension/recurring/pp_express');
+
+ //cancel an active recurring
+ $this->load->model('account/recurring');
+
+ if (isset($this->request->get['order_recurring_id'])) {
+ $order_recurring_id = $this->request->get['order_recurring_id'];
+ } else {
+ $order_recurring_id = 0;
+ }
+
+ $recurring_info = $this->model_account_recurring->getOrderRecurring($order_recurring_id);
+
+ if ($recurring_info && $recurring_info['reference']) {
+ if ($this->config->get('payment_pp_express_test')) {
+ $api_url = 'https://api-3t.sandbox.paypal.com/nvp';
+ $api_username = $this->config->get('payment_pp_express_sandbox_username');
+ $api_password = $this->config->get('payment_pp_express_sandbox_password');
+ $api_signature = $this->config->get('payment_pp_express_sandbox_signature');
+ } else {
+ $api_url = 'https://api-3t.paypal.com/nvp';
+ $api_username = $this->config->get('payment_pp_express_username');
+ $api_password = $this->config->get('payment_pp_express_password');
+ $api_signature = $this->config->get('payment_pp_express_signature');
+ }
+
+ $request = array(
+ 'USER' => $api_username,
+ 'PWD' => $api_password,
+ 'SIGNATURE' => $api_signature,
+ 'VERSION' => '109.0',
+ 'BUTTONSOURCE' => 'OpenCart_2.0_EC',
+ 'METHOD' => 'SetExpressCheckout',
+ 'METHOD' => 'ManageRecurringPaymentsProfileStatus',
+ 'PROFILEID' => $recurring_info['reference'],
+ 'ACTION' => 'Cancel'
+ );
+
+ $curl = curl_init($api_url);
+
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_HEADER, false);
+ curl_setopt($curl, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+
+ $response = curl_exec($curl);
+
+ if (!$response) {
+ $this->log(sprintf($this->language->get('error_curl'), curl_errno($curl), curl_error($curl)));
+ }
+
+ curl_close($curl);
+
+ $response_info = array();
+
+ parse_str($response, $response_info);
+
+ if (isset($response_info['PROFILEID'])) {
+ $this->model_account_recurring->editOrderRecurringStatus($order_recurring_id, 4);
+ $this->model_account_recurring->addOrderRecurringTransaction($order_recurring_id, 5);
+
+ $json['success'] = $this->language->get('text_cancelled');
+ } else {
+ $json['error'] = sprintf($this->language->get('error_not_cancelled'), $response_info['L_LONGMESSAGE0']);
+ }
+ } else {
+ $json['error'] = $this->language->get('error_not_found');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/recurring/squareup.php b/public/catalog/controller/extension/recurring/squareup.php
new file mode 100644
index 0000000..eabc932
--- /dev/null
+++ b/public/catalog/controller/extension/recurring/squareup.php
@@ -0,0 +1,170 @@
+<?php
+class ControllerExtensionRecurringSquareup extends Controller {
+ public function index() {
+ $this->load->language('extension/recurring/squareup');
+
+ $this->load->model('account/recurring');
+ $this->load->model('extension/payment/squareup');
+
+ if (isset($this->request->get['order_recurring_id'])) {
+ $order_recurring_id = $this->request->get['order_recurring_id'];
+ } else {
+ $order_recurring_id = 0;
+ }
+
+ $recurring_info = $this->model_account_recurring->getOrderRecurring($order_recurring_id);
+
+ if ($recurring_info) {
+ $data['cancel_url'] = html_entity_decode($this->url->link('extension/recurring/squareup/cancel', 'order_recurring_id=' . $order_recurring_id, 'SSL'));
+
+ $data['continue'] = $this->url->link('account/recurring', '', true);
+
+ if ($recurring_info['status'] == ModelExtensionPaymentSquareup::RECURRING_ACTIVE) {
+ $data['order_recurring_id'] = $order_recurring_id;
+ } else {
+ $data['order_recurring_id'] = '';
+ }
+
+ return $this->load->view('extension/recurring/squareup', $data);
+ }
+ }
+
+ public function cancel() {
+ $this->load->language('extension/recurring/squareup');
+
+ $this->load->model('account/recurring');
+ $this->load->model('extension/payment/squareup');
+
+ if (isset($this->request->get['order_recurring_id'])) {
+ $order_recurring_id = $this->request->get['order_recurring_id'];
+ } else {
+ $order_recurring_id = 0;
+ }
+
+ $json = array();
+
+ $recurring_info = $this->model_account_recurring->getOrderRecurring($order_recurring_id);
+
+ if ($recurring_info) {
+ $this->model_account_recurring->editOrderRecurringStatus($order_recurring_id, ModelExtensionPaymentSquareup::RECURRING_CANCELLED);
+
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($recurring_info['order_id']);
+
+ $this->model_checkout_order->addOrderHistory($recurring_info['order_id'], $order_info['order_status_id'], $this->language->get('text_order_history_cancel'), true);
+
+ $json['success'] = $this->language->get('text_canceled');
+ } else {
+ $json['error'] = $this->language->get('error_not_found');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function recurring() {
+ $this->load->language('extension/payment/squareup');
+
+ $this->load->model('extension/payment/squareup');
+
+ if (!$this->model_extension_payment_squareup->validateCRON()) {
+ return;
+ }
+
+ $this->load->library('squareup');
+
+ $result = array(
+ 'transaction_success' => array(),
+ 'transaction_error' => array(),
+ 'transaction_fail' => array(),
+ 'token_update_error' => ''
+ );
+
+ $result['token_update_error'] = $this->model_extension_payment_squareup->updateToken();
+
+ $this->load->model('checkout/order');
+
+ foreach ($this->model_extension_payment_squareup->nextRecurringPayments() as $payment) {
+ try {
+ if (!$payment['is_free']) {
+ $transaction = $this->squareup->addTransaction($payment['transaction']);
+
+ $transaction_status = !empty($transaction['tenders'][0]['card_details']['status']) ?
+ strtolower($transaction['tenders'][0]['card_details']['status']) : '';
+
+ $target_currency = $transaction['tenders'][0]['amount_money']['currency'];
+
+ $amount = $this->squareup->standardDenomination($transaction['tenders'][0]['amount_money']['amount'], $target_currency);
+
+ $this->model_extension_payment_squareup->addTransaction($transaction, $this->config->get('payment_squareup_merchant_id'), $payment['billing_address'], $payment['order_id'], "CRON JOB", "127.0.0.1");
+
+ $reference = $transaction['id'];
+ } else {
+ $amount = 0;
+ $target_currency = $this->config->get('config_currency');
+ $reference = '';
+ $transaction_status = 'captured';
+ }
+
+ $success = $transaction_status == 'captured';
+
+ $this->model_extension_payment_squareup->addRecurringTransaction($payment['order_recurring_id'], $reference, $amount, $success);
+
+ $trial_expired = false;
+ $recurring_expired = false;
+ $profile_suspended = false;
+
+ if ($success) {
+ $trial_expired = $this->model_extension_payment_squareup->updateRecurringTrial($payment['order_recurring_id']);
+
+ $recurring_expired = $this->model_extension_payment_squareup->updateRecurringExpired($payment['order_recurring_id']);
+
+ $result['transaction_success'][$payment['order_recurring_id']] = $this->currency->format($amount, $target_currency);
+ } else {
+ // Transaction was not successful. Suspend the recurring profile.
+ $profile_suspended = $this->model_extension_payment_squareup->suspendRecurringProfile($payment['order_recurring_id']);
+
+ $result['transaction_fail'][$payment['order_recurring_id']] = $this->currency->format($amount, $target_currency);
+ }
+
+
+ $order_status_id = $this->config->get('payment_squareup_status_' . $transaction_status);
+
+ if ($order_status_id) {
+ if (!$payment['is_free']) {
+ $order_status_comment = $this->language->get('squareup_status_comment_' . $transaction_status);
+ } else {
+ $order_status_comment = '';
+ }
+
+ if ($profile_suspended) {
+ $order_status_comment .= $this->language->get('text_squareup_profile_suspended');
+ }
+
+ if ($trial_expired) {
+ $order_status_comment .= $this->language->get('text_squareup_trial_expired');
+ }
+
+ if ($recurring_expired) {
+ $order_status_comment .= $this->language->get('text_squareup_recurring_expired');
+ }
+
+ if ($success) {
+ $notify = (bool)$this->config->get('payment_squareup_notify_recurring_success');
+ } else {
+ $notify = (bool)$this->config->get('payment_squareup_notify_recurring_fail');
+ }
+
+ $this->model_checkout_order->addOrderHistory($payment['order_id'], $order_status_id, trim($order_status_comment), $notify);
+ }
+ } catch (\Squareup\Exception $e) {
+ $result['transaction_error'][] = '[ID: ' . $payment['order_recurring_id'] . '] - ' . $e->getMessage();
+ }
+ };
+
+ if ($this->config->get('payment_squareup_cron_email_status')) {
+ $this->model_extension_payment_squareup->cronEmail($result);
+ }
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/total/coupon.php b/public/catalog/controller/extension/total/coupon.php
new file mode 100644
index 0000000..d7db2c7
--- /dev/null
+++ b/public/catalog/controller/extension/total/coupon.php
@@ -0,0 +1,49 @@
+<?php
+class ControllerExtensionTotalCoupon extends Controller {
+ public function index() {
+ if ($this->config->get('total_coupon_status')) {
+ $this->load->language('extension/total/coupon');
+
+ if (isset($this->session->data['coupon'])) {
+ $data['coupon'] = $this->session->data['coupon'];
+ } else {
+ $data['coupon'] = '';
+ }
+
+ return $this->load->view('extension/total/coupon', $data);
+ }
+ }
+
+ public function coupon() {
+ $this->load->language('extension/total/coupon');
+
+ $json = array();
+
+ $this->load->model('extension/total/coupon');
+
+ if (isset($this->request->post['coupon'])) {
+ $coupon = $this->request->post['coupon'];
+ } else {
+ $coupon = '';
+ }
+
+ $coupon_info = $this->model_extension_total_coupon->getCoupon($coupon);
+
+ if (empty($this->request->post['coupon'])) {
+ $json['error'] = $this->language->get('error_empty');
+
+ unset($this->session->data['coupon']);
+ } elseif ($coupon_info) {
+ $this->session->data['coupon'] = $this->request->post['coupon'];
+
+ $this->session->data['success'] = $this->language->get('text_success');
+
+ $json['redirect'] = $this->url->link('checkout/cart');
+ } else {
+ $json['error'] = $this->language->get('error_coupon');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+}
diff --git a/public/catalog/controller/extension/total/reward.php b/public/catalog/controller/extension/total/reward.php
new file mode 100644
index 0000000..6a3a010
--- /dev/null
+++ b/public/catalog/controller/extension/total/reward.php
@@ -0,0 +1,73 @@
+<?php
+class ControllerExtensionTotalReward extends Controller {
+ public function index() {
+ $points = $this->customer->getRewardPoints();
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ if ($points && $points_total && $this->config->get('total_reward_status')) {
+ $this->load->language('extension/total/reward');
+
+ $data['heading_title'] = sprintf($this->language->get('heading_title'), $points);
+
+ $data['entry_reward'] = sprintf($this->language->get('entry_reward'), $points_total);
+
+ if (isset($this->session->data['reward'])) {
+ $data['reward'] = $this->session->data['reward'];
+ } else {
+ $data['reward'] = '';
+ }
+
+ return $this->load->view('extension/total/reward', $data);
+ }
+ }
+
+ public function reward() {
+ $this->load->language('extension/total/reward');
+
+ $json = array();
+
+ $points = $this->customer->getRewardPoints();
+
+ $points_total = 0;
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['points']) {
+ $points_total += $product['points'];
+ }
+ }
+
+ if (empty($this->request->post['reward'])) {
+ $json['error'] = $this->language->get('error_reward');
+ }
+
+ if ($this->request->post['reward'] > $points) {
+ $json['error'] = sprintf($this->language->get('error_points'), $this->request->post['reward']);
+ }
+
+ if ($this->request->post['reward'] > $points_total) {
+ $json['error'] = sprintf($this->language->get('error_maximum'), $points_total);
+ }
+
+ if (!$json) {
+ $this->session->data['reward'] = abs($this->request->post['reward']);
+
+ $this->session->data['success'] = $this->language->get('text_success');
+
+ if (isset($this->request->post['redirect'])) {
+ $json['redirect'] = $this->url->link($this->request->post['redirect']);
+ } else {
+ $json['redirect'] = $this->url->link('checkout/cart');
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+}
diff --git a/public/catalog/controller/extension/total/shipping.php b/public/catalog/controller/extension/total/shipping.php
new file mode 100644
index 0000000..d4d67b6
--- /dev/null
+++ b/public/catalog/controller/extension/total/shipping.php
@@ -0,0 +1,211 @@
+<?php
+class ControllerExtensionTotalShipping extends Controller {
+ public function index() {
+ if ($this->config->get('total_shipping_status') && $this->config->get('total_shipping_estimator') && $this->cart->hasShipping()) {
+ $this->load->language('extension/total/shipping');
+
+ if (isset($this->session->data['shipping_address']['country_id'])) {
+ $data['country_id'] = $this->session->data['shipping_address']['country_id'];
+ } else {
+ $data['country_id'] = $this->config->get('config_country_id');
+ }
+
+ $this->load->model('localisation/country');
+
+ $data['countries'] = $this->model_localisation_country->getCountries();
+
+ if (isset($this->session->data['shipping_address']['zone_id'])) {
+ $data['zone_id'] = $this->session->data['shipping_address']['zone_id'];
+ } else {
+ $data['zone_id'] = '';
+ }
+
+ if (isset($this->session->data['shipping_address']['postcode'])) {
+ $data['postcode'] = $this->session->data['shipping_address']['postcode'];
+ } else {
+ $data['postcode'] = '';
+ }
+
+ if (isset($this->session->data['shipping_method'])) {
+ $data['shipping_method'] = $this->session->data['shipping_method']['code'];
+ } else {
+ $data['shipping_method'] = '';
+ }
+
+ return $this->load->view('extension/total/shipping', $data);
+ }
+ }
+
+ public function quote() {
+ $this->load->language('extension/total/shipping');
+
+ $json = array();
+
+ if (!$this->cart->hasProducts()) {
+ $json['error']['warning'] = $this->language->get('error_product');
+ }
+
+ if (!$this->cart->hasShipping()) {
+ $json['error']['warning'] = sprintf($this->language->get('error_no_shipping'), $this->url->link('information/contact'));
+ }
+
+ if ($this->request->post['country_id'] == '') {
+ $json['error']['country'] = $this->language->get('error_country');
+ }
+
+ if (!isset($this->request->post['zone_id']) || $this->request->post['zone_id'] == '') {
+ $json['error']['zone'] = $this->language->get('error_zone');
+ }
+
+ $this->load->model('localisation/country');
+
+ $country_info = $this->model_localisation_country->getCountry($this->request->post['country_id']);
+
+ if ($country_info && $country_info['postcode_required'] && (utf8_strlen(trim($this->request->post['postcode'])) < 2 || utf8_strlen(trim($this->request->post['postcode'])) > 10)) {
+ $json['error']['postcode'] = $this->language->get('error_postcode');
+ }
+
+ if (!$json) {
+ $this->tax->setShippingAddress($this->request->post['country_id'], $this->request->post['zone_id']);
+
+ if ($country_info) {
+ $country = $country_info['name'];
+ $iso_code_2 = $country_info['iso_code_2'];
+ $iso_code_3 = $country_info['iso_code_3'];
+ $address_format = $country_info['address_format'];
+ } else {
+ $country = '';
+ $iso_code_2 = '';
+ $iso_code_3 = '';
+ $address_format = '';
+ }
+
+ $this->load->model('localisation/zone');
+
+ $zone_info = $this->model_localisation_zone->getZone($this->request->post['zone_id']);
+
+ if ($zone_info) {
+ $zone = $zone_info['name'];
+ $zone_code = $zone_info['code'];
+ } else {
+ $zone = '';
+ $zone_code = '';
+ }
+
+ $this->session->data['shipping_address'] = array(
+ 'firstname' => '',
+ 'lastname' => '',
+ 'company' => '',
+ 'address_1' => '',
+ 'address_2' => '',
+ 'postcode' => $this->request->post['postcode'],
+ 'city' => '',
+ 'zone_id' => $this->request->post['zone_id'],
+ 'zone' => $zone,
+ 'zone_code' => $zone_code,
+ 'country_id' => $this->request->post['country_id'],
+ 'country' => $country,
+ 'iso_code_2' => $iso_code_2,
+ 'iso_code_3' => $iso_code_3,
+ 'address_format' => $address_format
+ );
+
+ $quote_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $quote_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($quote_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $quote_data);
+
+ $this->session->data['shipping_methods'] = $quote_data;
+
+ if ($this->session->data['shipping_methods']) {
+ $json['shipping_method'] = $this->session->data['shipping_methods'];
+ } else {
+ $json['error']['warning'] = sprintf($this->language->get('error_no_shipping'), $this->url->link('information/contact'));
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function shipping() {
+ $this->load->language('extension/total/shipping');
+
+ $json = array();
+
+ if (!empty($this->request->post['shipping_method'])) {
+ $shipping = explode('.', $this->request->post['shipping_method']);
+
+ if (!isset($shipping[0]) || !isset($shipping[1]) || !isset($this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]])) {
+ $json['warning'] = $this->language->get('error_shipping');
+ }
+ } else {
+ $json['warning'] = $this->language->get('error_shipping');
+ }
+
+ if (!$json) {
+ $shipping = explode('.', $this->request->post['shipping_method']);
+
+ $this->session->data['shipping_method'] = $this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]];
+
+ $this->session->data['success'] = $this->language->get('text_success');
+
+ $json['redirect'] = $this->url->link('checkout/cart');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function country() {
+ $json = array();
+
+ $this->load->model('localisation/country');
+
+ $country_info = $this->model_localisation_country->getCountry($this->request->get['country_id']);
+
+ if ($country_info) {
+ $this->load->model('localisation/zone');
+
+ $json = array(
+ 'country_id' => $country_info['country_id'],
+ 'name' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => $country_info['address_format'],
+ 'postcode_required' => $country_info['postcode_required'],
+ 'zone' => $this->model_localisation_zone->getZonesByCountryId($this->request->get['country_id']),
+ 'status' => $country_info['status']
+ );
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+} \ No newline at end of file
diff --git a/public/catalog/controller/extension/total/voucher.php b/public/catalog/controller/extension/total/voucher.php
new file mode 100644
index 0000000..0f7b1bc
--- /dev/null
+++ b/public/catalog/controller/extension/total/voucher.php
@@ -0,0 +1,103 @@
+<?php
+class ControllerExtensionTotalVoucher extends Controller {
+ public function index() {
+ if ($this->config->get('total_voucher_status')) {
+ $this->load->language('extension/total/voucher');
+
+ if (isset($this->session->data['voucher'])) {
+ $data['voucher'] = $this->session->data['voucher'];
+ } else {
+ $data['voucher'] = '';
+ }
+
+ return $this->load->view('extension/total/voucher', $data);
+ }
+ }
+
+ public function voucher() {
+ $this->load->language('extension/total/voucher');
+
+ $json = array();
+
+ $this->load->model('extension/total/voucher');
+
+ if (isset($this->request->post['voucher'])) {
+ $voucher = $this->request->post['voucher'];
+ } else {
+ $voucher = '';
+ }
+
+ $voucher_info = $this->model_extension_total_voucher->getVoucher($voucher);
+
+ if (empty($this->request->post['voucher'])) {
+ $json['error'] = $this->language->get('error_empty');
+ } elseif ($voucher_info) {
+ $this->session->data['voucher'] = $this->request->post['voucher'];
+
+ $this->session->data['success'] = $this->language->get('text_success');
+
+ $json['redirect'] = $this->url->link('checkout/cart');
+ } else {
+ $json['error'] = $this->language->get('error_voucher');
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function send($route, $args, $output) {
+ $this->load->model('checkout/order');
+
+ $order_info = $this->model_checkout_order->getOrder($args[0]);
+
+ // If order status in the complete range create any vouchers that where in the order need to be made available.
+ if (in_array($order_info['order_status_id'], $this->config->get('config_complete_status'))) {
+ $voucher_query = $this->db->query("SELECT *, vtd.name AS theme FROM `" . DB_PREFIX . "voucher` v LEFT JOIN " . DB_PREFIX . "voucher_theme vt ON (v.voucher_theme_id = vt.voucher_theme_id) LEFT JOIN " . DB_PREFIX . "voucher_theme_description vtd ON (vt.voucher_theme_id = vtd.voucher_theme_id) WHERE v.order_id = '" . (int)$order_info['order_id'] . "' AND vtd.language_id = '" . (int)$order_info['language_id'] . "'");
+
+ if ($voucher_query->num_rows) {
+ // Send out any gift voucher mails
+ $language = new Language($order_info['language_code']);
+ $language->load($order_info['language_code']);
+ $language->load('mail/voucher');
+
+ foreach ($voucher_query->rows as $voucher) {
+ // HTML Mail
+ $data = array();
+
+ $data['title'] = sprintf($language->get('text_subject'), $voucher['from_name']);
+
+ $data['text_greeting'] = sprintf($language->get('text_greeting'), $this->currency->format($voucher['amount'], $order_info['currency_code'], $order_info['currency_value']));
+ $data['text_from'] = sprintf($language->get('text_from'), $voucher['from_name']);
+ $data['text_message'] = $language->get('text_message');
+ $data['text_redeem'] = sprintf($language->get('text_redeem'), $voucher['code']);
+ $data['text_footer'] = $language->get('text_footer');
+
+ if (is_file(DIR_IMAGE . $voucher['image'])) {
+ $data['image'] = $this->config->get('config_url') . 'image/' . $voucher['image'];
+ } else {
+ $data['image'] = '';
+ }
+
+ $data['store_name'] = $order_info['store_name'];
+ $data['store_url'] = $order_info['store_url'];
+ $data['message'] = nl2br($voucher['message']);
+
+ $mail = new Mail($this->config->get('config_mail_engine'));
+ $mail->parameter = $this->config->get('config_mail_parameter');
+ $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
+ $mail->smtp_username = $this->config->get('config_mail_smtp_username');
+ $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
+ $mail->smtp_port = $this->config->get('config_mail_smtp_port');
+ $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
+
+ $mail->setTo($voucher['to_email']);
+ $mail->setFrom($this->config->get('config_email'));
+ $mail->setSender(html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'));
+ $mail->setSubject(html_entity_decode(sprintf($language->get('text_subject'), $voucher['from_name']), ENT_QUOTES, 'UTF-8'));
+ $mail->setHtml($this->load->view('mail/voucher', $data));
+ $mail->send();
+ }
+ }
+ }
+ }
+}