From 167ad6b467d26bc086ead078e3f49df521410be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= Date: Thu, 13 May 2021 16:12:43 +0200 Subject: [PATCH 1/8] backup commit --- clearpay.php | 7 + config.xml | 16 +- controllers/front/AbstractController.php | 1 + controllers/front/notify.php | 2 +- controllers/front/payment.php | 7 +- controllers/front/paymentEC.php | 402 +++++++++++++++++++++++ 6 files changed, 421 insertions(+), 14 deletions(-) create mode 100644 controllers/front/paymentEC.php diff --git a/clearpay.php b/clearpay.php index ea4d817..8045f0e 100644 --- a/clearpay.php +++ b/clearpay.php @@ -936,6 +936,13 @@ public function templateDisplay($templateName = '') __FILE__, 'views/templates/hook/' . $templateName ); + + $IsEcEnabled = true; + if ($IsEcEnabled) { + $uri = $this->context->link->getModuleLink('clearpay', 'paymentEC'); + $return .= "Express Checkout +"; + } } else { if ($isEnabled && $templateName === 'product.tpl' && Configuration::get('AFTERPAY_LOGS') === 'on') { $logMessage = ''; diff --git a/config.xml b/config.xml index 907dd8b..83798eb 100644 --- a/config.xml +++ b/config.xml @@ -1,12 +1,12 @@ - clearpay - - - - - - 1 - 1 + clearpay + + + + + + 1 + 1 \ No newline at end of file diff --git a/controllers/front/AbstractController.php b/controllers/front/AbstractController.php index 0905cce..c7fe617 100644 --- a/controllers/front/AbstractController.php +++ b/controllers/front/AbstractController.php @@ -47,6 +47,7 @@ public function redirect($url = '', $parameters = array()) */ public function saveLog($message, $severity = 1) { + die($message); try { if (is_array($message)) { $message = json_encode($message); diff --git a/controllers/front/notify.php b/controllers/front/notify.php index 5475cf0..c5326a1 100644 --- a/controllers/front/notify.php +++ b/controllers/front/notify.php @@ -326,7 +326,7 @@ private function getClearpayOrder() $getOrderRequest->send(); if ($getOrderRequest->getResponse()->getHttpStatusCode() >= 400) { - throw new \Exception($this->l('Unable to retrieve order from ') . self::PRODUCT_NAME . + throw new \Exception('Unable to retrieve order from ' . self::PRODUCT_NAME . ': ' . $this->clearpayOrderId); } $this->clearpayOrder = $getOrderRequest->getResponse()->getParsedBody(); diff --git a/controllers/front/payment.php b/controllers/front/payment.php index 0075a59..af44ddb 100644 --- a/controllers/front/payment.php +++ b/controllers/front/payment.php @@ -183,7 +183,6 @@ public function postProcess() $paymentObjData['currency'] ) ->setCourier(array( - 'shippedAt' => '', 'name' => $paymentObjData['carrier']->name . '', 'tracking' => '', 'priority' => 'STANDARD' @@ -250,11 +249,9 @@ public function postProcess() if (isset($clearpayPaymentObj->getResponse()->getParsedBody()->message)) { $errorMessage = $clearpayPaymentObj->getResponse()->getParsedBody()->message; } - $errorMessage .= $this->l('. Status code: ') - . $clearpayPaymentObj->getResponse()->getHttpStatusCode() - ; + $errorMessage .= '. Status code: ' . $clearpayPaymentObj->getResponse()->getHttpStatusCode(); $this->saveLog( - $this->l('Error received when trying to create a order: ') . + 'Error received when trying to create a order: ' . $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri(), 2 ); diff --git a/controllers/front/paymentEC.php b/controllers/front/paymentEC.php new file mode 100644 index 0000000..045ea5a --- /dev/null +++ b/controllers/front/paymentEC.php @@ -0,0 +1,402 @@ + + * @copyright 2020 Clearpay + * @license proprietary + */ + +use Afterpay\SDK\HTTP\Request\CreateCheckout; +use Afterpay\SDK\MerchantAccount as ClearpayMerchantAccount; + +require_once('AbstractController.php'); + +/** + * Class ClearpayPaymentECModuleFrontController + */ +class ClearpayPaymentECModuleFrontController extends AbstractController +{ + /** @var string $language */ + protected $language; + + /** + * Default API Version per region + * + * @var array + */ + public $defaultApiVersionPerRegion = array( + 'AU' => 'v2', + 'CA' => 'v2', + 'ES' => 'v1', + 'GB' => 'v2', + 'NZ' => 'v2', + 'US' => 'v2', + ); + + /** + * @param $region + * @return string + */ + public function getApiVersionPerRegion($region = '') + { + if (isset($this->defaultApiVersionPerRegion[$region])) { + return $this->defaultApiVersionPerRegion[$region]; + } + return json_encode(array($region)); + } + + /** + * @return mixed + * @throws \Afterpay\SDK\Exception\InvalidArgumentException + * @throws \Afterpay\SDK\Exception\NetworkException + * @throws \Afterpay\SDK\Exception\ParsingException + */ + public function postProcess() + { + $paymentObjData = array(); + $context = Context::getContext(); + $paymentObjData['currency'] = $context->currency->iso_code; + $paymentObjData['region'] = Configuration::get('CLEARPAY_REGION'); + + /** @var Cart $paymentObjData['cart'] */ + $paymentObjData['cart'] = $context->cart; + $paymentObjData['shippingAddress'] = new Address($paymentObjData['cart']->id_address_delivery); + $shippingCountryObj = new Country($paymentObjData['shippingAddress']->id_country); + $paymentObjData['shippingCountryCode'] = $shippingCountryObj->iso_code; + $shippingStateObj = new State($paymentObjData['shippingAddress']->id_state); + $paymentObjData['shippingStateCode'] = ''; + if (!empty($paymentObjData['shippingAddress']->id_state)) { + $paymentObjData['shippingStateCode'] = $shippingStateObj->iso_code; + } + $availableCarriers = $this->getAvailableCarriers(); + foreach ($availableCarriers as $key => $availableCarrier) { + $availableCarriers[$key]['shipping_cost'] = $context->cart->getOrderShippingCost($key); + } + var_dump("
", $availableCarriers);
+        die();
+        $paymentObjData['billingAddress'] = new Address($paymentObjData['cart']->id_address_invoice);
+        $paymentObjData['billingCountryCode'] = Country::getIsoById($paymentObjData['billingAddress']->id_country);
+        $billingStateObj = new State($paymentObjData['billingAddress']->id_state);
+        $paymentObjData['billingStateCode'] = '';
+        if (!empty($paymentObjData['billingAddress']->id_state)) {
+            $paymentObjData['billingStateCode'] = $billingStateObj->iso_code;
+        }
+        $paymentObjData['countryCode'] = $this->getCountryCode($paymentObjData);
+
+        $paymentObjData['discountAmount'] = $paymentObjData['cart']->getOrderTotal(true, Cart::ONLY_DISCOUNTS);
+
+        /** @var Carrier $paymentObjData['carrier'] */
+        $paymentObjData['carrier'] = new Carrier($paymentObjData['cart']->id_carrier);
+
+        /** @var Customer $paymentObjData['customer'] */
+        $paymentObjData['customer'] = $context->customer;
+
+        if (!$paymentObjData['cart']->id) {
+            Tools::redirect('index.php?controller=order');
+        }
+
+        $paymentObjData['urlToken'] = Tools::strtoupper(md5(uniqid(rand(), true)));
+
+        $paymentObjData['koUrl'] = $context->link->getPageLink(
+            'order',
+            null,
+            null,
+            array('step'=>3)
+        );
+        $paymentObjData['cancelUrl'] = (!empty(Configuration::get('CLEARPAY_URL_KO'))) ?
+            Configuration::get('CLEARPAY_URL_KO') : $paymentObjData['koUrl'];
+        $paymentObjData['publicKey'] = Configuration::get('CLEARPAY_PUBLIC_KEY');
+        $paymentObjData['secretKey'] = Configuration::get('CLEARPAY_SECRET_KEY');
+        $paymentObjData['environment'] = Configuration::get('CLEARPAY_ENVIRONMENT');
+
+        $query = array(
+            'id_cart' => $paymentObjData['cart']->id,
+            'key' => $paymentObjData['cart']->secure_key,
+        );
+        $paymentObjData['okUrl'] = _PS_BASE_URL_SSL_.__PS_BASE_URI__
+            .'index.php?canonical=true&fc=module&module=clearpay&controller=notify'
+            .'&token='.$paymentObjData['urlToken'] . '&' . http_build_query($query)
+        ;
+
+        $url = $paymentObjData['cancelUrl'];
+        try {
+            \Afterpay\SDK\Model::setAutomaticValidationEnabled(true);
+            $clearpayPaymentObj = new CreateCheckout();
+            $clearpayMerchantAccount = new ClearpayMerchantAccount();
+            $clearpayMerchantAccount
+                ->setMerchantId($paymentObjData['publicKey'])
+                ->setSecretKey($paymentObjData['secretKey'])
+                ->setApiEnvironment($paymentObjData['environment'])
+            ;
+            if (!is_null($paymentObjData['countryCode'])) {
+                $clearpayMerchantAccount->setCountryCode($paymentObjData['countryCode']);
+            }
+
+            $clearpayPaymentObj
+                ->setMerchant(array(
+                    'redirectConfirmUrl' => $paymentObjData['okUrl'],
+                    'redirectCancelUrl' => $paymentObjData['cancelUrl']
+                ))
+                ->setMerchantAccount($clearpayMerchantAccount)
+                ->setAmount(
+                    Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
+                    $paymentObjData['currency']
+                )
+                ->setTaxAmount(
+                    Clearpay::parseAmount(
+                        $paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)
+                        -
+                        $paymentObjData['cart']->getOrderTotal(false, Cart::BOTH)
+                    ),
+                    $paymentObjData['currency']
+                )
+                ->setConsumer(array(
+                    'phoneNumber' => $paymentObjData['billingAddress']->phone,
+                    'givenNames' => $paymentObjData['customer']->firstname,
+                    'surname' => $paymentObjData['customer']->lastname,
+                    'email' => $paymentObjData['customer']->email
+                ))
+                ->setBilling(array(
+                    'name' => $paymentObjData['billingAddress']->firstname . " " .
+                        $paymentObjData['billingAddress']->lastname,
+                    'line1' => $paymentObjData['billingAddress']->address1,
+                    'line2' => $paymentObjData['billingAddress']->address2,
+                    'suburb' => $paymentObjData['billingAddress']->city,
+                    'area1' => $paymentObjData['billingAddress']->city,
+                    'state' => $paymentObjData['billingStateCode'],
+                    'region' => $paymentObjData['billingStateCode'],
+                    'postcode' => $paymentObjData['billingAddress']->postcode,
+                    'countryCode' => $paymentObjData['billingCountryCode'],
+                    'phoneNumber' => $paymentObjData['billingAddress']->phone
+                ))
+                ->setShipping(array(
+                    'name' => $paymentObjData['shippingAddress']->firstname . " " .
+                        $paymentObjData['shippingAddress']->lastname,
+                    'line1' => $paymentObjData['shippingAddress']->address1,
+                    'line2' => $paymentObjData['shippingAddress']->address2,
+                    'suburb' => $paymentObjData['shippingAddress']->city,
+                    'area1' => $paymentObjData['shippingAddress']->city,
+                    'state' => $paymentObjData['shippingStateCode'],
+                    'region' => $paymentObjData['shippingStateCode'],
+                    'postcode' => $paymentObjData['shippingAddress']->postcode,
+                    'countryCode' => $paymentObjData['shippingCountryCode'],
+                    'phoneNumber' => $paymentObjData['shippingAddress']->phone
+                ))
+                ->setShippingAmount(
+                    Clearpay::parseAmount($paymentObjData['cart']->getTotalShippingCost()),
+                    $paymentObjData['currency']
+                )
+                ->setCourier(array(
+                    'shippedAt' => '',
+                    'name' => $paymentObjData['carrier']->name . '',
+                    'tracking' => '',
+                    'priority' => 'STANDARD'
+                ));
+
+            if (!empty($paymentObjData['discountAmount'])) {
+                $clearpayPaymentObj->setDiscounts(array(
+                    array(
+                        'displayName' => 'Shop discount',
+                        'amount' => array(
+                            Clearpay::parseAmount($paymentObjData['discountAmount']),
+                            $paymentObjData['currency']
+                        )
+                    )
+                ));
+            }
+
+            $items = $paymentObjData['cart']->getProducts();
+            $products = array();
+            foreach ($items as $item) {
+                $products[] = array(
+                    'name' => utf8_encode($item['name']),
+                    'sku' => $item['reference'],
+                    'quantity' => (int) $item['quantity'],
+                    'price' => array(
+                        'amount' => Clearpay::parseAmount($item['price_wt']),
+                        'currency' => $paymentObjData['currency']
+                    )
+                );
+            }
+            $clearpayPaymentObj->setItems($products);
+
+            $apiVersion = $this->getApiVersionPerRegion($paymentObjData['region']);
+            if ($apiVersion === 'v1') {
+                $clearpayPaymentObj = $this->addPaymentV1Options($clearpayPaymentObj, $paymentObjData);
+            } else {
+                $clearpayPaymentObj = $this->addPaymentV2Options($clearpayPaymentObj, $paymentObjData);
+            }
+
+            $header = $this->module->name . '/' . $this->module->version
+                . ' (Prestashop/' . _PS_VERSION_ . '; PHP/' . phpversion() . '; Merchant/' . $paymentObjData['publicKey']
+                . ') ' . _PS_BASE_URL_SSL_.__PS_BASE_URI__;
+            $clearpayPaymentObj->addHeader('User-Agent', $header);
+            $clearpayPaymentObj->addHeader('Country', $paymentObjData['countryCode']);
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
+            return Tools::redirect($url);
+        }
+
+        if (!$clearpayPaymentObj->isValid()) {
+            $this->saveLog($clearpayPaymentObj->getValidationErrors(), 2);
+            return Tools::redirect($url);
+        }
+
+        $endPoint = '/' . $apiVersion . '/';
+        $endPoint .= ($apiVersion === 'v2') ? "checkouts": "orders";
+        $clearpayPaymentObj->setUri($endPoint);
+
+        $clearpayPaymentObj->send();
+        $errorMessage = 'empty response';
+        if ($clearpayPaymentObj->getResponse()->getHttpStatusCode() >= 400
+            || isset($clearpayPaymentObj->getResponse()->getParsedBody()->errorCode)
+        ) {
+            if (isset($clearpayPaymentObj->getResponse()->getParsedBody()->message)) {
+                $errorMessage = $clearpayPaymentObj->getResponse()->getParsedBody()->message;
+            }
+            $errorMessage .= $this->l('. Status code: ')
+                . $clearpayPaymentObj->getResponse()->getHttpStatusCode()
+            ;
+            $this->saveLog(
+                $this->l('Error received when trying to create a order: ') .
+                $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri(),
+                2
+            );
+
+            return Tools::redirect($url);
+        }
+
+        try {
+            $url = $clearpayPaymentObj->getResponse()->getParsedBody()->redirectCheckoutUrl;
+            $orderId = $clearpayPaymentObj->getResponse()->getParsedBody()->token;
+            $cartId = pSQL($paymentObjData['cart']->id);
+            $orderId = pSQL($orderId);
+            $urlToken = pSQL($paymentObjData['urlToken']);
+            $countryCode = pSQL($paymentObjData['countryCode']);
+            $sql = "INSERT INTO `" . _DB_PREFIX_ . "clearpay_order` (`id`, `order_id`, `token`, `country_code`) 
+            VALUES ('$cartId','$orderId', '$urlToken', '$countryCode')";
+            $result = Db::getInstance()->execute($sql);
+            if (!$result) {
+                throw new \Exception('Unable to save clearpay-order-id in database: '. $sql);
+            }
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
+            $url = $paymentObjData['cancelUrl'];
+        }
+
+        return Tools::redirect($url);
+    }
+
+    /**
+     * @param CreateCheckout $clearpayPaymentObj
+     * @param array $paymentObjData
+     * @return CreateCheckout
+     */
+    private function addPaymentV1Options(CreateCheckout $clearpayPaymentObj, $paymentObjData)
+    {
+        $clearpayPaymentObj->setTotalAmount(
+            Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
+            $paymentObjData['currency']
+        );
+        return $clearpayPaymentObj;
+    }
+
+    /**
+     * @param CreateCheckout $clearpayPaymentObj
+     * @param array $paymentObjData
+     * @return CreateCheckout
+     */
+    private function addPaymentV2Options(CreateCheckout $clearpayPaymentObj, $paymentObjData)
+    {
+        $clearpayPaymentObj->setAmount(
+            Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
+            $paymentObjData['currency']
+        );
+        return $clearpayPaymentObj;
+    }
+
+    /**
+     * @param array $paymentObjData
+     * @return string|null
+     */
+    private function getCountryCode($paymentObjData)
+    {
+        $allowedCountries = json_decode(Configuration::get('CLEARPAY_ALLOWED_COUNTRIES'));
+        $lang = Language::getLanguage($this->context->language->id);
+        $langArray = explode("-", $lang['language_code']);
+        if (count($langArray) != 2 && isset($lang['locale'])) {
+            $langArray = explode("-", $lang['locale']);
+        }
+        $language = Tools::strtoupper($langArray[count($langArray)-1]);
+        // Prevent null language detection
+        if (in_array(Tools::strtoupper($language), $allowedCountries)) {
+            return $language;
+        }
+
+        $shippingAddress = new Address($paymentObjData['cart']->id_address_delivery);
+        if ($shippingAddress) {
+            $language = Country::getIsoById($paymentObjData['shippingAddress']->id_country);
+            if (in_array(Tools::strtoupper($language), $allowedCountries)) {
+                return $language;
+            }
+        }
+        $billingAddress = new Address($paymentObjData['cart']->id_address_invoice);
+        if ($billingAddress) {
+            $language = Country::getIsoById($paymentObjData['billingAddress']->id_country);
+            if (in_array(Tools::strtoupper($language), $allowedCountries)) {
+                return $language;
+            }
+        }
+        return null;
+    }
+
+    private function getAvailableCarriers()
+    {
+        $sql = 'SELECT mc.`id_reference`
+			FROM `'._DB_PREFIX_.'module_carrier` mc
+			WHERE mc.`id_module` = '. $this->module->id;
+        $moduleCarriers = Db::getInstance()->ExecuteS($sql);
+        $returnCarriers = array();
+        $allCarriers = Carrier::getCarriers($this->context->language->id, true);
+
+        foreach ($moduleCarriers as $key => $reference) {
+            foreach ($allCarriers as $carrier) {
+                if ($carrier['id_carrier'] == $reference['id_reference']) {
+                    $returnCarriers[$reference['id_reference']] = $carrier;
+                }
+            }
+        }
+        return $returnCarriers;
+    }
+
+    private function makeRequest()
+    {
+        $options = array(
+            CURLOPT_RETURNTRANSFER => true,     // return web page
+            CURLOPT_HEADER         => false,    // don't return headers
+            CURLOPT_FOLLOWLOCATION => true,     // follow redirects
+            CURLOPT_ENCODING       => "",       // handle all encodings
+            CURLOPT_USERAGENT      => "Prestashop", // who am i
+            CURLOPT_AUTOREFERER    => true,     // set referer on redirect
+            CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
+            CURLOPT_TIMEOUT        => 120,      // timeout on response
+            CURLOPT_MAXREDIRS      => 4,       // stop after 10 redirects
+            CURLOPT_SSL_VERIFYPEER => true     // Disabled SSL Cert checks
+        );
+
+        $url = 'https://api.eu-sandbox.afterpay.com/v2/checkouts';
+        $ch      = curl_init( $url );
+        curl_setopt_array( $ch, $options );
+        $content = curl_exec( $ch );
+        $err     = curl_errno( $ch );
+        $errmsg  = curl_error( $ch );
+        $header  = curl_getinfo( $ch );
+        curl_close( $ch );
+
+        $header['errno']   = $err;
+        $header['errmsg']  = $errmsg;
+        $header['content'] = $content;
+        return $header;
+    }
+}

From 6ffdeedbf23b44f2a08c716e474eeaa401a5cb01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= 
Date: Tue, 20 Jul 2021 17:04:46 +0200
Subject: [PATCH 2/8] EC

---
 clearpay.php                              |  59 +-
 controllers/front/AbstractController.php  |   1 -
 controllers/front/express.php             | 991 ++++++++++++++++++++++
 controllers/front/notify.php              |   2 +-
 controllers/front/payment.php             |  20 +-
 controllers/front/paymentEC.php           | 402 ---------
 views/templates/hook/express-checkout.tpl | 174 ++++
 7 files changed, 1232 insertions(+), 417 deletions(-)
 create mode 100644 controllers/front/express.php
 delete mode 100644 controllers/front/paymentEC.php
 create mode 100644 views/templates/hook/express-checkout.tpl

diff --git a/clearpay.php b/clearpay.php
index 8045f0e..16a6ab4 100644
--- a/clearpay.php
+++ b/clearpay.php
@@ -24,7 +24,7 @@ class Clearpay extends PaymentModule
     const PRODUCT_PAYMENT_NAME = "Clearpay";
 
     /**
-     * Available currency
+     * SIMULATOR_IS_ENABLED
      */
     const SIMULATOR_IS_ENABLED = true;
 
@@ -99,13 +99,13 @@ public function __construct()
     {
         $this->name = 'clearpay';
         $this->tab = 'payments_gateways';
-        $this->version = '1.1.1';
+        $this->version = '1.2.0';
         $this->author = $this->l('Clearpay');
         $this->currencies = true;
         $this->currencies_mode = 'checkbox';
         $this->module_key = '1da91d21c9c3427efd7530c2be29182d';
         $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);
-        $this->displayName = $this->l('Clearpay Payment Gateway');
+        $this->displayName = $this->l('Clearpay Payment Gateway with EC');
         $this->description = $this->l('Buy now, pay later. Always interest-free. Reach new customers, ') .
             $this->l('increase your conversion rate, recurrency and average order value ofering ') .
             $this->l('interest-free installments in your eCommerce.');
@@ -141,6 +141,7 @@ public function install()
         $this->loadSQLFile($sql_file);
 
         Configuration::updateValue('CLEARPAY_IS_ENABLED', 0);
+        Configuration::updateValue('CLEARPAY_IS_EC_ENABLED', 0);
         Configuration::updateValue('CLEARPAY_REGION', 'ES');
         Configuration::updateValue('CLEARPAY_PUBLIC_KEY', '');
         Configuration::updateValue('CLEARPAY_SECRET_KEY', '');
@@ -186,6 +187,7 @@ public function install()
     public function uninstall()
     {
         Configuration::deleteByName('CLEARPAY_IS_ENABLED');
+        Configuration::deleteByName('CLEARPAY_IS_EC_ENABLED');
         Configuration::deleteByName('CLEARPAY_PUBLIC_KEY');
         Configuration::deleteByName('CLEARPAY_SECRET_KEY');
         Configuration::deleteByName('CLEARPAY_PRODUCTION_SECRET_KEY');
@@ -291,6 +293,7 @@ public function hookHeader($params)
                 ' MId:'.Configuration::get('CLEARPAY_PUBLIC_KEY').
                 ' Region:'.Configuration::get('CLEARPAY_REGION').
                 ' Lang:'.$this->getCurrentLanguage().
+                ' EC Enabled:'.Configuration::get('CLEARPAY_IS_EC_ENABLED').
                 ' Enabled:'.Configuration::get('CLEARPAY_IS_ENABLED').
                 ' A_Countries:'.Configuration::get('CLEARPAY_ALLOWED_COUNTRIES').
                 ' R_Cat:'.(string)Configuration::get('CLEARPAY_RESTRICTED_CATEGORIES').
@@ -421,6 +424,26 @@ private function getConfigForm()
                 ),
             )
         );
+        $inputs[] = array(
+            'name' => 'CLEARPAY_IS_EC_ENABLED',
+            'type' =>  'switch',
+            'label' => $this->l('Express Checkout is enabled'),
+            'prefix' => '',
+            'class' => 't',
+            'required' => true,
+            'values'=> array(
+                array(
+                    'id' => 'CLEARPAY_IS_EC_ENABLED_TRUE',
+                    'value' => 1,
+                    'label' => $this->l('Yes', get_class($this), null, false),
+                ),
+                array(
+                    'id' => 'CLEARPAY_IS_EC_ENABLED_FALSE',
+                    'value' => 0,
+                    'label' => $this->l('No', get_class($this), null, false),
+                ),
+            )
+        );
         $query = array(
             array(
                 'CLEARPAY_REGION_id' => 'ES',
@@ -617,6 +640,7 @@ private function renderForm()
         $helper->fields_value['CLEARPAY_PUBLIC_KEY'] = Configuration::get('CLEARPAY_PUBLIC_KEY');
         $helper->fields_value['CLEARPAY_SECRET_KEY'] = Configuration::get('CLEARPAY_SECRET_KEY');
         $helper->fields_value['CLEARPAY_IS_ENABLED'] = Configuration::get('CLEARPAY_IS_ENABLED');
+        $helper->fields_value['CLEARPAY_IS_EC_ENABLED'] = Configuration::get('CLEARPAY_IS_EC_ENABLED');
         $helper->fields_value['CLEARPAY_ENVIRONMENT'] = Configuration::get('CLEARPAY_ENVIRONMENT');
         $helper->fields_value['CLEARPAY_REGION'] = Configuration::get('CLEARPAY_REGION');
         $helper->fields_value['CLEARPAY_MIN_AMOUNT'] = Configuration::get('CLEARPAY_MIN_AMOUNT');
@@ -639,6 +663,7 @@ public function getContent()
         $message = '';
         $settingsKeys = array();
         $settingsKeys[] = 'CLEARPAY_IS_ENABLED';
+        $settingsKeys[] = 'CLEARPAY_IS_EC_ENABLED';
         $settingsKeys[] = 'CLEARPAY_PUBLIC_KEY';
         $settingsKeys[] = 'CLEARPAY_SECRET_KEY';
         $settingsKeys[] = 'CLEARPAY_ENVIRONMENT';
@@ -861,6 +886,7 @@ public function hookPayment($params)
     public function templateDisplay($templateName = '')
     {
         $templateConfigs = array();
+        $IsEcEnabled = Configuration::get('CLEARPAY_IS_EC_ENABLED');
         if ($templateName === 'cart.tpl') {
             $amount = Clearpay::parseAmount($this->context->cart->getOrderTotal());
             $templateConfigs['AMOUNT'] =  Clearpay::parseAmount($this->context->cart->getOrderTotal()/4);
@@ -879,6 +905,7 @@ public function templateDisplay($templateName = '')
                 $templateConfigs['PRICE_SELECTOR'] = '.cart-total .value';
             }
         } else {
+            $IsEcEnabled = false;
             $productId = Tools::getValue('id_product');
             if (!$productId) {
                 return false;
@@ -898,7 +925,6 @@ public function templateDisplay($templateName = '')
         }
         $return = '';
         $isEnabled = Configuration::get('CLEARPAY_IS_ENABLED');
-
         $allowedCountries = json_decode(Configuration::get('CLEARPAY_ALLOWED_COUNTRIES'));
         $language = $this->getCurrentLanguage();
         if ($isEnabled &&
@@ -920,12 +946,16 @@ public function templateDisplay($templateName = '')
             } else {
                 $language = $language['language_code'];
             }
+            if($language == "en-US") {
+                $language = "en-GB";
+            }
             $templateConfigs['ISO_COUNTRY_CODE'] = str_replace('-', '_', $language);
             // Preserve Uppercase in locale
             if (Tools::strlen($templateConfigs['ISO_COUNTRY_CODE']) == 5) {
                 $templateConfigs['ISO_COUNTRY_CODE'] = Tools::substr($templateConfigs['ISO_COUNTRY_CODE'], 0, 2) .
                     Tools::strtoupper(Tools::substr($templateConfigs['ISO_COUNTRY_CODE'], 2, 4));
             }
+            $templateConfigs['COUNTRY'] = Tools::strtoupper(Tools::substr($templateConfigs['ISO_COUNTRY_CODE'], 3, 4));
             $templateConfigs['AMOUNT_WITH_CURRENCY'] = $templateConfigs['AMOUNT'] . $this->currencySymbol;
             if ($this->currency === 'GBP') {
                 $templateConfigs['AMOUNT_WITH_CURRENCY'] = $this->currencySymbol. $templateConfigs['AMOUNT'];
@@ -937,11 +967,21 @@ public function templateDisplay($templateName = '')
                 'views/templates/hook/' . $templateName
             );
 
-            $IsEcEnabled = true;
             if ($IsEcEnabled) {
-                $uri = $this->context->link->getModuleLink('clearpay', 'paymentEC');
-                $return .= "Express Checkout
-";
+                $merchantCart = new Cart($this->context->cart->id);
+                if (empty($merchantCart->secure_key)) {
+                    $merchantCart->secure_key = md5(uniqid(rand(), true));
+                    $merchantCart->save();
+                }
+                $params = array(
+                    'EXPRESS_CONTROLLER' => $this->context->link->getModuleLink('clearpay', 'express'),
+                    'SECURE_KEY' => $merchantCart->secure_key
+                );
+                $this->context->smarty->assign($params);
+                $return .= $this->display(
+                    __FILE__,
+                    'views/templates/hook/express-checkout.tpl'
+                );
             }
         } else {
             if ($isEnabled && $templateName === 'product.tpl' && Configuration::get('AFTERPAY_LOGS') === 'on') {
@@ -1278,6 +1318,9 @@ private function getCurrentLanguage()
                 return $language;
             }
         }
+        if ($language == 'US' || $language == 'EN') {
+            return "GB";
+        }
         return $language;
     }
 
diff --git a/controllers/front/AbstractController.php b/controllers/front/AbstractController.php
index c7fe617..0905cce 100644
--- a/controllers/front/AbstractController.php
+++ b/controllers/front/AbstractController.php
@@ -47,7 +47,6 @@ public function redirect($url = '', $parameters = array())
      */
     public function saveLog($message, $severity = 1)
     {
-        die($message);
         try {
             if (is_array($message)) {
                 $message = json_encode($message);
diff --git a/controllers/front/express.php b/controllers/front/express.php
new file mode 100644
index 0000000..a162e6d
--- /dev/null
+++ b/controllers/front/express.php
@@ -0,0 +1,991 @@
+
+ * @copyright 2020 Clearpay
+ * @license   proprietary
+ */
+
+use Afterpay\SDK\HTTP\Request as ClearpayRequest;
+use Afterpay\SDK\HTTP\Request\ImmediatePaymentCapture as ClearpayImmediatePaymentCaptureRequest;
+use Afterpay\SDK\MerchantAccount as ClearpayMerchant;
+use Afterpay\SDK\HTTP\Request\CreateCheckout;
+use PrestaShop\PrestaShop\Core\Crypto\Hashing;
+
+require_once('AbstractController.php');
+
+/**
+ * Class ClearpayExpressModuleFrontController
+ */
+class ClearpayExpressModuleFrontController extends AbstractController
+{
+    /** Product Name */
+    const PRODUCT_NAME = "Clearpay";
+
+    /** Cart tablename */
+    const CART_TABLE = 'clearpay_cart_process';
+
+    /** Clearpay orders tablename */
+    const ORDERS_TABLE = 'clearpay_order';
+
+    /**
+     * Seconds to expire a locked request
+     */
+    const CONCURRENCY_TIMEOUT = 1;
+
+    /**
+     * mismatch amount threshold in cents
+     */
+    const MISMATCH_AMOUNT_THRESHOLD = 1;
+
+    /**
+     * @var bool $mismatchError
+     */
+    protected $mismatchError = false;
+
+
+    /**
+     * @var bool $paymentDeclined
+     */
+    protected $paymentDeclined = false;
+
+    /**
+     * @var string $token
+     */
+    protected $token;
+
+    /**
+     * @var int $merchantOrderId
+     */
+    protected $merchantOrderId = null;
+
+    /**
+     * @var \Order $merchantOrder
+     */
+    protected $merchantOrder;
+
+    /**
+     * @var int $merchantCartId
+     */
+    protected $merchantCartId;
+
+    /**
+     * @var \Cart $merchantCart
+     */
+    protected $merchantCart;
+
+    /**
+     * @var string $clearpayOrderId
+     */
+    protected $clearpayOrderId;
+
+    /**
+     * @var string $clearpayCapturedPaymentId
+     */
+    protected $clearpayCapturedPaymentId;
+
+    /**
+     * @var ClearpayMerchant $clearpayMerchantAccount
+     */
+    protected $clearpayMerchantAccount;
+
+    /**
+     * @var Object $clearpayOrder
+     */
+    protected $clearpayOrder;
+
+    /**
+     * @var mixed $config
+     */
+    protected $config;
+    /**
+     * Default API Version per region
+     *
+     * @var array
+     */
+    public $defaultApiVersionPerRegion = array(
+        'AU' => 'v2',
+        'CA' => 'v2',
+        'ES' => 'v1',
+        'GB' => 'v2',
+        'NZ' => 'v2',
+        'US' => 'v2',
+    );
+
+    /**
+     * @var Object $jsonResponse
+     */
+    protected $jsonResponse;
+
+    /** @var string $language */
+    protected $language;
+
+    /**
+     * @param $func
+     * @param $params
+     * @return string
+     */
+    public function __call($func, $params)
+    {
+        if (in_array($func, array('l')) && !method_exists($this, $func)) {
+            return $params[0];
+        }
+    }
+
+    /**
+     * @return mixed
+     * @throws \Afterpay\SDK\Exception\InvalidArgumentException
+     * @throws \Afterpay\SDK\Exception\NetworkException
+     * @throws \Afterpay\SDK\Exception\ParsingException
+     */
+    public function postProcess()
+    {
+        if (Tools::getValue('action') === 'start_express_process') {
+            header('Content-type: application/json; charset=utf-8');
+            echo json_encode($this->createClearpayOrder());
+            exit;
+        }
+
+        if (Tools::getValue('action') === 'get_shipping_methods') {
+            header('Content-type: application/json; charset=utf-8');
+            echo json_encode($this->getShippingMethods());
+            exit;
+        }
+        if (Tools::getValue('action') === 'complete_order') {
+            // use shippingOptionIdentifier order field to set the carrier
+            $this->captureClearpayOrder();
+        }
+    }
+
+    /**
+     *
+     */
+    protected function createClearpayOrder()
+    {
+        try {
+            $context = Context::getContext();
+            $publicKey = Configuration::get('CLEARPAY_PUBLIC_KEY');
+            $cart = $context->cart;
+            $discountAmount = $cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS);
+            $cartUrl = $context->link->getPageLink(
+                'cart',
+                null,
+                null,
+                array('action' => 'show')
+            );
+            $countryCode = null;
+            $allowedCountries = json_decode(Configuration::get('CLEARPAY_ALLOWED_COUNTRIES'));
+            $lang = Language::getLanguage($context->language->id);
+
+            $langArray = explode("-", $lang['language_code']);
+            if (count($langArray) != 2 && isset($lang['locale'])) {
+                $langArray = explode("-", $lang['locale']);
+            }
+            $language = Tools::strtoupper($langArray[count($langArray)-1]);
+            if($language == "US") {
+                $language = "GB";
+            }
+            // Prevent null language detection
+            if (in_array(Tools::strtoupper($language), $allowedCountries)) {
+                $countryCode = $language;
+            }
+
+            \Afterpay\SDK\Model::setAutomaticValidationEnabled(true);
+            $clearpayPaymentObj = new CreateCheckout();
+            $clearpayMerchantAccount = new ClearpayMerchant();
+            $clearpayMerchantAccount
+                ->setMerchantId($publicKey)
+                ->setSecretKey( Configuration::get('CLEARPAY_SECRET_KEY'))
+                ->setApiEnvironment(Configuration::get('CLEARPAY_ENVIRONMENT'))
+            ;
+            if (!is_null($countryCode)) {
+                $clearpayMerchantAccount->setCountryCode($countryCode);
+            }
+
+            $clearpayPaymentObj
+                ->setMode('express')
+                ->setMerchant(array(
+                    'popupOriginUrl' => $cartUrl
+                ))
+                ->setMerchantAccount($clearpayMerchantAccount)
+                ->setTaxAmount(
+                    Clearpay::parseAmount(
+                        $cart->getOrderTotal(true, Cart::BOTH)
+                        -
+                        $cart->getOrderTotal(false, Cart::BOTH)
+                    ),
+                    $context->currency->iso_code
+                );
+
+            if (!empty($discountAmount)) {
+                $clearpayPaymentObj->setDiscounts(array(
+                    array(
+                        'displayName' => 'Shop discount',
+                        'amount' => array(
+                            Clearpay::parseAmount($discountAmount),
+                            $context->currency->iso_code
+                        )
+                    )
+                ));
+            }
+
+            $items = $cart->getProducts();
+            $products = array();
+            foreach ($items as $item) {
+                $products[] = array(
+                    'name' => utf8_encode($item['name']),
+                    'sku' => $item['reference'],
+                    'quantity' => (int) $item['quantity'],
+                    'price' => array(
+                        'amount' => Clearpay::parseAmount($item['price_wt']),
+                        'currency' => $context->currency->iso_code
+                    )
+                );
+            }
+            $clearpayPaymentObj->setItems($products);
+
+            $apiVersion = $this->getApiVersionPerRegion(Configuration::get('CLEARPAY_REGION'));
+            if ($apiVersion === 'v1') {
+                $clearpayPaymentObj->setTotalAmount(
+                    Clearpay::parseAmount($cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING)),
+                    $context->currency->iso_code
+                );
+            } else {
+                $clearpayPaymentObj->setAmount(
+                    Clearpay::parseAmount($cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING)),
+                    $context->currency->iso_code
+                );
+            }
+
+            $header = $this->module->name . '/' . $this->module->version
+                . ' (Prestashop/' . _PS_VERSION_ . '; PHP/' . phpversion() . '; Merchant/' . $publicKey
+                . ') ' . _PS_BASE_URL_SSL_.__PS_BASE_URI__;
+            $clearpayPaymentObj->addHeader('User-Agent', $header);
+            $clearpayPaymentObj->addHeader('Country', $countryCode);
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
+                return array(
+                    'success'  => false,
+                    'message'  => $exception->getMessage(),
+                    'redirect' => $cartUrl
+                );
+        }
+
+        if (!$clearpayPaymentObj->isValid()) {
+
+            $this->saveLog($clearpayPaymentObj->getValidationErrors(), 2);
+            return array(
+                'success'  => false,
+                'message'  => $clearpayPaymentObj->getValidationErrors(),
+                'redirect' => $cartUrl
+            );
+        }
+
+        $endPoint = '/' . $apiVersion . '/';
+        $endPoint .= ($apiVersion === 'v2') ? "checkouts": "orders";
+        $clearpayPaymentObj->setUri($endPoint);
+
+        $clearpayPaymentObj->send();
+        $errorMessage = 'empty response';
+        if ($clearpayPaymentObj->getResponse()->getHttpStatusCode() >= 400
+            || isset($clearpayPaymentObj->getResponse()->getParsedBody()->errorCode)
+        ) {
+            if (isset($clearpayPaymentObj->getResponse()->getParsedBody()->message)) {
+                $errorMessage = $clearpayPaymentObj->getResponse()->getParsedBody()->message;
+            }
+            $errorMessage .= '. Status code: ' . $clearpayPaymentObj->getResponse()->getHttpStatusCode();
+            $logMessage = 'Error received when trying to create a order: ' .
+                $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri();
+            $this->saveLog(
+                $logMessage,
+                2
+            );
+
+            return array(
+                'success'  => false,
+                'message'  => $logMessage,
+                'redirect' => $cartUrl
+            );
+        }
+
+        try {
+            $orderId = $clearpayPaymentObj->getResponse()->getParsedBody()->token;
+            $cartId = pSQL($cart->id);
+            $orderId = pSQL($orderId);
+            $urlToken = Tools::strtoupper(md5(uniqid(rand(), true)));
+            $countryCode = pSQL($countryCode);
+            $sql = "INSERT INTO `" . _DB_PREFIX_ . "clearpay_order` (`id`, `order_id`, `token`, `country_code`) 
+            VALUES ('$cartId','$orderId', '$urlToken', '$countryCode')";
+            $result = Db::getInstance()->execute($sql);
+            if (!$result) {
+                throw new \Exception('Unable to save clearpay-order-id in database: '. $sql);
+            }
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
+            return array(
+                'success'  => false,
+                'message'  => $exception->getMessage(),
+                'redirect' => $cartUrl
+            );
+        }
+
+        return array(
+            'success' => true,
+            'token'  => $orderId,
+            'urlToken' => $urlToken,
+        );
+    }
+
+    /**
+     * @param $methodId
+     * @return array
+     */
+    protected function getShippingMethods($methodId = null)
+    {
+        $context = Context::getContext();
+        $availableCarriers = $this->getAvailableCarriers();
+        $shippingMethods = array();
+        foreach ($availableCarriers as $key => $availableCarrier) {
+            $availableCarriers[$key]['shipping_cost'] = $context->cart->getOrderShippingCost($key);
+            $currentMethod = array(
+                "id" => $availableCarriers[$key]['id_carrier'],
+                "name" => $availableCarriers[$key]['name'],
+                "description" => $availableCarriers[$key]['delay'],
+                "shippingAmount" => array(
+                    "amount" => (string) $context->cart->getOrderShippingCost($key),
+                    "currency" => $context->currency->iso_code
+                ),
+                "orderAmount" => array(
+                    "amount" => (string) ($this->context->cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING) +
+                        $context->cart->getOrderShippingCost($key)),
+                    "currency" => $context->currency->iso_code
+                )
+            );
+            if (!empty($methodId) && $methodId == $availableCarriers[$key]['id_carrier']) {
+                return $currentMethod;
+            }
+            $shippingMethods[] = $currentMethod;
+        }
+
+        return $shippingMethods;
+    }
+
+    /**
+     * @return array
+     */
+    private function getAvailableCarriers()
+    {
+        $sql = 'SELECT mc.`id_reference`
+			FROM `'._DB_PREFIX_.'module_carrier` mc
+			WHERE mc.`id_module` = '. $this->module->id;
+        $moduleCarriers = Db::getInstance()->ExecuteS($sql);
+        $returnCarriers = array();
+        $allCarriers = Carrier::getCarriers($this->context->language->id, true);
+
+        foreach ($moduleCarriers as $key => $reference) {
+            foreach ($allCarriers as $carrier) {
+                if ($carrier['id_carrier'] == $reference['id_reference']) {
+                    $returnCarriers[$reference['id_reference']] = $carrier;
+                }
+            }
+        }
+        return $returnCarriers;
+    }
+
+    /**
+     *
+     */
+    private function captureClearpayOrder ()
+    {
+        // Validations
+        try {
+            $this->prepareVariables();
+            if (!empty($this->merchantOrderId)) {
+                header('Content-type: application/json; charset=utf-8');
+                echo json_encode(array(
+                    'success'  => true,
+                    'url'  => $this->getReturnUrl(false),
+                ));
+                exit;
+            }
+            $this->checkConcurrency();
+            $this->getMerchantCart();
+            $this->getClearpayOrderId();
+            $this->getClearpayOrder();
+            $this->validateAmount();
+            $this->checkMerchantOrderStatus();
+        } catch (\Exception $exception) {
+            header('Content-type: application/json; charset=utf-8');
+            echo json_encode(array(
+                'success'  => false,
+                'message'  => $exception->getMessage(),
+                'url'  => $this->getReturnUrl(true),
+            ));
+            exit;
+        }
+
+        // Process Clearpay Order
+        try {
+            //$this->captureClearpayPayment();
+            $this->clearpayCapturedPaymentId = "55443322";
+        } catch (\Exception $exception) {
+            header('Content-type: application/json; charset=utf-8');
+            echo json_encode(array(
+                'success'  => false,
+                'message'  => $exception->getMessage(),
+                'url'  => $this->getReturnUrl(true),
+            ));
+            exit;
+        }
+
+        // Process Merchant Order
+        $this->processMerchantOrder();
+        try {
+        } catch (\Exception $exception) {
+            $this->rollbackMerchantOrder();
+            header('Content-type: application/json; charset=utf-8');
+            echo json_encode(array(
+                'success'  => false,
+                'message'  => $exception->getMessage(),
+                'url'  => $this->getReturnUrl(true),
+            ));
+            exit;
+        }
+
+        try {
+            $this->unblockConcurrency($this->merchantCartId);
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
+        }
+        //all goes well
+        header('Content-type: application/json; charset=utf-8');
+        echo json_encode(array(
+            'success'  => true,
+            'url'  => $this->getReturnUrl(false),
+        ));
+        exit;
+    }
+
+    /**
+     * @param $region
+     * @return string
+     */
+    public function getApiVersionPerRegion($region = '')
+    {
+        if (isset($this->defaultApiVersionPerRegion[$region])) {
+            return $this->defaultApiVersionPerRegion[$region];
+        }
+        return json_encode(array($region));
+    }
+
+    /**
+     * Check the concurrency of the purchase
+     *
+     * @throws Exception
+     */
+    public function checkConcurrency()
+    {
+        $this->unblockConcurrency();
+        $this->blockConcurrency($this->merchantCartId);
+    }
+
+    /**
+     * Find and init variables needed to process payment
+     *
+     * @throws Exception
+     */
+    public function prepareVariables()
+    {
+        $this->token = Tools::getValue('urlToken');
+        $this->merchantCartId = $this->context->cart->id;
+
+        if ($this->merchantCartId == '') {
+            throw new \Exception("Merchant cart id not provided in callback url");
+        }
+
+        $callbackOkUrl = $this->context->link->getPageLink('order-confirmation', null, null);
+
+        $this->config = array(
+            'urlOK' => $callbackOkUrl,
+            'secureKey' => Tools::getValue('key'),
+        );
+
+        $this->config['publicKey'] = Configuration::get('CLEARPAY_PUBLIC_KEY');
+        $this->config['privateKey'] = Configuration::get('CLEARPAY_SECRET_KEY');
+        $this->config['environment'] = Configuration::get('CLEARPAY_ENVIRONMENT');
+        $this->config['region'] = Configuration::get('CLEARPAY_REGION');
+        $this->config['apiVersion'] = $this->getApiVersionPerRegion($this->config['region']);
+
+        $this->merchantOrderId = $this->getMerchantOrderId();
+
+        $countryCode = $this->getClearpayOrderCountryCode();
+        $this->clearpayMerchantAccount = new ClearpayMerchant();
+        $this->clearpayMerchantAccount
+            ->setMerchantId($this->config['publicKey'])
+            ->setSecretKey($this->config['privateKey'])
+            ->setApiEnvironment($this->config['environment'])
+        ;
+        if (!is_null($countryCode)) {
+            $this->clearpayMerchantAccount->setCountryCode($countryCode);
+        }
+
+        if (!($this->config['secureKey'] && Module::isEnabled(self::CODE))) {
+            // This exception is only for Prestashop
+            throw new \Exception('Can\'t process ' . self::PRODUCT_NAME . ' order, module may not be enabled');
+        }
+    }
+
+    /**
+     * Find prestashop Cart Id
+     */
+    public function getMerchantOrderId()
+    {
+        $table = _DB_PREFIX_.self::ORDERS_TABLE;
+        $merchantCartId = (int)$this->merchantCartId;
+        $token = pSQL($this->token);
+        $sql = "select ps_order_id from `{$table}` where id = {$merchantCartId}
+         and token = '{$token}'";
+
+        return Db::getInstance()->getValue($sql);
+    }
+
+    /**
+     * Retrieve the merchant order by id
+     *
+     * @throws Exception
+     */
+    public function getMerchantCart()
+    {
+        try {
+            $this->merchantCart = new Cart($this->merchantCartId);
+            if (!Validate::isLoadedObject($this->merchantCart)) {
+                // This exception is only for Prestashop
+                throw new \Exception('Unable to load cart');
+            }
+            if ($this->merchantCart->secure_key != $this->config['secureKey']) {
+                throw new \Exception('Secure Key is not valid');
+            }
+        } catch (\Exception $exception) {
+            throw new \Exception('Unable to find cart with id' . $this->merchantCartId);
+        }
+    }
+
+    /**
+     * Find Clearpay Order Id
+     *
+     * @throws Exception
+     */
+    private function getClearpayOrderId()
+    {
+        $token = pSQL($this->token);
+        $sql = "select order_id from `" . _DB_PREFIX_ . "clearpay_order` where id = "
+            .(int)$this->merchantCartId . " and token = '" . $token . "'";
+        $this->clearpayOrderId = Db::getInstance()->getValue($sql);
+
+        if (empty($this->clearpayOrderId)) {
+            throw new \Exception(self::PRODUCT_NAME . ' order id not found on clearpay_orders table');
+        }
+    }
+
+    /**
+     * Find Clearpay country code
+     *
+     * @throws Exception
+     */
+    private function getClearpayOrderCountryCode()
+    {
+        $token = pSQL($this->token);
+        $sql = "select country_code from `" . _DB_PREFIX_ . "clearpay_order` where id = "
+            .(int)$this->merchantCartId . " and token = '" . $token . "'";
+        return Db::getInstance()->getValue($sql);
+    }
+
+    /**
+     * Find Clearpay Order in Orders Server using Clearpay SDK
+     *
+     * @throws Exception
+     */
+    private function getClearpayOrder()
+    {
+        $getOrderRequest = new ClearpayRequest();
+        $uri = '/' . $this->config['apiVersion'] . '/';
+        $uri .= ($this->config['apiVersion'] === 'v1') ? 'orders/' : 'checkouts/';
+        $getOrderRequest
+            ->setMerchantAccount($this->clearpayMerchantAccount)
+            ->setUri($uri . $this->clearpayOrderId)
+        ;
+        $getOrderRequest->send();
+
+        if ($getOrderRequest->getResponse()->getHttpStatusCode() >= 400) {
+            throw new \Exception('Unable to retrieve order from ' . self::PRODUCT_NAME .
+                ': ' . $this->clearpayOrderId);
+        }
+        $this->clearpayOrder = $getOrderRequest->getResponse()->getParsedBody();
+    }
+
+    /**
+     * Check that the merchant order and the order in Clearpay have the same amount to prevent hacking
+     *
+     * @throws Exception
+     */
+    public function validateAmount()
+    {
+        if ($this->config['apiVersion'] === 'v1') {
+            $cpAmount = $this->clearpayOrder->totalAmount->amount;
+        } else {
+            $cpAmount = $this->clearpayOrder->amount->amount;
+        }
+        $totalAmount = (string) $cpAmount;
+        $merchantAmount = (string) ($this->merchantCart->getOrderTotal(true, Cart::BOTH));
+        if ($totalAmount != $merchantAmount) {
+            $numberClearpayAmount = (integer) (100 * $cpAmount);
+            $ClearpayShippingOption = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
+            $numberMerchantAmount = (integer) (100 * $this->merchantCart->getOrderTotal(true, Cart::BOTH)) +
+                (integer) (100 * $ClearpayShippingOption['shippingAmount']['amount']);
+            $amountDff =  $numberMerchantAmount - $numberClearpayAmount;
+            if (abs($amountDff) > self::MISMATCH_AMOUNT_THRESHOLD) {
+                $this->mismatchError = true;
+                $amountMismatchError = 'Amount mismatch in PrestaShop Cart #'. $this->merchantCartId .
+                    ' compared with ' . self::PRODUCT_NAME . ' Order: ' . $this->clearpayOrderId .
+                    '. The Cart in PrestaShop has an amount of: ' . $merchantAmount . ' and in ' . self::PRODUCT_NAME .
+                    ' of: ' . $totalAmount;
+
+                $this->saveLog($amountMismatchError, 3);
+                throw new \Exception($amountMismatchError);
+            }
+        }
+    }
+
+    /**
+     * Check that the merchant order was not previously processes and is ready to be paid
+     *
+     * @throws Exception
+     */
+    public function checkMerchantOrderStatus()
+    {
+        try {
+            if ($this->merchantCart->orderExists() !== false) {
+                throw new \Exception('The cart ' . $this->merchantCartId . ' is already an order, unable to
+                create it');
+            }
+
+            // Double check
+            $tableName = _DB_PREFIX_ . self::ORDERS_TABLE;
+            $fieldName = 'ps_order_id';
+            $token = pSQL($this->token);
+            $clearpayOrderId = pSQL($this->clearpayOrderId);
+            $sql = ('select ' . $fieldName . ' from `' . $tableName . '` where `id` = ' . (int)$this->merchantCartId
+                . ' and `order_id` = \'' . $clearpayOrderId . '\''
+                . ' and `token` = \'' . $token . '\''
+                . ' and `' . $fieldName . '` is not null');
+            $results = Db::getInstance()->ExecuteS($sql);
+            if (is_array($results) && count($results) === 1) {
+                $exceptionMessage = sprintf(
+                    "Order was already created [cartId=%s][Token=%s][" . self::PRODUCT_NAME . "=%s]",
+                    $this->merchantCartId,
+                    $this->token,
+                    $this->clearpayOrderId
+                );
+                throw new \Exception($exceptionMessage);
+            }
+        } catch (\Exception $exception) {
+            throw new \Exception($exception->getMessage());
+        }
+        return true;
+    }
+
+    /**
+     * Confirm the order in Clearpay
+     *
+     * @throws Exception
+     */
+    private function captureClearpayPayment()
+    {
+        $ClearpayShippingOption = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
+        $numberMerchantAmount =  $this->merchantCart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING) +
+            $ClearpayShippingOption['shippingAmount']['amount'];
+        $context = Context::getContext();
+        $immediatePaymentCaptureRequest = new ClearpayImmediatePaymentCaptureRequest(array(
+            'token' => $this->clearpayOrder->token,
+            'amount' => array(
+                'amount' => $numberMerchantAmount,
+                'currency' => $context->currency->iso_code
+            )
+        ));
+        $immediatePaymentCaptureRequest->setMerchantAccount($this->clearpayMerchantAccount);
+        $uri = '/' . $this->config['apiVersion'] . '/payments/capture/';
+        $immediatePaymentCaptureRequest->setUri($uri);
+        $immediatePaymentCaptureRequest->send();
+        if ($immediatePaymentCaptureRequest->getResponse()->getHttpStatusCode() >= 400) {
+            $this->paymentDeclined = true;
+            throw new \Exception(
+                self::PRODUCT_NAME . ' capture payment error, order token: ' . $this->token . '. ' .
+                $immediatePaymentCaptureRequest->getResponse()->getParsedBody()->errorCode
+            );
+        }
+        $this->clearpayCapturedPaymentId = $immediatePaymentCaptureRequest->getResponse()->getParsedBody()->id;
+        if (!$immediatePaymentCaptureRequest->getResponse()->isApproved()) {
+            $this->paymentDeclined = true;
+            throw new \Exception(
+                self::PRODUCT_NAME . ' capture payment error, the payment was not processed successfully'
+            );
+        }
+    }
+
+    /**
+     * Process the merchant order and notify client
+     *
+     * @throws Exception
+     */
+    public function processMerchantOrder()
+    {
+        if ($this->config['apiVersion'] === 'v1') {
+            $cpAmount = $this->clearpayOrder->totalAmount->amount;
+        } else {
+            $cpAmount = $this->clearpayOrder->amount->amount;
+        }
+
+        //creating the addresses objects
+        $billingAddress = new Address();
+        $cpAddress = $this->clearpayOrder->shipping;
+        $city = '';
+        if (isset($cpAddress->area1)) {
+            $city = $cpAddress->area1;
+        } elseif (isset($cpAddress->suburb)) {
+            $city = $cpAddress->suburb;
+        }
+        $fullName = explode(' ', $cpAddress->name, 2);
+        $country = null;
+        if (isset($cpAddress->countryCode)) {
+            $country = Country::getByIso(substr($cpAddress->countryCode, 0, 3));
+        }
+        if (empty($country)) {
+            $country = Country::getByIso($this->context->language->iso_code);
+        }
+        $billingAddress->firstname = (isset($fullName[0])) ? $fullName[0] : '';
+        $billingAddress->lastname = (isset($fullName[1])) ? $fullName[1] : '';
+        $billingAddress->address1 = (isset($cpAddress->line1)) ? $cpAddress->line1 : '';
+        $billingAddress->address2 = (isset($cpAddress->line2)) ? $cpAddress->line2 : '';
+        $billingAddress->city = $city;
+        $billingAddress->other = (isset($cpAddress->region)) ? $cpAddress->region : '';
+        $billingAddress->iso_code = $this->context->language->id;
+        $billingAddress->id_country = $country;
+        $billingAddress->postcode = (isset($cpAddress->postcode)) ? $cpAddress->postcode : '';
+        $billingAddress->phone = (isset($cpAddress->phoneNumber)) ? $cpAddress->phoneNumber : '';
+        $billingAddress->alias = 'ClearpayExpress:'.$this->merchantCartId;
+        $billingAddress->save();
+        $this->merchantCart->updateAddressId(0, $billingAddress->id);
+        $this->merchantCart->updateDeliveryAddressId(0, $billingAddress->id);
+        $this->merchantCart->update();
+        $this->merchantCart->save();
+
+        // Creating the customer and guest objects
+        $cpConsumer = $this->clearpayOrder->consumer;
+        $customer = new Customer();
+        $customer->firstname = $cpConsumer->givenNames;
+        $customer->lastname = $cpConsumer->surname;
+        $customer->email = $cpConsumer->email;
+        $customer->passwd = md5(uniqid(rand(), true));
+        $customer->save();
+
+        $guest = new Guest();
+        $guest->userAgent();
+        $guest->id_customer = $customer->id;
+        $guest->save();
+
+        //set the customer and the guest ids into the cart
+        $this->merchantCart->id_customer = $customer->id;
+        $this->merchantCart->id_guest = $guest->id;
+        //set the delivery method id into the cart
+        $this->merchantCart->id_carrier = $this->clearpayOrder->shippingOptionIdentifier;
+        $delivery_option = $this->merchantCart->getDeliveryOption();
+        if (isset($delivery_option[0])) {
+            unset($delivery_option[0]);
+        }
+        $delivery_option[$this->merchantCart->id_address_delivery] =
+            (string)$this->clearpayOrder->shippingOptionIdentifier.',';
+        $this->merchantCart->setDeliveryOption($delivery_option);
+        //var_dump("
", $delivery_option);die;
+        $this->merchantCart->save();
+
+        $validateOrder = $this->module->validateOrder(
+            $this->merchantCartId,
+            Configuration::get('PS_OS_PAYMENT'),
+            $cpAmount,
+            self::PRODUCT_NAME,
+            'clearpayOrderId: ' .  $this->clearpayCapturedPaymentId,
+            array('transaction_id' => $this->clearpayCapturedPaymentId),
+            null,
+            false,
+            $this->config['secureKey']
+        );
+
+        $orderId = Order::getIdByCartId($this->merchantCartId);
+        $order = new Order($orderId);
+        $taxRate = (100 * $order->total_paid_tax_excl) / $cpAmount;
+        $total_paid_tax_excl = round((($cpAmount * $taxRate) / 100), 2);
+        $order->total_paid = $cpAmount;
+        $order->total_paid_tax_incl = $cpAmount;
+        $order->total_paid_tax_excl = $total_paid_tax_excl;
+
+        //Update cart carrier amounts
+        $shippingTotalAmount = 0;
+        $shippingMethod = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
+        if (!empty($shippingMethod)) {
+            $shippingTotalAmount = $shippingMethod->shippingAmount->amount;
+        }
+        $order->total_shipping = $shippingTotalAmount;
+        $order->total_shipping_tax_incl = $shippingTotalAmount;
+        $order->total_shipping_tax_excl = round((($shippingTotalAmount * $taxRate) / 100), 2);
+
+        $this->updateClearpayOrder();
+
+        try {
+            $token = pSQL($this->token);
+            $clearpayOrderId = pSQL($this->clearpayOrderId);
+            Db::getInstance()->update(
+                self::ORDERS_TABLE,
+                array('ps_order_id' => $this->module->currentOrder),
+                'id = '. (int)$this->merchantCartId
+                . ' and order_id = \'' . $clearpayOrderId . '\''
+                . ' and token = \'' . $token . '\''
+            );
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 2);
+        }
+
+        $message = self::PRODUCT_NAME . ' Order CONFIRMED' .
+            '. ' . self::PRODUCT_NAME . ' OrderId=' .  $this->clearpayCapturedPaymentId .
+            '. Prestashop OrderId=' . $this->module->currentOrder;
+        $this->saveLog($message, 1);
+    }
+
+    /**
+     * @throws Exception
+     */
+    private function updateClearpayOrder()
+    {
+        try {
+            if ($this->config['region'] === 'ES') { //ONLY AVAILABLE FOR EUROPE
+                $getOrderRequest = new ClearpayRequest();
+                $getOrderRequest
+                    ->setMerchantAccount($this->clearpayMerchantAccount)
+                    ->setUri("/v1/payments/".$this->clearpayCapturedPaymentId)
+                    ->setHttpMethod('PUT')
+                    ->setRequestBody(json_encode(array("merchantReference" => $this->module->currentOrder)));
+                $getOrderRequest->send();
+                if ($getOrderRequest->getResponse()->getHttpStatusCode() >= 400) {
+                    throw new \Exception('Unable to retrieve order from ' . self::PRODUCT_NAME .
+                        ' = ' . $this->clearpayOrderId);
+                }
+
+                $this->clearpayOrder = $getOrderRequest->getResponse()->getParsedBody();
+            }
+        } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 2);
+        }
+    }
+
+    /**
+     * Leave the merchant order as it was previously
+     *
+     * @throws Exception
+     */
+    public function rollbackMerchantOrder()
+    {
+        try {
+            $message = self::PRODUCT_NAME . ' Roolback method called: ' .
+                '. ' . self::PRODUCT_NAME . ' OrderId=' . $this->clearpayOrderId .
+                '. Prestashop CartId=' . $this->merchantCartId .
+                '. Prestashop OrderId=' . $this->merchantOrderId;
+            $this->saveLog($message, 2);
+            if ($this->module->currentOrder) {
+                $objOrder = new Order($this->module->currentOrder);
+                $history = new OrderHistory();
+                $history->id_order = (int)$objOrder->id;
+                $history->changeIdOrderState(8, (int)($objOrder->id));
+            }
+        } catch (\Exception $exception) {
+            $this->saveLog('Error on ' . self::PRODUCT_NAME . ' rollback Transaction: ' .
+                '. ' . self::PRODUCT_NAME . ' OrderId=' . $this->clearpayOrderId .
+                '. Prestashop CartId=' . $this->merchantCartId .
+                '. Prestashop OrderId=' . $this->merchantOrderId .
+                $exception->getMessage(), 2);
+        }
+    }
+
+    /**
+     * Lock the concurrency to prevent duplicated inputs
+     * @param $cartId
+     *
+     * @throws Exception
+     */
+    protected function blockConcurrency($cartId)
+    {
+        try {
+            $table = self::CART_TABLE;
+            Db::getInstance()->insert($table, array('id' =>(int)$cartId, 'timestamp' =>(time())));
+        } catch (\Exception $exception) {
+            throw new \Exception($exception->getMessage());
+        }
+    }
+
+    /**
+     * @param null $orderId
+     *
+     * @throws Exception
+     */
+    private function unblockConcurrency($orderId = null)
+    {
+        try {
+            if (is_null($orderId)) {
+                Db::getInstance()->delete(self::CART_TABLE, 'timestamp < ' . (time() - self::CONCURRENCY_TIMEOUT));
+                return;
+            }
+            Db::getInstance()->delete(self::CART_TABLE, 'id = ' . (int)$orderId);
+        } catch (\Exception $exception) {
+            throw new \Exception($exception->getMessage());
+        }
+    }
+
+    /**
+     * Redirect the request to the e-commerce or show the output in json
+     *
+     * @param bool $error
+     */
+    public function getReturnUrl($error = true)
+    {
+        if($error) {
+            $context = Context::getContext();
+            $url = $context->link->getPageLink(
+                'cart',
+                null,
+                null,
+                array('action' => 'show')
+            );
+        } else {
+            $url = $this->config['urlOK'];
+        }
+        $parameters = array(
+            'id_cart' => $this->merchantCartId,
+            'key' => $this->config['secureKey'],
+            'id_module' => $this->module->id,
+            'id_order' => $this->module->currentOrder
+        );
+        if ($this->mismatchError) {
+            $parameters["clearpay_mismatch"] = "true";
+        }
+        if ($this->paymentDeclined) {
+            $parameters["clearpay_declined"] = "true";
+            $parameters["clearpay_reference_id"] = $this->clearpayCapturedPaymentId;
+        }
+
+        $parsedUrl = parse_url($url);
+        $separator = '&';
+        if (!isset($parsedUrl['query']) || $parsedUrl['query'] == null) {
+            $separator = '?';
+        }
+        return $url. $separator . http_build_query($parameters);
+    }
+}
diff --git a/controllers/front/notify.php b/controllers/front/notify.php
index c5326a1..350ec53 100644
--- a/controllers/front/notify.php
+++ b/controllers/front/notify.php
@@ -148,7 +148,7 @@ public function postProcess()
         // Validations
         try {
             $this->prepareVariables();
-            if (!is_null($this->merchantOrderId)) {
+            if (!empty($this->merchantOrderId)) {
                 $this->finishProcess(false);
             }
             $this->checkConcurrency();
diff --git a/controllers/front/payment.php b/controllers/front/payment.php
index af44ddb..9586eab 100644
--- a/controllers/front/payment.php
+++ b/controllers/front/payment.php
@@ -54,8 +54,14 @@ public function getApiVersionPerRegion($region = '')
      */
     public function postProcess()
     {
-        $paymentObjData = array();
         $context = Context::getContext();
+        $cartUrl = $context->link->getPageLink(
+            'cart',
+            null,
+            null,
+            array('action' => 'show')
+        );
+        $paymentObjData = array();
         $paymentObjData['currency'] = $context->currency->iso_code;
         $paymentObjData['region'] = Configuration::get('CLEARPAY_REGION');
 
@@ -132,7 +138,8 @@ public function postProcess()
                 ->setMerchant(array(
                     'redirectConfirmUrl' => $paymentObjData['okUrl'],
                     'redirectCancelUrl' => $paymentObjData['cancelUrl']
-                ))
+                ));
+            $clearpayPaymentObj
                 ->setMerchantAccount($clearpayMerchantAccount)
                 ->setAmount(
                     Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
@@ -221,7 +228,6 @@ public function postProcess()
             } else {
                 $clearpayPaymentObj = $this->addPaymentV2Options($clearpayPaymentObj, $paymentObjData);
             }
-
             $header = $this->module->name . '/' . $this->module->version
                 . ' (Prestashop/' . _PS_VERSION_ . '; PHP/' . phpversion() . '; Merchant/' . $paymentObjData['publicKey']
                 . ') ' . _PS_BASE_URL_SSL_.__PS_BASE_URI__;
@@ -250,9 +256,10 @@ public function postProcess()
                 $errorMessage = $clearpayPaymentObj->getResponse()->getParsedBody()->message;
             }
             $errorMessage .= '. Status code: ' . $clearpayPaymentObj->getResponse()->getHttpStatusCode();
+            $logMessage = 'Error received when trying to create a order: ' .
+                $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri();
             $this->saveLog(
-                'Error received when trying to create a order: ' .
-                $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri(),
+                $logMessage,
                 2
             );
 
@@ -340,6 +347,9 @@ private function getCountryCode($paymentObjData)
                 return $language;
             }
         }
