aboutsummaryrefslogtreecommitdiffstats
path: root/public/catalog/controller/extension/payment/klarna_checkout.php
diff options
context:
space:
mode:
Diffstat (limited to 'public/catalog/controller/extension/payment/klarna_checkout.php')
-rw-r--r--public/catalog/controller/extension/payment/klarna_checkout.php1963
1 files changed, 1963 insertions, 0 deletions
diff --git a/public/catalog/controller/extension/payment/klarna_checkout.php b/public/catalog/controller/extension/payment/klarna_checkout.php
new file mode 100644
index 0000000..675ea81
--- /dev/null
+++ b/public/catalog/controller/extension/payment/klarna_checkout.php
@@ -0,0 +1,1963 @@
+<?php
+class ControllerExtensionPaymentKlarnaCheckout extends Controller {
+ public function index() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $this->document->setTitle($this->language->get('heading_title'));
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout', $data));
+ }
+
+ public function main() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $redirect = false;
+ $html_snippet = '';
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+ }
+
+ // Validate cart has recurring products
+ if ($this->cart->hasRecurringProducts()) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ if ($this->config->get('klarna_checkout_total') > 0 && $this->config->get('klarna_checkout_total') > $total) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if ($this->model_extension_payment_klarna_checkout->checkForPaymentTaxes($products)) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ $text_title = $this->language->get('text_title');
+
+ unset($this->session->data['success']);
+
+ $this->setPayment();
+ $this->setShipping();
+
+ $this->session->data['payment_method'] = array(
+ 'code' => 'klarna_checkout',
+ 'title' => $text_title,
+ 'terms' => $this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true),
+ 'sort_order' => '1'
+ );
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote['code'] == $this->session->data['shipping_method']['code']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ //Klarna Connector
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
+
+ if (!$klarna_account || !$connector) {
+ $redirect = $this->url->link('checkout/cart');
+ }
+
+ if (!$redirect) {
+ // Get currency code and currency value to use to calculate taxes
+
+ // Build order_lines
+ $create_order = true;
+ $klarna_checkout = false;
+
+ $this->createOrder();
+
+ list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
+
+ if (isset($this->session->data['klarna_checkout_currency']) && $this->session->data['klarna_checkout_currency'] != $this->session->data['currency']) {
+ $this->model_extension_payment_klarna_checkout->log('Currency changed, unsetting kc order id');
+ unset($this->session->data['klarna_checkout_order_id']);
+ unset($this->session->data['klarna_checkout_data']);
+ }
+
+ $this->session->data['klarna_checkout_currency'] = $this->session->data['currency'];
+
+ // Fetch or create order
+ if (isset($this->session->data['klarna_checkout_order_id'])) {
+ $retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->session->data['klarna_checkout_order_id']);
+
+ if ($retrieve) {
+ //If address has changed, unset klarna_checkout_order_id and create new order
+ $address_change = false;
+
+ if (isset($this->session->data['klarna_checkout_data']) && $this->session->data['klarna_checkout_data']) {
+ if (isset($this->session->data['klarna_checkout_data']['zone_code'])) {
+ $kc_region = $this->session->data['klarna_checkout_data']['zone_code'];
+ } else {
+ $kc_region = '';
+ }
+
+ if (isset($this->session->data['klarna_checkout_data']['iso_code_2'])) {
+ $kc_country = $this->session->data['klarna_checkout_data']['iso_code_2'];
+ } else {
+ $kc_country = '';
+ }
+
+ if (isset($this->session->data['shipping_address']['zone_code'])) {
+ $oc_region = $this->session->data['shipping_address']['zone_code'];
+ } else {
+ $oc_region = '';
+ }
+
+ if (isset($this->session->data['shipping_address']['iso_code_2'])) {
+ $oc_country = $this->session->data['shipping_address']['iso_code_2'];
+ } else {
+ $oc_country = '';
+ }
+
+ $kc_address = array(
+ 'region' => $kc_region,
+ 'country' => $kc_country,
+ );
+
+ $oc_address = array(
+ 'region' => $oc_region,
+ 'country' => $oc_country,
+ );
+
+ //If address has changed, dont use retrieved order, create new one instead
+ if (array_diff(array_map('strtolower', $kc_address), array_map('strtolower', $oc_address))) {
+ $address_change = true;
+ }
+ }
+
+ if (!$address_change) {
+ $this->model_extension_payment_klarna_checkout->log('Order Updated');
+ $this->model_extension_payment_klarna_checkout->log($klarna_order_data);
+
+ $create_order = false;
+
+ $update = $this->model_extension_payment_klarna_checkout->orderUpdate($connector, $this->session->data['klarna_checkout_order_id'], $klarna_order_data);
+
+ if ($update) {
+ $klarna_checkout = $update->fetch();
+
+ $this->model_extension_payment_klarna_checkout->updateOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
+ }
+ }
+ }
+ }
+
+ if ($create_order) {
+ $this->model_extension_payment_klarna_checkout->log('Order Created');
+ $this->model_extension_payment_klarna_checkout->log($klarna_order_data);
+
+ unset($this->session->data['klarna_checkout_data']);
+
+ $create = $this->model_extension_payment_klarna_checkout->orderCreate($connector, $klarna_order_data);
+
+ if ($create) {
+ $klarna_checkout = $create->fetch();
+
+ $this->model_extension_payment_klarna_checkout->addOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
+ }
+ }
+
+ if ($klarna_checkout) {
+ $this->session->data['klarna_checkout_order_id'] = $klarna_checkout['order_id'];
+
+ $html_snippet = $klarna_checkout['html_snippet'];
+ }
+ }
+
+ if (isset($this->request->post['response']) && $this->request->post['response'] == 'template') {
+ $data['redirect'] = $redirect;
+
+ $data['klarna_checkout'] = $html_snippet;
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_main', $data));
+ } elseif (isset($this->request->post['response']) && $this->request->post['response'] == 'json') {
+ $json['redirect'] = $redirect;
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+ }
+
+ public function sidebar() {
+ $this->load->language('checkout/checkout');
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $this->setPayment();
+ $this->setShipping();
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote['code'] == $this->session->data['shipping_method']['code']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ $data['shipping_required'] = $this->cart->hasShipping();
+
+ if (isset($this->session->data['shipping_methods'])) {
+ $data['shipping_methods'] = $this->session->data['shipping_methods'];
+ } else {
+ unset($data['shipping_method']);
+
+ $data['shipping_methods'] = array();
+ }
+
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $data['code'] = $this->session->data['shipping_method']['code'];
+ } else {
+ $data['code'] = '';
+ }
+
+ $this->load->model('tool/image');
+ $this->load->model('tool/upload');
+
+ $data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ if ($product['image']) {
+ $image = $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_height'));
+ } else {
+ $image = '';
+ }
+
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ if ($option['type'] != 'file') {
+ $value = $option['value'];
+ } else {
+ $upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
+
+ if ($upload_info) {
+ $value = $upload_info['name'];
+ } else {
+ $value = '';
+ }
+ }
+
+ $option_data[] = array(
+ 'name' => $option['name'],
+ 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value),
+ 'type' => $option['type']
+ );
+ }
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $price = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
+ } else {
+ $price = false;
+ }
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $total = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')) * $product['quantity'], $this->session->data['currency']);
+ } else {
+ $total = false;
+ }
+
+ $data['products'][] = array(
+ 'cart_id' => $product['cart_id'],
+ 'thumb' => $image,
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'recurring' => ($product['recurring'] ? $product['recurring']['name'] : ''),
+ 'quantity' => $product['quantity'],
+ 'price' => $price,
+ 'total' => $total,
+ 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id'])
+ );
+ }
+
+ // Gift Voucher
+ $data['vouchers'] = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $key => $voucher) {
+ $data['vouchers'][] = array(
+ 'key' => $key,
+ 'description' => $voucher['description'],
+ 'amount' => $this->currency->format($voucher['amount'], $this->session->data['currency'])
+ );
+ }
+ }
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ $this->load->model('setting/extension');
+
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get($result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $data['totals'] = array();
+
+ foreach ($totals as $total) {
+ $data['totals'][] = array(
+ 'title' => $total['title'],
+ 'text' => $this->currency->format($total['value'], $this->session->data['currency'])
+ );
+ }
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_sidebar', $data));
+ }
+
+ public function shippingAddress() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/zone');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $json = array();
+
+ unset($this->session->data['shipping_address']);
+ unset($this->session->data['shipping_methods']);
+
+ if (($this->request->server['REQUEST_METHOD'] == 'POST') && isset($this->request->post['country'])) {
+ $country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode3($this->request->post['country']);
+
+ if ($country_info) {
+ // Set default zone for shipping calculations. Get overwritten by correct data when order is confirmed
+ $zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
+
+ $zone = array();
+ if (isset($this->request->post['region']) && !empty($this->request->post['region'])) {
+ $zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($this->request->post['region'], $country_info['country_id']);
+ }
+
+ if ($zone || $zones) {
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => utf8_substr($this->request->post['given_name'], 0, 32),
+ 'lastname' => utf8_substr($this->request->post['family_name'], 0, 32),
+ 'company' => null,
+ 'address_1' => utf8_substr($this->request->post['street_address'], 0, 128),
+ 'address_2' => utf8_substr($this->request->post['street_address'], 129, 256),
+ 'postcode' => utf8_substr($this->request->post['postal_code'], 0, 10),
+ 'city' => utf8_substr($this->request->post['city'], 0, 128),
+ 'zone_id' => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
+ 'zone' => ($zone ? $zone['name'] : $zones[0]['name']),
+ 'zone_code' => ($zone ? $zone['code'] : $zones[0]['code']),
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => $country_info['address_format'],
+ 'custom_field' => array(),
+ );
+
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Couldnt find country: ' . $this->request->post['country']);
+ }
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function cartTotal() {
+ $this->load->language('checkout/cart');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ // Totals
+ $this->load->model('setting/extension');
+
+ $totals = array();
+ $taxes = $this->cart->getTaxes();
+ $total = 0;
+
+ // Because __call can not keep var references so we put them into an array.
+ $total_data = array(
+ 'totals' => &$totals,
+ 'taxes' => &$taxes,
+ 'total' => &$total
+ );
+
+ // Display prices
+ if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
+ $sort_order = array();
+
+ $results = $this->model_setting_extension->getExtensions('total');
+
+ foreach ($results as $key => $value) {
+ $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
+ }
+
+ array_multisort($sort_order, SORT_ASC, $results);
+
+ foreach ($results as $result) {
+ if ($this->config->get($result['code'] . '_status')) {
+ $this->load->model('extension/total/' . $result['code']);
+
+ // We have to put the totals in an array so that they pass by reference.
+ $this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($totals as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $totals);
+
+ $total = sprintf($this->language->get('text_items'), $this->cart->countProducts() + (isset($this->session->data['vouchers']) ? count($this->session->data['vouchers']) : 0), $this->currency->format($total, $this->session->data['currency']));
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($total));
+ }
+
+ public function addressUpdate() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('account/customer');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/zone');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $process = true;
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ $json = array();
+
+ $http_response_code = 400;
+
+ // Check to see if request data is complete
+ if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address)) {
+ $this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $process = false;
+ }
+
+ // Get Klarna order info from db
+ if ($process) {
+ $order_id = null;
+
+ foreach ($request->order_lines as $order_line) {
+ if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
+ $order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
+ break;
+ }
+ }
+
+ if ($order_id) {
+ // Get klarna order data from db
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
+
+ if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
+ $this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
+ $process = false;
+ }
+ } else {
+ $process = false;
+ }
+ }
+
+ if ($process) {
+ $klarna_checkout_order_data = json_decode($this->encryption->decrypt($this->config->get('config_encryption'), $klarna_checkout_order['data']), true);
+
+ // Check credentials in request with ones stored in db
+ $valid_request = false;
+ foreach ($this->config->get('klarna_checkout_account') as $account) {
+ if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
+ $valid_request = true;
+ break;
+ }
+ }
+
+ if (!$valid_request) {
+ $this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
+ $process = false;
+ }
+ }
+
+ // Request is valid, we can spoof/simulate the customer to calculate shipping
+ if ($process) {
+ session_destroy();
+ session_id($klarna_checkout_order_data['session_id']);
+ session_start();
+ $this->session->start('default', $klarna_checkout_order_data['session_key']);
+
+ if ($klarna_checkout_order_data['customer_id']) {
+ $customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
+
+ if ($customer_info) {
+ $this->customer->login($customer_info['email'], '', true);
+ }
+ }
+
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if (!$order_info) {
+ $this->model_extension_payment_klarna_checkout->log('No order found using order_id: ' . $order_id . '. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $process = false;
+ }
+
+ // Set more session data from the order
+ $this->session->data['currency'] = $order_info['currency_code'];
+ $this->session->data['language'] = $order_info['language_code'];
+
+ $country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
+
+ if (!$country_info) {
+ $this->model_extension_payment_klarna_checkout->log('No country found using: ' . $request->shipping_address->country . '. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ }
+
+ if ($order_info && $country_info) {
+ $zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
+
+ $zone = array();
+ if (isset($request->shipping_address->region) && !empty($request->shipping_address->region)) {
+ $zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $country_info['country_id']);
+ }
+
+ if ($zone || $zones) {
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
+ 'zone' => ($zone ? $zone['name'] : $zones[0]['name']),
+ 'zone_code' => ($zone ? $zone['code'] : $zones[0]['code']),
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+
+ $this->session->data['klarna_checkout_data'] = array(
+ 'email' => $request->billing_address->email,
+ 'firstname' => $request->billing_address->given_name,
+ 'lastname' => $request->billing_address->family_name,
+ 'telephone' => $request->billing_address->phone,
+ 'iso_code_2' => $this->session->data['shipping_address']['iso_code_2'],
+ 'zone_code' => $this->session->data['shipping_address']['zone_code']
+ );
+
+ // Unset $tax_rates
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($country_info['country_id'], ($zone ? $zone['zone_id'] : $zones[0]['zone_id']));
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ //Check if customer is US. If so, send taxes differently
+ if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
+ $include_taxes = false;
+ } else {
+ $include_taxes = true;
+ }
+
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $method_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $shipping_methods = $method_data;
+
+ if ($shipping_methods) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
+
+ if ($klarna_account && $connector) {
+ list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
+
+ if ($this->cart->hasShipping()) {
+ $shipping_method = array();
+
+ if (isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
+ foreach ($shipping_methods as $individual_shipping_method) {
+ if ($individual_shipping_method['quote']) {
+ foreach ($individual_shipping_method['quote'] as $quote) {
+ if (($this->session->data['shipping_method']['code'] == $quote['code']) && ($this->session->data['shipping_method']['title'] == $quote['title']) && ($this->session->data['shipping_method']['cost'] == $quote['cost']) && ($this->session->data['shipping_method']['tax_class_id'] == $quote['tax_class_id'])) {
+ $shipping_method = $quote;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ // If the current shipping method isn't in the available shipping methods, assign default
+ if (!$shipping_method) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($shipping_methods);
+ }
+
+ $total_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id']), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], false), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
+ if ($order_line['type'] == 'shipping_fee') {
+ unset($klarna_order_data['order_lines'][$key]);
+ break;
+ }
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'shipping_fee',
+ 'name' => $this->session->data['shipping_method']['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ //If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
+ if (!$include_taxes) {
+ foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
+ if ($order_line['type'] == 'sales_tax') {
+ unset($klarna_order_data['order_lines'][$key]);
+ break;
+ }
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'sales_tax',
+ 'name' => $this->language->get('text_sales_tax'),
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ $http_response_code = 200;
+
+ $json = array(
+ 'order_amount' => round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'order_tax_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
+ 'order_lines' => array_values($klarna_order_data['order_lines'])
+ );
+ }
+ }
+ }
+ }
+ }
+
+ $this->model_extension_payment_klarna_checkout->log($http_response_code);
+ $this->model_extension_payment_klarna_checkout->log($json);
+
+ http_response_code($http_response_code);
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function notification() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ if (isset($request->order_id)) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($request->order_id);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if (!$klarna_account || !$connector) {
+ $this->model_extension_payment_klarna_checkout->log('Could not getConnector');
+ }
+
+ $retrieve = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $request->order_id);
+
+ $order_status_id = false;
+ if ($retrieve) {
+ switch ($request->event_type) {
+ case 'FRAUD_RISK_ACCEPTED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_accepted_id');
+ break;
+ case 'FRAUD_RISK_REJECTED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
+ break;
+ }
+ }
+
+ if ($order_status_id) {
+ $this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $request->order_id);
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('$request->order_id is not set');
+ }
+ }
+
+ public function validation() {
+ $this->load->model('account/customer');
+ $this->load->model('checkout/order');
+ $this->load->model('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ $validate = true;
+
+ $request = json_decode(file_get_contents('php://input'));
+
+ $json = array();
+
+ // Check to see if request data is complete
+ if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address) || !isset($request->billing_address) || empty($request->billing_address)) {
+ $this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
+ $this->model_extension_payment_klarna_checkout->log($request);
+ $validate = false;
+ }
+
+ // Get Klarna order info from db
+ if ($validate) {
+ $order_id = null;
+
+ foreach ($request->order_lines as $order_line) {
+ if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
+ $order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
+ break;
+ }
+ }
+
+ if ($order_id) {
+ // Get klarna order data from db
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
+
+ if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
+ $this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
+ $validate = false;
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot get decrypted order_id');
+ $validate = false;
+ }
+ }
+
+ if ($validate) {
+ $klarna_checkout_order_data = json_decode($this->encryption->decrypt($klarna_checkout_order['data']), true);
+
+ // Check credentials in request with ones stored in db
+ $valid_request = false;
+ foreach ($this->config->get('klarna_checkout_account') as $account) {
+ if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
+ $valid_request = true;
+ break;
+ }
+ }
+
+ if (!$valid_request) {
+ $this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
+ $validate = false;
+ }
+ }
+
+ // Spoof/simulate the customer to calculate shipping
+ if ($validate) {
+ session_destroy();
+ session_id($klarna_checkout_order_data['session_id']);
+ session_start();
+ $this->session->start('default', $klarna_checkout_order_data['session_key']);
+
+ if ($klarna_checkout_order_data['customer_id']) {
+ $customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
+
+ if ($customer_info) {
+ $this->customer->login($customer_info['email'], '', true);
+ }
+ }
+
+ // Validate cart has products and has stock.
+ if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
+ $this->model_extension_payment_klarna_checkout->log('Cart has no products or cart has no stock');
+ $validate = false;
+ }
+
+ // Validate minimum quantity requirements.
+ $products = $this->cart->getProducts();
+
+ foreach ($products as $product) {
+ $product_total = 0;
+
+ foreach ($products as $product_2) {
+ if ($product_2['product_id'] == $product['product_id']) {
+ $product_total += $product_2['quantity'];
+ }
+ }
+
+ if ($product['minimum'] > $product_total) {
+ $this->model_extension_payment_klarna_checkout->log('Cart doesnt meet minimum quantities');
+ $validate = false;
+ }
+ }
+
+ // Validate cart has recurring products
+ if ($this->cart->hasRecurringProducts()) {
+ $this->model_extension_payment_klarna_checkout->log('Cart has recurring products');
+ $validate = false;
+ }
+ }
+
+ // Check order total to see if session matches post data
+ if ($validate) {
+ $order_info = $this->model_checkout_order->getOrder($order_id);
+
+ if ($order_info) {
+ // Unset $tax_rates and set them again using correct shipping data
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ // Check order_amount
+ if (round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_amount) {
+ $this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_amount does not match session order total. Klarna Request: ' . $request->order_amount . '. OpenCart: ' . round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100));
+ $this->model_extension_payment_klarna_checkout->log($order_info);
+ $this->model_extension_payment_klarna_checkout->log($this->cart->getTaxes());
+ $validate = false;
+ }
+
+ // Check order_tax_amount
+ if (round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_tax_amount) {
+ $this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_tax_amount does not match session tax total. Totals below:');
+ $this->model_extension_payment_klarna_checkout->log('Session taxes:');
+ $this->model_extension_payment_klarna_checkout->log(round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100));
+ $this->model_extension_payment_klarna_checkout->log('Request taxes:');
+ $this->model_extension_payment_klarna_checkout->log($request->order_tax_amount);
+ $validate = false;
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot find order using: ' . $order_id);
+ $validate = false;
+ }
+ }
+
+ // If validates, add customer's email (if guest checkout) and then send 200 response
+ if ($validate) {
+ if (!$this->customer->isLogged()) {
+ $this->model_extension_payment_klarna_checkout->updateOcOrderEmail($order_id, utf8_substr($request->shipping_address->email, 0, 96));
+ }
+
+ // Update OpenCart order with payment and shipping details
+ $payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->billing_address->country);
+ $shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
+
+ //If region is passed, try to update OpenCart order with correct region/zone
+ $payment_zone_info = array();
+ if ($payment_country_info && isset($request->billing_address->region)) {
+ $payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->billing_address->region, $payment_country_info['country_id']);
+ }
+
+ $shipping_zone_info = array();
+ if ($shipping_country_info && isset($request->shipping_address->region)) {
+ $shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $shipping_country_info['country_id']);
+ }
+
+ $order_data = array(
+ 'firstname' => utf8_substr($request->billing_address->given_name, 0, 32),
+ 'lastname' => utf8_substr($request->billing_address->family_name, 0, 32),
+ 'telephone' => utf8_substr($request->billing_address->phone, 0, 32),
+ 'payment_firstname' => utf8_substr($request->billing_address->given_name, 0, 32),
+ 'payment_lastname' => utf8_substr($request->billing_address->family_name, 0, 32),
+ 'payment_address_1' => utf8_substr($request->billing_address->street_address, 0, 128),
+ 'payment_address_2' => (isset($request->billing_address->street_address2) ? utf8_substr($request->billing_address->street_address2, 0, 128) : ''),
+ 'payment_city' => utf8_substr($request->billing_address->city, 0, 128),
+ 'payment_postcode' => utf8_substr($request->billing_address->postal_code, 0, 10),
+ 'payment_zone' => ($payment_zone_info ? $payment_zone_info['name'] : ''),
+ 'payment_zone_id' => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
+ 'payment_country' => ($payment_country_info ? $payment_country_info['name'] : ''),
+ 'payment_country_id' => ($payment_country_info ? $payment_country_info['country_id'] : ''),
+ 'payment_address_format' => ($payment_country_info ? $payment_country_info['address_format'] : ''),
+ 'shipping_firstname' => utf8_substr($request->shipping_address->given_name, 0, 32),
+ 'shipping_lastname' => utf8_substr($request->shipping_address->family_name, 0, 32),
+ 'shipping_address_1' => utf8_substr($request->shipping_address->street_address, 0, 128),
+ 'shipping_address_2' => (isset($request->shipping_address->street_address2) ? utf8_substr($request->shipping_address->street_address2, 0, 128) : ''),
+ 'shipping_city' => utf8_substr($request->shipping_address->city, 0, 128),
+ 'shipping_postcode' => utf8_substr($request->shipping_address->postal_code, 0, 10),
+ 'shipping_zone' => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
+ 'shipping_zone_id' => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
+ 'shipping_country' => ($shipping_country_info ? $shipping_country_info['name'] : ''),
+ 'shipping_country_id' => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
+ 'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
+ );
+
+ $this->model_extension_payment_klarna_checkout->updateOcOrder($order_id, $order_data);
+
+ $this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
+
+ http_response_code(200);
+ } else {
+ http_response_code(303);
+ $this->response->addHeader('Location: ' . $this->url->link('checkout/failure', '', true));
+ }
+
+ $this->response->addHeader('Content-Type: application/json');
+ $this->response->setOutput(json_encode($json));
+ }
+
+ public function confirmation() {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ if (isset($this->session->data['order_id'])) {
+ $this->cart->clear();
+
+ unset($this->session->data['shipping_method']);
+ unset($this->session->data['shipping_methods']);
+ unset($this->session->data['payment_method']);
+ unset($this->session->data['payment_methods']);
+ unset($this->session->data['guest']);
+ unset($this->session->data['comment']);
+ unset($this->session->data['order_id']);
+ unset($this->session->data['coupon']);
+ unset($this->session->data['reward']);
+ unset($this->session->data['voucher']);
+ unset($this->session->data['vouchers']);
+ unset($this->session->data['totals']);
+
+ unset($this->session->data['klarna_checkout_order_id']);
+ unset($this->session->data['klarna_checkout_data']);
+ }
+
+ $this->document->setTitle($this->language->get('heading_title_success'));
+
+ $data['breadcrumbs'] = array();
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_home'),
+ 'href' => $this->url->link('common/home')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_basket'),
+ 'href' => $this->url->link('checkout/cart')
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_checkout'),
+ 'href' => $this->url->link('checkout/checkout', '', true)
+ );
+
+ $data['breadcrumbs'][] = array(
+ 'text' => $this->language->get('text_success'),
+ 'href' => $this->url->link('checkout/success')
+ );
+
+ $data['continue'] = $this->url->link('common/home');
+
+ $data['column_left'] = $this->load->controller('common/column_left');
+ $data['column_right'] = $this->load->controller('common/column_right');
+ $data['content_top'] = $this->load->controller('common/content_top');
+ $data['content_bottom'] = $this->load->controller('common/content_bottom');
+ $data['footer'] = $this->load->controller('common/footer');
+ $data['header'] = $this->load->controller('common/header');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ $klarna_checkout = false;
+ $html_snippet = '';
+
+ if (isset($this->request->get['klarna_order_id'])) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if (!$klarna_account || !$connector) {
+ $this->model_extension_payment_klarna_checkout->log('Could not getConnector');
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ $retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->request->get['klarna_order_id']);
+
+ if ($retrieve) {
+ $klarna_checkout = $retrieve->fetch();
+
+ if ($klarna_checkout && $klarna_checkout['html_snippet']) {
+ $html_snippet = $klarna_checkout['html_snippet'];
+ }
+ } else {
+ $this->response->redirect($this->url->link('checkout/cart', '', true));
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $this->request->get['klarna_order_id']);
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('$this->request->get[\'klarna_order_id\'] is not set');
+ $this->response->redirect($this->url->link('checkout/failure', '', true));
+ }
+
+ $data['klarna_checkout'] = $html_snippet;
+
+ $this->response->setOutput($this->load->view('extension/payment/klarna_checkout_success', $data));
+ }
+
+ public function push() {
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('checkout/order');
+
+ if (!$this->config->get('klarna_checkout_status')) {
+ return false;
+ }
+
+ if (isset($this->request->get['klarna_order_id'])) {
+ $klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
+
+ if ($klarna_checkout_order) {
+ $order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
+
+ if ($order_info) {
+ list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
+
+ if ($klarna_account && $connector) {
+ $order = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $this->request->get['klarna_order_id']);
+
+ $this->model_extension_payment_klarna_checkout->log('Order details from push:');
+ $this->model_extension_payment_klarna_checkout->log($order);
+
+ if ($order) {
+ if ($order->acknowledge()) {
+ // Update OpenCart order with payment and shipping details
+ $payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['billing_address']['country']);
+ $shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['shipping_address']['country']);
+
+ //If region is passed, try to update OpenCart order with correct region/zone
+ $payment_zone_info = array();
+ if ($payment_country_info && isset($order['billing_address']['region'])) {
+ $payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['billing_address']['region'], $payment_country_info['country_id']);
+ }
+
+ $shipping_zone_info = array();
+ if ($shipping_country_info && isset($order['shipping_address']['region'])) {
+ $shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['shipping_address']['region'], $shipping_country_info['country_id']);
+ }
+
+ $order_data = array(
+ 'firstname' => utf8_substr($order['billing_address']['given_name'], 0, 32),
+ 'lastname' => utf8_substr($order['billing_address']['family_name'], 0, 32),
+ 'telephone' => utf8_substr($order['billing_address']['phone'], 0, 32),
+ 'payment_firstname' => utf8_substr($order['billing_address']['given_name'], 0, 32),
+ 'payment_lastname' => utf8_substr($order['billing_address']['family_name'], 0, 32),
+ 'payment_address_1' => utf8_substr($order['billing_address']['street_address'], 0, 128),
+ 'payment_address_2' => (isset($order['billing_address']['street_address2']) ? utf8_substr($order['billing_address']['street_address2'], 0, 128) : ''),
+ 'payment_city' => utf8_substr($order['billing_address']['city'], 0, 128),
+ 'payment_postcode' => utf8_substr($order['billing_address']['postal_code'], 0, 10),
+ 'payment_zone' => ($payment_zone_info ? $payment_zone_info['name'] : ''),
+ 'payment_zone_id' => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
+ 'payment_country' => ($payment_country_info ? $payment_country_info['name'] : ''),
+ 'payment_country_id' => ($payment_country_info ? $payment_country_info['country_id'] : ''),
+ 'payment_address_format' => ($payment_country_info ? $payment_country_info['address_format'] : ''),
+ 'shipping_firstname' => utf8_substr($order['shipping_address']['given_name'], 0, 32),
+ 'shipping_lastname' => utf8_substr($order['shipping_address']['family_name'], 0, 32),
+ 'shipping_address_1' => utf8_substr($order['shipping_address']['street_address'], 0, 128),
+ 'shipping_address_2' => (isset($order['shipping_address']['street_address2']) ? utf8_substr($order['shipping_address']['street_address2'], 0, 128) : ''),
+ 'shipping_city' => utf8_substr($order['shipping_address']['city'], 0, 128),
+ 'shipping_postcode' => utf8_substr($order['shipping_address']['postal_code'], 0, 10),
+ 'shipping_zone' => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
+ 'shipping_zone_id' => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
+ 'shipping_country' => ($shipping_country_info ? $shipping_country_info['name'] : ''),
+ 'shipping_country_id' => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
+ 'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
+ );
+
+ $this->model_extension_payment_klarna_checkout->updateOcOrder($klarna_checkout_order['order_id'], $order_data);
+
+ $order_status_id = false;
+ switch ($order['status']) {
+ case 'AUTHORIZED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_authorised_id');
+
+ if ($order['fraud_status'] == 'PENDING') {
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_pending_id');
+ } elseif ($order['fraud_status'] == 'REJECTED') {
+ $order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
+ }
+ break;
+ case 'PART_CAPTURED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_part_captured_id');
+ break;
+ case 'CAPTURED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_captured_id');
+ break;
+ case 'CANCELLED':
+ $order_status_id = $this->config->get('klarna_checkout_order_status_cancelled_id');
+ break;
+ }
+
+ if ($order_status_id) {
+ $this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot retrieve KC order using order_id: ' . $this->request->get['klarna_order_id']);
+ }
+ }
+ }
+ } else {
+ $this->model_extension_payment_klarna_checkout->log('Cannot find KC order using order_id: ' . $this->request->get['klarna_order_id']);
+ }
+ }
+ }
+
+ private function setPayment() {
+ $this->load->model('account/address');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ if (isset($this->session->data['payment_address']) && !empty($this->session->data['payment_address'])) {
+ $this->session->data['payment_address'] = $this->session->data['payment_address'];
+ } elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
+ $this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ } else {
+ $country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
+
+ $zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
+
+ $this->session->data['payment_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => $zone_info['zone_id'],
+ 'zone' => $zone_info['name'],
+ 'zone_code' => $zone_info['code'],
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+ }
+
+ $this->tax->setPaymentAddress($this->session->data['payment_address']['country_id'], $this->session->data['payment_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+ }
+
+ private function setShipping() {
+ $this->load->model('account/address');
+ $this->load->model('localisation/country');
+ $this->load->model('localisation/zone');
+
+ if (isset($this->session->data['shipping_address']) && !empty($this->session->data['shipping_address'])) {
+ $this->session->data['shipping_address'] = $this->session->data['shipping_address'];
+ } elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
+ $this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
+ } else {
+ $country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
+
+ $zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
+
+ $this->session->data['shipping_address'] = array(
+ 'address_id' => null,
+ 'firstname' => null,
+ 'lastname' => null,
+ 'company' => null,
+ 'address_1' => null,
+ 'address_2' => null,
+ 'postcode' => null,
+ 'city' => null,
+ 'zone_id' => $zone_info['zone_id'],
+ 'zone' => $zone_info['name'],
+ 'zone_code' => $zone_info['code'],
+ 'country_id' => $country_info['country_id'],
+ 'country' => $country_info['name'],
+ 'iso_code_2' => $country_info['iso_code_2'],
+ 'iso_code_3' => $country_info['iso_code_3'],
+ 'address_format' => '',
+ 'custom_field' => array()
+ );
+ }
+
+ $this->tax->unsetRates();
+ $this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
+ $this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
+
+ if (isset($this->session->data['shipping_address'])) {
+ // Shipping Methods
+ $method_data = array();
+
+ $this->load->model('setting/extension');
+
+ $results = $this->model_setting_extension->getExtensions('shipping');
+
+ foreach ($results as $result) {
+ if ($this->config->get('shipping_' . $result['code'] . '_status')) {
+ $this->load->model('extension/shipping/' . $result['code']);
+
+ $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
+
+ if ($quote) {
+ $method_data[$result['code']] = array(
+ 'title' => $quote['title'],
+ 'quote' => $quote['quote'],
+ 'sort_order' => $quote['sort_order'],
+ 'error' => $quote['error']
+ );
+ }
+ }
+ }
+
+ $sort_order = array();
+
+ foreach ($method_data as $key => $value) {
+ $sort_order[$key] = $value['sort_order'];
+ }
+
+ array_multisort($sort_order, SORT_ASC, $method_data);
+
+ $this->session->data['shipping_methods'] = $method_data;
+ }
+ }
+
+ private function createOrder() {
+ //Klarna defaults:
+ $this->session->data['comment'] = '';
+
+ if (!$this->customer->isLogged()) {
+ $this->session->data['guest'] = array(
+ 'customer_group_id' => $this->config->get('config_customer_group_id'),
+ 'firstname' => '',
+ 'lastname' => '',
+ 'email' => '',
+ 'telephone' => '',
+ 'fax' => '',
+ 'custom_field' => array(),
+ );
+ }
+
+ //OpenCart:
+ $order_data = array();
+
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ $order_data['totals'] = $totals;
+
+ $this->load->language('checkout/checkout');
+
+ $order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
+ $order_data['store_id'] = $this->config->get('config_store_id');
+ $order_data['store_name'] = $this->config->get('config_name');
+
+ if ($order_data['store_id']) {
+ $order_data['store_url'] = $this->config->get('config_url');
+ } else {
+ $order_data['store_url'] = HTTP_SERVER;
+ }
+
+ if ($this->customer->isLogged()) {
+ $this->load->model('account/customer');
+
+ $customer_info = $this->model_account_customer->getCustomer($this->customer->getId());
+
+ $order_data['customer_id'] = $this->customer->getId();
+ $order_data['customer_group_id'] = $customer_info['customer_group_id'];
+ $order_data['firstname'] = $customer_info['firstname'];
+ $order_data['lastname'] = $customer_info['lastname'];
+ $order_data['email'] = $customer_info['email'];
+ $order_data['telephone'] = $customer_info['telephone'];
+ $order_data['custom_field'] = json_decode($customer_info['custom_field'], true);
+ } elseif (isset($this->session->data['guest'])) {
+ $order_data['customer_id'] = 0;
+ $order_data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
+ $order_data['firstname'] = $this->session->data['guest']['firstname'];
+ $order_data['lastname'] = $this->session->data['guest']['lastname'];
+ $order_data['email'] = $this->session->data['guest']['email'];
+ $order_data['telephone'] = $this->session->data['guest']['telephone'];
+ $order_data['custom_field'] = $this->session->data['guest']['custom_field'];
+ }
+
+ $order_data['payment_firstname'] = $this->session->data['payment_address']['firstname'];
+ $order_data['payment_lastname'] = $this->session->data['payment_address']['lastname'];
+ $order_data['payment_company'] = $this->session->data['payment_address']['company'];
+ $order_data['payment_address_1'] = $this->session->data['payment_address']['address_1'];
+ $order_data['payment_address_2'] = $this->session->data['payment_address']['address_2'];
+ $order_data['payment_city'] = $this->session->data['payment_address']['city'];
+ $order_data['payment_postcode'] = $this->session->data['payment_address']['postcode'];
+ $order_data['payment_zone'] = $this->session->data['payment_address']['zone'];
+ $order_data['payment_zone_id'] = $this->session->data['payment_address']['zone_id'];
+ $order_data['payment_country'] = $this->session->data['payment_address']['country'];
+ $order_data['payment_country_id'] = $this->session->data['payment_address']['country_id'];
+ $order_data['payment_address_format'] = $this->session->data['payment_address']['address_format'];
+ $order_data['payment_custom_field'] = (isset($this->session->data['payment_address']['custom_field']) ? $this->session->data['payment_address']['custom_field'] : array());
+
+ if (isset($this->session->data['payment_method']['title'])) {
+ $order_data['payment_method'] = $this->session->data['payment_method']['title'];
+ } else {
+ $order_data['payment_method'] = '';
+ }
+
+ if (isset($this->session->data['payment_method']['code'])) {
+ $order_data['payment_code'] = $this->session->data['payment_method']['code'];
+ } else {
+ $order_data['payment_code'] = '';
+ }
+
+ if ($this->cart->hasShipping()) {
+ $order_data['shipping_firstname'] = $this->session->data['shipping_address']['firstname'];
+ $order_data['shipping_lastname'] = $this->session->data['shipping_address']['lastname'];
+ $order_data['shipping_company'] = $this->session->data['shipping_address']['company'];
+ $order_data['shipping_address_1'] = $this->session->data['shipping_address']['address_1'];
+ $order_data['shipping_address_2'] = $this->session->data['shipping_address']['address_2'];
+ $order_data['shipping_city'] = $this->session->data['shipping_address']['city'];
+ $order_data['shipping_postcode'] = $this->session->data['shipping_address']['postcode'];
+ $order_data['shipping_zone'] = $this->session->data['shipping_address']['zone'];
+ $order_data['shipping_zone_id'] = $this->session->data['shipping_address']['zone_id'];
+ $order_data['shipping_country'] = $this->session->data['shipping_address']['country'];
+ $order_data['shipping_country_id'] = $this->session->data['shipping_address']['country_id'];
+ $order_data['shipping_address_format'] = $this->session->data['shipping_address']['address_format'];
+ $order_data['shipping_custom_field'] = (isset($this->session->data['shipping_address']['custom_field']) ? $this->session->data['shipping_address']['custom_field'] : array());
+
+ if (isset($this->session->data['shipping_method']['title'])) {
+ $order_data['shipping_method'] = $this->session->data['shipping_method']['title'];
+ } else {
+ $order_data['shipping_method'] = '';
+ }
+
+ if (isset($this->session->data['shipping_method']['code'])) {
+ $order_data['shipping_code'] = $this->session->data['shipping_method']['code'];
+ } else {
+ $order_data['shipping_code'] = '';
+ }
+ } else {
+ $order_data['shipping_firstname'] = '';
+ $order_data['shipping_lastname'] = '';
+ $order_data['shipping_company'] = '';
+ $order_data['shipping_address_1'] = '';
+ $order_data['shipping_address_2'] = '';
+ $order_data['shipping_city'] = '';
+ $order_data['shipping_postcode'] = '';
+ $order_data['shipping_zone'] = '';
+ $order_data['shipping_zone_id'] = '';
+ $order_data['shipping_country'] = '';
+ $order_data['shipping_country_id'] = '';
+ $order_data['shipping_address_format'] = '';
+ $order_data['shipping_custom_field'] = array();
+ $order_data['shipping_method'] = '';
+ $order_data['shipping_code'] = '';
+ }
+
+ $order_data['products'] = array();
+
+ foreach ($this->cart->getProducts() as $product) {
+ $option_data = array();
+
+ foreach ($product['option'] as $option) {
+ $option_data[] = array(
+ 'product_option_id' => $option['product_option_id'],
+ 'product_option_value_id' => $option['product_option_value_id'],
+ 'option_id' => $option['option_id'],
+ 'option_value_id' => $option['option_value_id'],
+ 'name' => $option['name'],
+ 'value' => $option['value'],
+ 'type' => $option['type']
+ );
+ }
+
+ $order_data['products'][] = array(
+ 'product_id' => $product['product_id'],
+ 'name' => $product['name'],
+ 'model' => $product['model'],
+ 'option' => $option_data,
+ 'download' => $product['download'],
+ 'quantity' => $product['quantity'],
+ 'subtract' => $product['subtract'],
+ 'price' => $product['price'],
+ 'total' => $product['total'],
+ 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
+ 'reward' => $product['reward']
+ );
+ }
+
+ // Gift Voucher
+ $order_data['vouchers'] = array();
+
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $voucher) {
+ $order_data['vouchers'][] = array(
+ 'description' => $voucher['description'],
+ 'code' => token(10),
+ 'to_name' => $voucher['to_name'],
+ 'to_email' => $voucher['to_email'],
+ 'from_name' => $voucher['from_name'],
+ 'from_email' => $voucher['from_email'],
+ 'voucher_theme_id' => $voucher['voucher_theme_id'],
+ 'message' => $voucher['message'],
+ 'amount' => $voucher['amount']
+ );
+ }
+ }
+
+ $order_data['comment'] = $this->session->data['comment'];
+ $order_data['total'] = $total;
+
+ if (isset($this->request->cookie['tracking'])) {
+ $order_data['tracking'] = $this->request->cookie['tracking'];
+
+ $subtotal = $this->cart->getSubTotal();
+
+ // Affiliate
+ $this->load->model('affiliate/affiliate');
+
+ $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
+
+ if ($affiliate_info) {
+ $order_data['affiliate_id'] = $affiliate_info['affiliate_id'];
+ $order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ }
+
+ // Marketing
+ $this->load->model('checkout/marketing');
+
+ $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
+
+ if ($marketing_info) {
+ $order_data['marketing_id'] = $marketing_info['marketing_id'];
+ } else {
+ $order_data['marketing_id'] = 0;
+ }
+ } else {
+ $order_data['affiliate_id'] = 0;
+ $order_data['commission'] = 0;
+ $order_data['marketing_id'] = 0;
+ $order_data['tracking'] = '';
+ }
+
+ $order_data['language_id'] = $this->config->get('config_language_id');
+ $order_data['currency_id'] = $this->currency->getId($this->session->data['currency']);
+ $order_data['currency_code'] = $this->session->data['currency'];
+ $order_data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
+ $order_data['ip'] = $this->request->server['REMOTE_ADDR'];
+
+ if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
+ } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
+ $order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
+ } else {
+ $order_data['forwarded_ip'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_USER_AGENT'])) {
+ $order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
+ } else {
+ $order_data['user_agent'] = '';
+ }
+
+ if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
+ $order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
+ } else {
+ $order_data['accept_language'] = '';
+ }
+
+ $this->load->model('checkout/order');
+
+ $this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
+ }
+
+ private function klarnaOrderData($klarna_account) {
+ $this->load->language('extension/payment/klarna_checkout');
+
+ $this->load->model('extension/payment/klarna_checkout');
+ $this->load->model('localisation/country');
+
+ $currency_code = $this->session->data['currency'];
+ $currency_value = $this->currency->getValue($this->session->data['currency']);
+
+ // Shipping
+ $unset_shipping_method = true;
+ if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
+ foreach ($this->session->data['shipping_methods'] as $shipping_method) {
+ if ($shipping_method['quote']) {
+ foreach ($shipping_method['quote'] as $quote) {
+ if ($quote == $this->session->data['shipping_method']) {
+ $unset_shipping_method = false;
+ break 2;
+ }
+ }
+ }
+ }
+ }
+
+ if ($unset_shipping_method) {
+ unset($this->session->data['shipping_method']);
+ }
+
+ if ((!isset($this->session->data['shipping_method']) || empty($this->session->data['shipping_method'])) && (isset($this->session->data['shipping_methods']) && !empty($this->session->data['shipping_methods']))) {
+ $this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
+ }
+
+ //Check if customer is US. If so, send taxes differently
+ if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
+ $include_taxes = false;
+ } else {
+ $include_taxes = true;
+ }
+
+ if ($this->cart->hasShipping() && isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
+ $total_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id']), $currency_code, $currency_value, false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], false), $currency_code, $currency_value, false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'shipping_fee',
+ 'name' => $this->session->data['shipping_method']['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ // Billing Address
+ if (isset($this->session->data['klarna_checkout_data'])) {
+ $klarna_order_data['billing_address'] = array(
+ 'given_name' => $this->session->data['klarna_checkout_data']['firstname'],
+ 'family_name' => $this->session->data['klarna_checkout_data']['lastname'],
+ 'email' => $this->session->data['klarna_checkout_data']['email'],
+ 'phone' => $this->session->data['klarna_checkout_data']['telephone'],
+ 'postal_code' => $this->session->data['shipping_address']['postcode'],
+ 'region' => $this->session->data['shipping_address']['zone_code'],
+ 'country' => $this->session->data['shipping_address']['iso_code_2'],
+ );
+ } else {
+ $klarna_order_data['billing_address'] = array(
+ 'given_name' => $this->session->data['shipping_address']['firstname'],
+ 'family_name' => $this->session->data['shipping_address']['lastname'],
+ 'email' => ($this->customer->isLogged() ? $this->customer->getEmail() : null),
+ 'phone' => ($this->customer->isLogged() ? $this->customer->getTelephone() : null)
+ );
+ }
+
+ // Order Total
+ list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
+
+ $merchant_urls = array(
+ 'checkout' => html_entity_decode($this->url->link('extension/payment/klarna_checkout', 'klarna_order_id={checkout.order.id}', true)),
+ 'confirmation' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/confirmation', 'klarna_order_id={checkout.order.id}', true)),
+ 'push' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/push', 'klarna_order_id={checkout.order.id}', true)),
+ 'validation' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/validation', 'klarna_order_id={checkout.order.id}', true)),
+ 'address_update' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/addressUpdate', 'klarna_order_id={checkout.order.id}', true)),
+ 'notification' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/notification', 'klarna_order_id={checkout.order.id}', true)),
+ );
+
+ if ($this->config->get('klarna_checkout_terms')) {
+ $merchant_urls['terms'] = html_entity_decode($this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true));
+ }
+
+ $country_info = $this->model_localisation_country->getCountry($klarna_account['country']);
+
+ if ($country_info) {
+ $klarna_order_data['purchase_country'] = $country_info['iso_code_2'];
+ }
+
+ $klarna_order_data['purchase_currency'] = $currency_code;
+ $klarna_order_data['locale'] = $klarna_account['locale'];
+
+ $klarna_order_data['order_amount'] = round($this->currency->format($total, $currency_code, $currency_value, false) * 100);
+ $klarna_order_data['order_tax_amount'] = round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100);
+
+ $klarna_order_data['merchant_urls'] = $merchant_urls;
+
+ // Callback data to be used to spoof/simulate customer to accurately calculate shipping
+ $encrypted_order_data = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode(array(
+ 'session_id' => session_id(),
+ 'session_key' => $this->session->getId(),
+ 'customer_id' => $this->customer->getId(),
+ 'order_id' => $this->session->data['order_id'],
+ 'merchant_id' => $klarna_account['merchant_id'],
+ 'secret' => $klarna_account['secret']
+ )));
+
+ $encrypted_order_id = $this->encryption->encrypt($this->config->get('config_encryption'), $this->session->data['order_id']);
+
+ $klarna_order_data['merchant_reference1'] = $this->session->data['order_id'];
+
+ $klarna_order_data['options'] = array();
+
+ if ($this->config->get('klarna_checkout_colour_button')) {
+ $klarna_order_data['options']['color_button'] = $this->config->get('klarna_checkout_colour_button');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_button_text')) {
+ $klarna_order_data['options']['color_button_text'] = $this->config->get('klarna_checkout_colour_button_text');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_checkbox')) {
+ $klarna_order_data['options']['color_checkbox'] = $this->config->get('klarna_checkout_colour_checkbox');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_checkbox_checkmark')) {
+ $klarna_order_data['options']['color_checkbox_checkmark'] = $this->config->get('klarna_checkout_colour_checkbox_checkmark');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_header')) {
+ $klarna_order_data['options']['color_header'] = $this->config->get('klarna_checkout_colour_header');
+ }
+
+ if ($this->config->get('klarna_checkout_colour_link')) {
+ $klarna_order_data['options']['color_link'] = $this->config->get('klarna_checkout_colour_link');
+ }
+
+ if ($this->config->get('klarna_checkout_separate_shipping_address')) {
+ $klarna_order_data['options']['allow_separate_shipping_address'] = true;
+ }
+
+ // Only pass DOB/title mandatory for UK stores
+ if ($country_info['iso_code_2'] == 'GB') {
+ if ($this->config->get('klarna_checkout_dob_mandatory')) {
+ $klarna_order_data['options']['date_of_birth_mandatory'] = true;
+ }
+
+ if ($this->config->get('klarna_checkout_title_mandatory')) {
+ $klarna_order_data['options']['title_mandatory'] = true;
+ }
+ }
+
+ if ($this->config->get('klarna_checkout_additional_text_box') && $this->customer->isLogged() && !$this->customer->getNewsletter()) {
+ $klarna_order_data['options']['additional_checkbox'] = array(
+ 'text' => $this->language->get('text_newsletter'),
+ 'checked' => false,
+ 'required' => false
+ );
+ }
+
+ $shipping_countries = $this->model_extension_payment_klarna_checkout->getCountriesByGeoZone($klarna_account['shipping']);
+
+ $klarna_shipping_countries = array();
+ foreach ($shipping_countries as $shipping_country) {
+ $country_info = $this->model_localisation_country->getCountry($shipping_country['country_id']);
+
+ if ($country_info && $country_info['iso_code_2']) {
+ $klarna_shipping_countries[] = $country_info['iso_code_2'];
+ }
+ }
+
+ $klarna_order_data['shipping_countries'] = $klarna_shipping_countries;
+
+ $average_product_tax_rate = array();
+
+ // Products (Add these last because we send encrypted session order_id)
+ foreach ($this->cart->getProducts() as $product) {
+ $total_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+
+ if ($include_taxes) {
+ $total_tax_amount = $this->currency->format($this->tax->getTax($product['price'], $product['tax_class_id']) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+ } else {
+ $total_tax_amount = 0;
+ }
+
+ $total_sub_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], false) * $product['quantity'], $currency_code, $currency_value, false) * 100;
+
+ $tax_rate = 0;
+
+ if ($include_taxes && $total_tax_amount && $total_sub_amount) {
+ $tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
+ }
+
+ $average_product_tax_rate[] = round($tax_rate * 100);
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => ($product['shipping'] ? 'physical' : 'digital'),
+ 'reference' => $product['model'],
+ 'name' => $product['name'],
+ 'quantity' => $product['quantity'],
+ 'quantity_unit' => 'pcs',
+ 'unit_price' => round($this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => round($tax_rate * 100),
+ 'total_amount' => round($total_amount),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'merchant_data' => $encrypted_order_id,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ // Gift Voucher
+ if (!empty($this->session->data['vouchers'])) {
+ foreach ($this->session->data['vouchers'] as $key => $voucher) {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'gift_card',
+ 'reference' => '',
+ 'name' => $voucher['description'],
+ 'quantity' => 1,
+ 'quantity_unit' => 'pcs',
+ 'unit_price' => round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'merchant_data' => $encrypted_order_id,
+ 'total_discount_amount' => 0
+ );
+ }
+ }
+
+ foreach ($totals as $result) {
+ if ($result['code'] == 'coupon') {
+ $discount_total_price = 0;
+ $discount_sub_total_price = 0;
+ foreach ($this->cart->getProducts() as $product) {
+ $discount_total_price += $this->tax->calculate($result['value'], $product['tax_class_id'], $include_taxes);
+ $discount_sub_total_price += $result['value'];
+ }
+
+ $average_discount_total_price = $discount_total_price / count($average_product_tax_rate);
+
+ $average_discount_sub_total_price = $discount_sub_total_price / count($average_product_tax_rate);
+
+ $total_tax_amount = ($average_discount_sub_total_price / 100) * (array_sum($average_product_tax_rate) / count($average_product_tax_rate));
+
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'discount',
+ 'name' => $result['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => array_sum($average_product_tax_rate) / count($average_product_tax_rate),
+ 'total_amount' => round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => round($total_tax_amount),
+ 'total_discount_amount' => 0
+ );
+ }
+
+ if ($result['code'] == 'voucher') {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'discount',
+ 'name' => $result['title'],
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+ }
+
+ //If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
+ if (!$include_taxes) {
+ $klarna_order_data['order_lines'][] = array(
+ 'type' => 'sales_tax',
+ 'name' => $this->language->get('text_sales_tax'),
+ 'quantity' => '1',
+ 'unit_price' => round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
+ 'tax_rate' => 0,
+ 'total_amount' => round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
+ 'total_tax_amount' => 0,
+ 'total_discount_amount' => 0
+ );
+ }
+
+ return array($klarna_order_data, $encrypted_order_data);
+ }
+}