+        if ($language == 'US' || $language == 'EN') {
+            return "GB";
+        }
         return null;
     }
 }
diff --git a/controllers/front/paymentEC.php b/controllers/front/paymentEC.php
deleted file mode 100644
index 045ea5a..0000000
--- a/controllers/front/paymentEC.php
+++ /dev/null
@@ -1,402 +0,0 @@
-
- * @copyright 2020 Clearpay
- * @license   proprietary
- */
-
-use Afterpay\SDK\HTTP\Request\CreateCheckout;
-use Afterpay\SDK\MerchantAccount as ClearpayMerchantAccount;
-
-require_once('AbstractController.php');
-
-/**
- * Class ClearpayPaymentECModuleFrontController
- */
-class ClearpayPaymentECModuleFrontController extends AbstractController
-{
-    /** @var string $language */
-    protected $language;
-
-    /**
-     * Default API Version per region
-     *
-     * @var array
-     */
-    public $defaultApiVersionPerRegion = array(
-        'AU' => 'v2',
-        'CA' => 'v2',
-        'ES' => 'v1',
-        'GB' => 'v2',
-        'NZ' => 'v2',
-        'US' => 'v2',
-    );
-
-    /**
-     * @param $region
-     * @return string
-     */
-    public function getApiVersionPerRegion($region = '')
-    {
-        if (isset($this->defaultApiVersionPerRegion[$region])) {
-            return $this->defaultApiVersionPerRegion[$region];
-        }
-        return json_encode(array($region));
-    }
-
-    /**
-     * @return mixed
-     * @throws \Afterpay\SDK\Exception\InvalidArgumentException
-     * @throws \Afterpay\SDK\Exception\NetworkException
-     * @throws \Afterpay\SDK\Exception\ParsingException
-     */
-    public function postProcess()
-    {
-        $paymentObjData = array();
-        $context = Context::getContext();
-        $paymentObjData['currency'] = $context->currency->iso_code;
-        $paymentObjData['region'] = Configuration::get('CLEARPAY_REGION');
-
-        /** @var Cart $paymentObjData['cart'] */
-        $paymentObjData['cart'] = $context->cart;
-        $paymentObjData['shippingAddress'] = new Address($paymentObjData['cart']->id_address_delivery);
-        $shippingCountryObj = new Country($paymentObjData['shippingAddress']->id_country);
-        $paymentObjData['shippingCountryCode'] = $shippingCountryObj->iso_code;
-        $shippingStateObj = new State($paymentObjData['shippingAddress']->id_state);
-        $paymentObjData['shippingStateCode'] = '';
-        if (!empty($paymentObjData['shippingAddress']->id_state)) {
-            $paymentObjData['shippingStateCode'] = $shippingStateObj->iso_code;
-        }
-        $availableCarriers = $this->getAvailableCarriers();
-        foreach ($availableCarriers as $key => $availableCarrier) {
-            $availableCarriers[$key]['shipping_cost'] = $context->cart->getOrderShippingCost($key);
-        }
-        var_dump("
", $availableCarriers);
-        die();
-        $paymentObjData['billingAddress'] = new Address($paymentObjData['cart']->id_address_invoice);
-        $paymentObjData['billingCountryCode'] = Country::getIsoById($paymentObjData['billingAddress']->id_country);
-        $billingStateObj = new State($paymentObjData['billingAddress']->id_state);
-        $paymentObjData['billingStateCode'] = '';
-        if (!empty($paymentObjData['billingAddress']->id_state)) {
-            $paymentObjData['billingStateCode'] = $billingStateObj->iso_code;
-        }
-        $paymentObjData['countryCode'] = $this->getCountryCode($paymentObjData);
-
-        $paymentObjData['discountAmount'] = $paymentObjData['cart']->getOrderTotal(true, Cart::ONLY_DISCOUNTS);
-
-        /** @var Carrier $paymentObjData['carrier'] */
-        $paymentObjData['carrier'] = new Carrier($paymentObjData['cart']->id_carrier);
-
-        /** @var Customer $paymentObjData['customer'] */
-        $paymentObjData['customer'] = $context->customer;
-
-        if (!$paymentObjData['cart']->id) {
-            Tools::redirect('index.php?controller=order');
-        }
-
-        $paymentObjData['urlToken'] = Tools::strtoupper(md5(uniqid(rand(), true)));
-
-        $paymentObjData['koUrl'] = $context->link->getPageLink(
-            'order',
-            null,
-            null,
-            array('step'=>3)
-        );
-        $paymentObjData['cancelUrl'] = (!empty(Configuration::get('CLEARPAY_URL_KO'))) ?
-            Configuration::get('CLEARPAY_URL_KO') : $paymentObjData['koUrl'];
-        $paymentObjData['publicKey'] = Configuration::get('CLEARPAY_PUBLIC_KEY');
-        $paymentObjData['secretKey'] = Configuration::get('CLEARPAY_SECRET_KEY');
-        $paymentObjData['environment'] = Configuration::get('CLEARPAY_ENVIRONMENT');
-
-        $query = array(
-            'id_cart' => $paymentObjData['cart']->id,
-            'key' => $paymentObjData['cart']->secure_key,
-        );
-        $paymentObjData['okUrl'] = _PS_BASE_URL_SSL_.__PS_BASE_URI__
-            .'index.php?canonical=true&fc=module&module=clearpay&controller=notify'
-            .'&token='.$paymentObjData['urlToken'] . '&' . http_build_query($query)
-        ;
-
-        $url = $paymentObjData['cancelUrl'];
-        try {
-            \Afterpay\SDK\Model::setAutomaticValidationEnabled(true);
-            $clearpayPaymentObj = new CreateCheckout();
-            $clearpayMerchantAccount = new ClearpayMerchantAccount();
-            $clearpayMerchantAccount
-                ->setMerchantId($paymentObjData['publicKey'])
-                ->setSecretKey($paymentObjData['secretKey'])
-                ->setApiEnvironment($paymentObjData['environment'])
-            ;
-            if (!is_null($paymentObjData['countryCode'])) {
-                $clearpayMerchantAccount->setCountryCode($paymentObjData['countryCode']);
-            }
-
-            $clearpayPaymentObj
-                ->setMerchant(array(
-                    'redirectConfirmUrl' => $paymentObjData['okUrl'],
-                    'redirectCancelUrl' => $paymentObjData['cancelUrl']
-                ))
-                ->setMerchantAccount($clearpayMerchantAccount)
-                ->setAmount(
-                    Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
-                    $paymentObjData['currency']
-                )
-                ->setTaxAmount(
-                    Clearpay::parseAmount(
-                        $paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)
-                        -
-                        $paymentObjData['cart']->getOrderTotal(false, Cart::BOTH)
-                    ),
-                    $paymentObjData['currency']
-                )
-                ->setConsumer(array(
-                    'phoneNumber' => $paymentObjData['billingAddress']->phone,
-                    'givenNames' => $paymentObjData['customer']->firstname,
-                    'surname' => $paymentObjData['customer']->lastname,
-                    'email' => $paymentObjData['customer']->email
-                ))
-                ->setBilling(array(
-                    'name' => $paymentObjData['billingAddress']->firstname . " " .
-                        $paymentObjData['billingAddress']->lastname,
-                    'line1' => $paymentObjData['billingAddress']->address1,
-                    'line2' => $paymentObjData['billingAddress']->address2,
-                    'suburb' => $paymentObjData['billingAddress']->city,
-                    'area1' => $paymentObjData['billingAddress']->city,
-                    'state' => $paymentObjData['billingStateCode'],
-                    'region' => $paymentObjData['billingStateCode'],
-                    'postcode' => $paymentObjData['billingAddress']->postcode,
-                    'countryCode' => $paymentObjData['billingCountryCode'],
-                    'phoneNumber' => $paymentObjData['billingAddress']->phone
-                ))
-                ->setShipping(array(
-                    'name' => $paymentObjData['shippingAddress']->firstname . " " .
-                        $paymentObjData['shippingAddress']->lastname,
-                    'line1' => $paymentObjData['shippingAddress']->address1,
-                    'line2' => $paymentObjData['shippingAddress']->address2,
-                    'suburb' => $paymentObjData['shippingAddress']->city,
-                    'area1' => $paymentObjData['shippingAddress']->city,
-                    'state' => $paymentObjData['shippingStateCode'],
-                    'region' => $paymentObjData['shippingStateCode'],
-                    'postcode' => $paymentObjData['shippingAddress']->postcode,
-                    'countryCode' => $paymentObjData['shippingCountryCode'],
-                    'phoneNumber' => $paymentObjData['shippingAddress']->phone
-                ))
-                ->setShippingAmount(
-                    Clearpay::parseAmount($paymentObjData['cart']->getTotalShippingCost()),
-                    $paymentObjData['currency']
-                )
-                ->setCourier(array(
-                    'shippedAt' => '',
-                    'name' => $paymentObjData['carrier']->name . '',
-                    'tracking' => '',
-                    'priority' => 'STANDARD'
-                ));
-
-            if (!empty($paymentObjData['discountAmount'])) {
-                $clearpayPaymentObj->setDiscounts(array(
-                    array(
-                        'displayName' => 'Shop discount',
-                        'amount' => array(
-                            Clearpay::parseAmount($paymentObjData['discountAmount']),
-                            $paymentObjData['currency']
-                        )
-                    )
-                ));
-            }
-
-            $items = $paymentObjData['cart']->getProducts();
-            $products = array();
-            foreach ($items as $item) {
-                $products[] = array(
-                    'name' => utf8_encode($item['name']),
-                    'sku' => $item['reference'],
-                    'quantity' => (int) $item['quantity'],
-                    'price' => array(
-                        'amount' => Clearpay::parseAmount($item['price_wt']),
-                        'currency' => $paymentObjData['currency']
-                    )
-                );
-            }
-            $clearpayPaymentObj->setItems($products);
-
-            $apiVersion = $this->getApiVersionPerRegion($paymentObjData['region']);
-            if ($apiVersion === 'v1') {
-                $clearpayPaymentObj = $this->addPaymentV1Options($clearpayPaymentObj, $paymentObjData);
-            } else {
-                $clearpayPaymentObj = $this->addPaymentV2Options($clearpayPaymentObj, $paymentObjData);
-            }
-
-            $header = $this->module->name . '/' . $this->module->version
-                . ' (Prestashop/' . _PS_VERSION_ . '; PHP/' . phpversion() . '; Merchant/' . $paymentObjData['publicKey']
-                . ') ' . _PS_BASE_URL_SSL_.__PS_BASE_URI__;
-            $clearpayPaymentObj->addHeader('User-Agent', $header);
-            $clearpayPaymentObj->addHeader('Country', $paymentObjData['countryCode']);
-        } catch (\Exception $exception) {
-            $this->saveLog($exception->getMessage(), 3);
-            return Tools::redirect($url);
-        }
-
-        if (!$clearpayPaymentObj->isValid()) {
-            $this->saveLog($clearpayPaymentObj->getValidationErrors(), 2);
-            return Tools::redirect($url);
-        }
-
-        $endPoint = '/' . $apiVersion . '/';
-        $endPoint .= ($apiVersion === 'v2') ? "checkouts": "orders";
-        $clearpayPaymentObj->setUri($endPoint);
-
-        $clearpayPaymentObj->send();
-        $errorMessage = 'empty response';
-        if ($clearpayPaymentObj->getResponse()->getHttpStatusCode() >= 400
-            || isset($clearpayPaymentObj->getResponse()->getParsedBody()->errorCode)
-        ) {
-            if (isset($clearpayPaymentObj->getResponse()->getParsedBody()->message)) {
-                $errorMessage = $clearpayPaymentObj->getResponse()->getParsedBody()->message;
-            }
-            $errorMessage .= $this->l('. Status code: ')
-                . $clearpayPaymentObj->getResponse()->getHttpStatusCode()
-            ;
-            $this->saveLog(
-                $this->l('Error received when trying to create a order: ') .
-                $errorMessage . '. URL: ' . $clearpayPaymentObj->getApiEnvironmentUrl().$clearpayPaymentObj->getUri(),
-                2
-            );
-
-            return Tools::redirect($url);
-        }
-
-        try {
-            $url = $clearpayPaymentObj->getResponse()->getParsedBody()->redirectCheckoutUrl;
-            $orderId = $clearpayPaymentObj->getResponse()->getParsedBody()->token;
-            $cartId = pSQL($paymentObjData['cart']->id);
-            $orderId = pSQL($orderId);
-            $urlToken = pSQL($paymentObjData['urlToken']);
-            $countryCode = pSQL($paymentObjData['countryCode']);
-            $sql = "INSERT INTO `" . _DB_PREFIX_ . "clearpay_order` (`id`, `order_id`, `token`, `country_code`) 
-            VALUES ('$cartId','$orderId', '$urlToken', '$countryCode')";
-            $result = Db::getInstance()->execute($sql);
-            if (!$result) {
-                throw new \Exception('Unable to save clearpay-order-id in database: '. $sql);
-            }
-        } catch (\Exception $exception) {
-            $this->saveLog($exception->getMessage(), 3);
-            $url = $paymentObjData['cancelUrl'];
-        }
-
-        return Tools::redirect($url);
-    }
-
-    /**
-     * @param CreateCheckout $clearpayPaymentObj
-     * @param array $paymentObjData
-     * @return CreateCheckout
-     */
-    private function addPaymentV1Options(CreateCheckout $clearpayPaymentObj, $paymentObjData)
-    {
-        $clearpayPaymentObj->setTotalAmount(
-            Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
-            $paymentObjData['currency']
-        );
-        return $clearpayPaymentObj;
-    }
-
-    /**
-     * @param CreateCheckout $clearpayPaymentObj
-     * @param array $paymentObjData
-     * @return CreateCheckout
-     */
-    private function addPaymentV2Options(CreateCheckout $clearpayPaymentObj, $paymentObjData)
-    {
-        $clearpayPaymentObj->setAmount(
-            Clearpay::parseAmount($paymentObjData['cart']->getOrderTotal(true, Cart::BOTH)),
-            $paymentObjData['currency']
-        );
-        return $clearpayPaymentObj;
-    }
-
-    /**
-     * @param array $paymentObjData
-     * @return string|null
-     */
-    private function getCountryCode($paymentObjData)
-    {
-        $allowedCountries = json_decode(Configuration::get('CLEARPAY_ALLOWED_COUNTRIES'));
-        $lang = Language::getLanguage($this->context->language->id);
-        $langArray = explode("-", $lang['language_code']);
-        if (count($langArray) != 2 && isset($lang['locale'])) {
-            $langArray = explode("-", $lang['locale']);
-        }
-        $language = Tools::strtoupper($langArray[count($langArray)-1]);
-        // Prevent null language detection
-        if (in_array(Tools::strtoupper($language), $allowedCountries)) {
-            return $language;
-        }
-
-        $shippingAddress = new Address($paymentObjData['cart']->id_address_delivery);
-        if ($shippingAddress) {
-            $language = Country::getIsoById($paymentObjData['shippingAddress']->id_country);
-            if (in_array(Tools::strtoupper($language), $allowedCountries)) {
-                return $language;
-            }
-        }
-        $billingAddress = new Address($paymentObjData['cart']->id_address_invoice);
-        if ($billingAddress) {
-            $language = Country::getIsoById($paymentObjData['billingAddress']->id_country);
-            if (in_array(Tools::strtoupper($language), $allowedCountries)) {
-                return $language;
-            }
-        }
-        return null;
-    }
-
-    private function getAvailableCarriers()
-    {
-        $sql = 'SELECT mc.`id_reference`
-			FROM `'._DB_PREFIX_.'module_carrier` mc
-			WHERE mc.`id_module` = '. $this->module->id;
-        $moduleCarriers = Db::getInstance()->ExecuteS($sql);
-        $returnCarriers = array();
-        $allCarriers = Carrier::getCarriers($this->context->language->id, true);
-
-        foreach ($moduleCarriers as $key => $reference) {
-            foreach ($allCarriers as $carrier) {
-                if ($carrier['id_carrier'] == $reference['id_reference']) {
-                    $returnCarriers[$reference['id_reference']] = $carrier;
-                }
-            }
-        }
-        return $returnCarriers;
-    }
-
-    private function makeRequest()
-    {
-        $options = array(
-            CURLOPT_RETURNTRANSFER => true,     // return web page
-            CURLOPT_HEADER         => false,    // don't return headers
-            CURLOPT_FOLLOWLOCATION => true,     // follow redirects
-            CURLOPT_ENCODING       => "",       // handle all encodings
-            CURLOPT_USERAGENT      => "Prestashop", // who am i
-            CURLOPT_AUTOREFERER    => true,     // set referer on redirect
-            CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
-            CURLOPT_TIMEOUT        => 120,      // timeout on response
-            CURLOPT_MAXREDIRS      => 4,       // stop after 10 redirects
-            CURLOPT_SSL_VERIFYPEER => true     // Disabled SSL Cert checks
-        );
-
-        $url = 'https://api.eu-sandbox.afterpay.com/v2/checkouts';
-        $ch      = curl_init( $url );
-        curl_setopt_array( $ch, $options );
-        $content = curl_exec( $ch );
-        $err     = curl_errno( $ch );
-        $errmsg  = curl_error( $ch );
-        $header  = curl_getinfo( $ch );
-        curl_close( $ch );
-
-        $header['errno']   = $err;
-        $header['errmsg']  = $errmsg;
-        $header['content'] = $content;
-        return $header;
-    }
-}
diff --git a/views/templates/hook/express-checkout.tpl b/views/templates/hook/express-checkout.tpl
new file mode 100644
index 0000000..ca840d4
--- /dev/null
+++ b/views/templates/hook/express-checkout.tpl
@@ -0,0 +1,174 @@
+{*
+ * This file is part of the official Clearpay module for PrestaShop.
+ *
+ * @author    Clearpay 
+ * @copyright 2020 Clearpay
+ * @license   proprietary
+*}
+
+
+
+
+
+
+

From cec0dab0373bd9d6ed06d4494286fdf1ca181e43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= 
Date: Tue, 20 Jul 2021 18:33:13 +0200
Subject: [PATCH 3/8] ec fixes

---
 controllers/front/express.php             | 70 +++++++++++------------
 views/templates/hook/express-checkout.tpl |  2 +-
 2 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/controllers/front/express.php b/controllers/front/express.php
index a162e6d..0e5b9a4 100644
--- a/controllers/front/express.php
+++ b/controllers/front/express.php
@@ -398,6 +398,7 @@ private function getAvailableCarriers()
      */
     private function captureClearpayOrder ()
     {
+
         // Validations
         try {
             $this->prepareVariables();
@@ -416,6 +417,7 @@ private function captureClearpayOrder ()
             $this->validateAmount();
             $this->checkMerchantOrderStatus();
         } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
             header('Content-type: application/json; charset=utf-8');
             echo json_encode(array(
                 'success'  => false,
@@ -427,9 +429,9 @@ private function captureClearpayOrder ()
 
         // Process Clearpay Order
         try {
-            //$this->captureClearpayPayment();
-            $this->clearpayCapturedPaymentId = "55443322";
+            $this->captureClearpayPayment();
         } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
             header('Content-type: application/json; charset=utf-8');
             echo json_encode(array(
                 'success'  => false,
@@ -440,9 +442,10 @@ private function captureClearpayOrder ()
         }
 
         // Process Merchant Order
-        $this->processMerchantOrder();
         try {
+            $this->processMerchantOrder();
         } catch (\Exception $exception) {
+            $this->saveLog($exception->getMessage(), 3);
             $this->rollbackMerchantOrder();
             header('Content-type: application/json; charset=utf-8');
             echo json_encode(array(
@@ -557,17 +560,13 @@ public function getMerchantOrderId()
      */
     public function getMerchantCart()
     {
-        try {
-            $this->merchantCart = new Cart($this->merchantCartId);
-            if (!Validate::isLoadedObject($this->merchantCart)) {
-                // This exception is only for Prestashop
-                throw new \Exception('Unable to load cart');
-            }
-            if ($this->merchantCart->secure_key != $this->config['secureKey']) {
-                throw new \Exception('Secure Key is not valid');
-            }
-        } catch (\Exception $exception) {
-            throw new \Exception('Unable to find cart with id' . $this->merchantCartId);
+        $this->merchantCart = new Cart($this->merchantCartId);
+        if (!Validate::isLoadedObject($this->merchantCart)) {
+            // This exception is only for Prestashop
+            throw new \Exception('Unable to load cart with id' . $this->merchantCartId);
+        }
+        if ($this->merchantCart->secure_key != $this->config['secureKey']) {
+            throw new \Exception('Secure Key is not valid');
         }
     }
 
@@ -636,25 +635,25 @@ public function validateAmount()
         } else {
             $cpAmount = $this->clearpayOrder->amount->amount;
         }
-        $totalAmount = (string) $cpAmount;
-        $merchantAmount = (string) ($this->merchantCart->getOrderTotal(true, Cart::BOTH));
-        if ($totalAmount != $merchantAmount) {
-            $numberClearpayAmount = (integer) (100 * $cpAmount);
-            $ClearpayShippingOption = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
-            $numberMerchantAmount = (integer) (100 * $this->merchantCart->getOrderTotal(true, Cart::BOTH)) +
-                (integer) (100 * $ClearpayShippingOption['shippingAmount']['amount']);
-            $amountDff =  $numberMerchantAmount - $numberClearpayAmount;
-            if (abs($amountDff) > self::MISMATCH_AMOUNT_THRESHOLD) {
-                $this->mismatchError = true;
-                $amountMismatchError = 'Amount mismatch in PrestaShop Cart #'. $this->merchantCartId .
-                    ' compared with ' . self::PRODUCT_NAME . ' Order: ' . $this->clearpayOrderId .
-                    '. The Cart in PrestaShop has an amount of: ' . $merchantAmount . ' and in ' . self::PRODUCT_NAME .
-                    ' of: ' . $totalAmount;
-
-                $this->saveLog($amountMismatchError, 3);
-                throw new \Exception($amountMismatchError);
-            }
+
+        $numberClearpayAmount = (integer) (100 * $cpAmount);
+        $ClearpayShippingOption = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
+        $numberMerchantAmount = (integer) (100 * $this->merchantCart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING)) +
+            (integer) (100 * $ClearpayShippingOption['shippingAmount']['amount']);
+        $merchantAmount = (string)($numberMerchantAmount/100);
+        $amountDff =  $numberMerchantAmount - $numberClearpayAmount;
+
+        if (abs($amountDff) > self::MISMATCH_AMOUNT_THRESHOLD) {
+            $this->mismatchError = true;
+            $amountMismatchError = 'Amount mismatch in PrestaShop Cart #'. $this->merchantCartId .
+                ' compared with ' . self::PRODUCT_NAME . ' Order: ' . $this->clearpayOrderId .
+                '. The Cart in PrestaShop has an amount of: ' . $merchantAmount . ' and in ' . self::PRODUCT_NAME .
+                ' of: ' . (string) $cpAmount;
+
+            $this->saveLog($amountMismatchError, 3);
+            throw new \Exception($amountMismatchError);
         }
+
     }
 
     /**
@@ -806,7 +805,6 @@ public function processMerchantOrder()
         $delivery_option[$this->merchantCart->id_address_delivery] =
             (string)$this->clearpayOrder->shippingOptionIdentifier.',';
         $this->merchantCart->setDeliveryOption($delivery_option);
-        //var_dump("
", $delivery_option);die;
         $this->merchantCart->save();
 
         $validateOrder = $this->module->validateOrder(
@@ -815,7 +813,9 @@ public function processMerchantOrder()
             $cpAmount,
             self::PRODUCT_NAME,
             'clearpayOrderId: ' .  $this->clearpayCapturedPaymentId,
-            array('transaction_id' => $this->clearpayCapturedPaymentId),
+            array('transaction_id' => $this->clearpayCapturedPaymentId,
+                'ClearpayAmount' => $cpAmount,
+                "ShippingMethod" => $this->clearpayOrder->shippingOptionIdentifier),
             null,
             false,
             $this->config['secureKey']
@@ -833,7 +833,7 @@ public function processMerchantOrder()
         $shippingTotalAmount = 0;
         $shippingMethod = $this->getShippingMethods($this->clearpayOrder->shippingOptionIdentifier);
         if (!empty($shippingMethod)) {
-            $shippingTotalAmount = $shippingMethod->shippingAmount->amount;
+            $shippingTotalAmount = $shippingMethod['shippingAmount']['amount'];
         }
         $order->total_shipping = $shippingTotalAmount;
         $order->total_shipping_tax_incl = $shippingTotalAmount;
diff --git a/views/templates/hook/express-checkout.tpl b/views/templates/hook/express-checkout.tpl
index ca840d4..ae55e72 100644
--- a/views/templates/hook/express-checkout.tpl
+++ b/views/templates/hook/express-checkout.tpl
@@ -117,7 +117,7 @@
                                 console.log("success", ajax_data);
                                 if (ajax_data.success === true) {
                                     jQuery('.btn-afterpay_express').prop('disabled', false);
-                                    // window.location.href = ajax_data.url;
+                                    window.location.href = ajax_data.url;
                                     if (spinner) {
                                         spinner.overlay.remove();
                                         spinner.css.remove();

From 08d2a95caa34885dc074022329faff5ae1c028b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= 
Date: Wed, 21 Jul 2021 10:26:23 +0200
Subject: [PATCH 4/8] ec fixes

---
 controllers/front/express.php | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/controllers/front/express.php b/controllers/front/express.php
index 0e5b9a4..f687516 100644
--- a/controllers/front/express.php
+++ b/controllers/front/express.php
@@ -156,6 +156,14 @@ public function postProcess()
             // use shippingOptionIdentifier order field to set the carrier
             $this->captureClearpayOrder();
         }
+
+        $url = $this->context->link->getPageLink(
+            'index',
+            null,
+            null,
+            array()
+        );
+        return Tools::redirect($url);
     }
 
     /**
@@ -796,6 +804,7 @@ public function processMerchantOrder()
         //set the customer and the guest ids into the cart
         $this->merchantCart->id_customer = $customer->id;
         $this->merchantCart->id_guest = $guest->id;
+
         //set the delivery method id into the cart
         $this->merchantCart->id_carrier = $this->clearpayOrder->shippingOptionIdentifier;
         $delivery_option = $this->merchantCart->getDeliveryOption();
@@ -821,6 +830,7 @@ public function processMerchantOrder()
             $this->config['secureKey']
         );
 
+        // Update order data after clearpay complete
         $orderId = Order::getIdByCartId($this->merchantCartId);
         $order = new Order($orderId);
         $taxRate = (100 * $order->total_paid_tax_excl) / $cpAmount;
@@ -838,6 +848,16 @@ public function processMerchantOrder()
         $order->total_shipping = $shippingTotalAmount;
         $order->total_shipping_tax_incl = $shippingTotalAmount;
         $order->total_shipping_tax_excl = round((($shippingTotalAmount * $taxRate) / 100), 2);
+        $order->save();
+
+        // Update context and cookie before redirection.
+        $this->context->customer = $customer;
+        $this->context->cookie->id_customer = (int) $customer->id;
+        $this->context->cookie->customer_lastname = $customer->lastname;
+        $this->context->cookie->customer_firstname = $customer->firstname;
+        $this->context->cookie->passwd = $customer->passwd;
+        $this->context->cookie->email = $customer->email;
+        $this->context->cookie->is_guest = $customer->isGuest();
 
         $this->updateClearpayOrder();
 
@@ -973,6 +993,7 @@ public function getReturnUrl($error = true)
             'id_module' => $this->module->id,
             'id_order' => $this->module->currentOrder
         );
+
         if ($this->mismatchError) {
             $parameters["clearpay_mismatch"] = "true";
         }

From c61dd583cd2f932eeabcd0fde1373d40613b71b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= 
Date: Wed, 21 Jul 2021 18:54:25 +0200
Subject: [PATCH 5/8] ps 1.6 compatible

---
 clearpay.php                              | 66 ++++++++++++++++++-----
 controllers/front/express.php             | 15 ++++--
 views/templates/hook/express-checkout.tpl | 14 +++--
 3 files changed, 74 insertions(+), 21 deletions(-)

diff --git a/clearpay.php b/clearpay.php
index 2abfdd3..d11df96 100644
--- a/clearpay.php
+++ b/clearpay.php
@@ -159,6 +159,7 @@ public function __construct()
             $this->currencySymbol = $context->currency->sign;
         }
 
+        $this->registerHook('displayShoppingCartFooter');
         parent::__construct();
     }
 
@@ -209,6 +210,7 @@ public function install()
             && $this->registerHook('actionOrderSlipAdd')
             && $this->registerHook('actionProductCancel')
             && $this->registerHook('header')
+            && $this->registerHook('displayShoppingCartFooter')
         );
 
         if ($return && _PS_VERSION_ < "1.7") {
@@ -361,6 +363,14 @@ public function hookHeader($params)
         }
     }
 
+    /**
+     * @throws Exception
+     */
+    public function HookDisplayShoppingCartFooter()
+    {
+        return $this->getExpressButton();
+    }
+
     /**
      * @return array
      * @throws Exception
@@ -1006,20 +1016,7 @@ public function templateDisplay($templateName = '')
             );
 
             if ($IsEcEnabled) {
-                $merchantCart = new Cart($this->context->cart->id);
-                if (empty($merchantCart->secure_key)) {
-                    $merchantCart->secure_key = md5(uniqid(rand(), true));
-                    $merchantCart->save();
-                }
-                $params = array(
-                    'EXPRESS_CONTROLLER' => $this->context->link->getModuleLink('clearpay', 'express'),
-                    'SECURE_KEY' => $merchantCart->secure_key
-                );
-                $this->context->smarty->assign($params);
-                $return .= $this->display(
-                    __FILE__,
-                    'views/templates/hook/express-checkout.tpl'
-                );
+                $return .= $this->getExpressButton();
             }
         } else {
             if ($isEnabled && $templateName === 'product.tpl' && Configuration::get('CLEARPAY_LOGS') === 'on') {
@@ -1046,6 +1043,47 @@ public function templateDisplay($templateName = '')
         return $return;
     }
 
+    protected function getExpressButton()
+    {
+        $merchantCart = new Cart($this->context->cart->id);
+        $params = array();
+
+        if (!isset($this->context->smarty->tpl_vars["COUNTRY"])) {
+            $language = Language::getLanguage($this->context->language->id);
+            if (isset($language['locale'])) {
+                $language = $language['locale'];
+            } else {
+                $language = $language['language_code'];
+            }
+            if($language == "en-us") {
+                $language = "en-gb";
+            }
+            $isoCountryCode = str_replace('-', '_', $language);
+            // Preserve Uppercase in locale
+            if (Tools::strlen($isoCountryCode) == 5) {
+                $isoCountryCode = Tools::substr($isoCountryCode, 0, 2) .
+                    Tools::strtoupper(Tools::substr($isoCountryCode, 2, 4));
+            }
+            $params["COUNTRY"] = Tools::strtoupper(Tools::substr($isoCountryCode, 3, 4));;
+        }
+        // Temporary hook to prevent EC on Europe
+        if($params["COUNTRY"] != 'GB') {
+            return '';
+        }
+        if (empty($merchantCart->secure_key)) {
+            $merchantCart->secure_key = md5(uniqid(rand(), true));
+            $merchantCart->save();
+        }
+        $params["EXPRESS_CONTROLLER"] = $this->context->link->getModuleLink('clearpay', 'express');
+        $params["SECURE_KEY"] = $merchantCart->secure_key;
+        $this->context->smarty->assign($params);
+        return $this->display(
+            __FILE__,
+            'views/templates/hook/express-checkout.tpl'
+        );
+    }
+
+
     /**
      * @return bool
      */
diff --git a/controllers/front/express.php b/controllers/front/express.php
index f687516..3f1a820 100644
--- a/controllers/front/express.php
+++ b/controllers/front/express.php
@@ -387,6 +387,10 @@ private function getAvailableCarriers()
         $sql = 'SELECT mc.`id_reference`
 			FROM `'._DB_PREFIX_.'module_carrier` mc
 			WHERE mc.`id_module` = '. $this->module->id;
+        if (version_compare(_PS_VERSION_, '1.7', 'lt')) {
+            $sql = 'SELECT `id_reference`
+			FROM `'._DB_PREFIX_.'carrier`';
+        }
         $moduleCarriers = Db::getInstance()->ExecuteS($sql);
         $returnCarriers = array();
         $allCarriers = Carrier::getCarriers($this->context->language->id, true);
@@ -406,7 +410,6 @@ private function getAvailableCarriers()
      */
     private function captureClearpayOrder ()
     {
-
         // Validations
         try {
             $this->prepareVariables();
@@ -783,7 +786,9 @@ public function processMerchantOrder()
         $billingAddress->alias = 'ClearpayExpress:'.$this->merchantCartId;
         $billingAddress->save();
         $this->merchantCart->updateAddressId(0, $billingAddress->id);
-        $this->merchantCart->updateDeliveryAddressId(0, $billingAddress->id);
+        if (version_compare(_PS_VERSION_, '1.7', 'ge')) {
+            $this->merchantCart->updateDeliveryAddressId(0, $billingAddress->id);
+        }
         $this->merchantCart->update();
         $this->merchantCart->save();
 
@@ -831,7 +836,11 @@ public function processMerchantOrder()
         );
 
         // Update order data after clearpay complete
-        $orderId = Order::getIdByCartId($this->merchantCartId);
+        if (version_compare(_PS_VERSION_, '1.7', 'ge')) {
+            $orderId = Order::getIdByCartId($this->merchantCartId);
+        } else {
+            $orderId = Order::getOrderByCartId($this->merchantCartId);
+        }
         $order = new Order($orderId);
         $taxRate = (100 * $order->total_paid_tax_excl) / $cpAmount;
         $total_paid_tax_excl = round((($cpAmount * $taxRate) / 100), 2);
diff --git a/views/templates/hook/express-checkout.tpl b/views/templates/hook/express-checkout.tpl
index ae55e72..bd7acbf 100644
--- a/views/templates/hook/express-checkout.tpl
+++ b/views/templates/hook/express-checkout.tpl
@@ -33,6 +33,12 @@
     .btn-afterpay_express img {
         width: 100%;
     }
+    #afterpay_express_button {
+        margin-bottom: 10px;
+    }
+    #HOOK_SHOPPING_CART {
+        text-align: right;
+    }
 
 
 
-
-
-
+
\ No newline at end of file