shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

klarna_checkout.php (84456B)


      1 <?php
      2 class ControllerExtensionPaymentKlarnaCheckout extends Controller {
      3 	public function index() {
      4 		$this->load->language('extension/payment/klarna_checkout');
      5 
      6 		$this->load->model('extension/payment/klarna_checkout');
      7 		$this->load->model('localisation/country');
      8 
      9 		$this->document->setTitle($this->language->get('heading_title'));
     10 
     11 		$data['column_left'] = $this->load->controller('common/column_left');
     12 		$data['column_right'] = $this->load->controller('common/column_right');
     13 		$data['content_top'] = $this->load->controller('common/content_top');
     14 		$data['content_bottom'] = $this->load->controller('common/content_bottom');
     15 		$data['footer'] = $this->load->controller('common/footer');
     16 		$data['header'] = $this->load->controller('common/header');
     17 
     18 		$this->response->setOutput($this->load->view('extension/payment/klarna_checkout', $data));
     19 	}
     20 
     21 	public function main() {
     22 		$this->load->language('extension/payment/klarna_checkout');
     23 
     24 		$this->load->model('extension/payment/klarna_checkout');
     25 		$this->load->model('localisation/country');
     26 
     27 		$redirect = false;
     28 		$html_snippet = '';
     29 
     30 		// Validate cart has products and has stock.
     31 		if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
     32 			$redirect = $this->url->link('checkout/cart');
     33 		}
     34 
     35 		// Validate minimum quantity requirements.
     36 		$products = $this->cart->getProducts();
     37 
     38 		foreach ($products as $product) {
     39 			$product_total = 0;
     40 
     41 			foreach ($products as $product_2) {
     42 				if ($product_2['product_id'] == $product['product_id']) {
     43 					$product_total += $product_2['quantity'];
     44 				}
     45 			}
     46 
     47 			if ($product['minimum'] > $product_total) {
     48 				$redirect = $this->url->link('checkout/cart');
     49 			}
     50 		}
     51 
     52 		// Validate cart has recurring products
     53 		if ($this->cart->hasRecurringProducts()) {
     54 			$redirect = $this->url->link('checkout/cart');
     55 		}
     56 
     57 		list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
     58 
     59 		if ($this->config->get('klarna_checkout_total') > 0 && $this->config->get('klarna_checkout_total') > $total) {
     60 			$redirect = $this->url->link('checkout/cart');
     61 		}
     62 
     63 		if (!$this->config->get('klarna_checkout_status')) {
     64 			$redirect = $this->url->link('checkout/cart');
     65 		}
     66 
     67 		if ($this->model_extension_payment_klarna_checkout->checkForPaymentTaxes($products)) {
     68 			$redirect = $this->url->link('checkout/cart');
     69 		}
     70 
     71 		$text_title = $this->language->get('text_title');
     72 
     73 		unset($this->session->data['success']);
     74 
     75 		$this->setPayment();
     76 		$this->setShipping();
     77 
     78 		$this->session->data['payment_method'] = array(
     79 			'code'       => 'klarna_checkout',
     80 			'title'      => $text_title,
     81 			'terms'      => $this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true),
     82 			'sort_order' => '1'
     83 		);
     84 
     85 		// Shipping
     86 		$unset_shipping_method = true;
     87 		if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
     88 			foreach ($this->session->data['shipping_methods'] as $shipping_method) {
     89 				if ($shipping_method['quote']) {
     90 					foreach ($shipping_method['quote'] as $quote) {
     91 						if ($quote['code'] == $this->session->data['shipping_method']['code']) {
     92 							$unset_shipping_method = false;
     93 							break 2;
     94 						}
     95 					}
     96 				}
     97 			}
     98 		}
     99 
    100 		if ($unset_shipping_method) {
    101 			unset($this->session->data['shipping_method']);
    102 		}
    103 
    104 		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']))) {
    105 			$this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
    106 		}
    107 
    108 		//Klarna Connector
    109 		list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
    110 
    111 		if (!$klarna_account || !$connector) {
    112 			$redirect = $this->url->link('checkout/cart');
    113 		}
    114 
    115 		if (!$redirect) {
    116 			// Get currency code and currency value to use to calculate taxes
    117 
    118 			// Build order_lines
    119 			$create_order = true;
    120 			$klarna_checkout = false;
    121 
    122 			$this->createOrder();
    123 
    124 			list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
    125 
    126 			if (isset($this->session->data['klarna_checkout_currency']) && $this->session->data['klarna_checkout_currency'] != $this->session->data['currency']) {
    127 				$this->model_extension_payment_klarna_checkout->log('Currency changed, unsetting kc order id');
    128 				unset($this->session->data['klarna_checkout_order_id']);
    129 				unset($this->session->data['klarna_checkout_data']);
    130 			}
    131 
    132 			$this->session->data['klarna_checkout_currency'] = $this->session->data['currency'];
    133 
    134 			// Fetch or create order
    135 			if (isset($this->session->data['klarna_checkout_order_id'])) {
    136 				$retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->session->data['klarna_checkout_order_id']);
    137 
    138 				if ($retrieve) {
    139 					//If address has changed, unset klarna_checkout_order_id and create new order
    140 					$address_change = false;
    141 
    142 					if (isset($this->session->data['klarna_checkout_data']) && $this->session->data['klarna_checkout_data']) {
    143 						if (isset($this->session->data['klarna_checkout_data']['zone_code'])) {
    144 							$kc_region = $this->session->data['klarna_checkout_data']['zone_code'];
    145 						} else {
    146 							$kc_region = '';
    147 						}
    148 
    149 						if (isset($this->session->data['klarna_checkout_data']['iso_code_2'])) {
    150 							$kc_country = $this->session->data['klarna_checkout_data']['iso_code_2'];
    151 						} else {
    152 							$kc_country = '';
    153 						}
    154 
    155 						if (isset($this->session->data['shipping_address']['zone_code'])) {
    156 							$oc_region = $this->session->data['shipping_address']['zone_code'];
    157 						} else {
    158 							$oc_region = '';
    159 						}
    160 
    161 						if (isset($this->session->data['shipping_address']['iso_code_2'])) {
    162 							$oc_country = $this->session->data['shipping_address']['iso_code_2'];
    163 						} else {
    164 							$oc_country = '';
    165 						}
    166 
    167 						$kc_address = array(
    168 							'region'  => $kc_region,
    169 							'country' => $kc_country,
    170 						);
    171 
    172 						$oc_address = array(
    173 							'region'  => $oc_region,
    174 							'country' => $oc_country,
    175 						);
    176 
    177 						//If address has changed, dont use retrieved order, create new one instead
    178 						if (array_diff(array_map('strtolower', $kc_address), array_map('strtolower', $oc_address))) {
    179 							$address_change = true;
    180 						}
    181 					}
    182 
    183 					if (!$address_change) {
    184                         $this->model_extension_payment_klarna_checkout->log('Order Updated');
    185                         $this->model_extension_payment_klarna_checkout->log($klarna_order_data);
    186 
    187 						$create_order = false;
    188 
    189 						$update = $this->model_extension_payment_klarna_checkout->orderUpdate($connector, $this->session->data['klarna_checkout_order_id'], $klarna_order_data);
    190 
    191 						if ($update) {
    192 							$klarna_checkout = $update->fetch();
    193 
    194 							$this->model_extension_payment_klarna_checkout->updateOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
    195 						}
    196 					}
    197 				}
    198 			}
    199 
    200 			if ($create_order) {
    201 				$this->model_extension_payment_klarna_checkout->log('Order Created');
    202 				$this->model_extension_payment_klarna_checkout->log($klarna_order_data);
    203 
    204 				unset($this->session->data['klarna_checkout_data']);
    205 
    206 				$create = $this->model_extension_payment_klarna_checkout->orderCreate($connector, $klarna_order_data);
    207 
    208 				if ($create) {
    209 					$klarna_checkout = $create->fetch();
    210 
    211 					$this->model_extension_payment_klarna_checkout->addOrder($this->session->data['order_id'], $klarna_checkout['order_id'], $encrypted_order_data);
    212 				}
    213 			}
    214 
    215 			if ($klarna_checkout) {
    216 				$this->session->data['klarna_checkout_order_id'] = $klarna_checkout['order_id'];
    217 
    218 				$html_snippet = $klarna_checkout['html_snippet'];
    219 			}
    220 		}
    221 
    222 		if (isset($this->request->post['response']) && $this->request->post['response'] == 'template') {
    223 			$data['redirect'] = $redirect;
    224 
    225 			$data['klarna_checkout'] = $html_snippet;
    226 
    227 			$this->response->setOutput($this->load->view('extension/payment/klarna_checkout_main', $data));
    228 		} elseif (isset($this->request->post['response']) && $this->request->post['response'] == 'json') {
    229 			$json['redirect'] = $redirect;
    230 
    231 			$this->response->addHeader('Content-Type: application/json');
    232 			$this->response->setOutput(json_encode($json));
    233 		}
    234 	}
    235 
    236 	public function sidebar() {
    237 		$this->load->language('checkout/checkout');
    238 		$this->load->language('extension/payment/klarna_checkout');
    239 
    240 		$this->load->model('extension/payment/klarna_checkout');
    241 
    242 		if (!$this->config->get('klarna_checkout_status')) {
    243 			return false;
    244 		}
    245 
    246 		$this->setPayment();
    247 		$this->setShipping();
    248 
    249 		// Shipping
    250 		$unset_shipping_method = true;
    251 		if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
    252 			foreach ($this->session->data['shipping_methods'] as $shipping_method) {
    253 				if ($shipping_method['quote']) {
    254 					foreach ($shipping_method['quote'] as $quote) {
    255 						if ($quote['code'] == $this->session->data['shipping_method']['code']) {
    256 							$unset_shipping_method = false;
    257 							break 2;
    258 						}
    259 					}
    260 				}
    261 			}
    262 		}
    263 
    264 		if ($unset_shipping_method) {
    265 			unset($this->session->data['shipping_method']);
    266 		}
    267 
    268 		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']))) {
    269 			$this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
    270 		}
    271 
    272 		$data['shipping_required'] = $this->cart->hasShipping();
    273 
    274 		if (isset($this->session->data['shipping_methods'])) {
    275 			$data['shipping_methods'] = $this->session->data['shipping_methods'];
    276 		} else {
    277 			unset($data['shipping_method']);
    278 
    279 			$data['shipping_methods'] = array();
    280 		}
    281 
    282 		if (isset($this->session->data['shipping_method']['code'])) {
    283 			$data['code'] = $this->session->data['shipping_method']['code'];
    284 		} else {
    285 			$data['code'] = '';
    286 		}
    287 
    288 		$this->load->model('tool/image');
    289 		$this->load->model('tool/upload');
    290 
    291 		$data['products'] = array();
    292 
    293 		foreach ($this->cart->getProducts() as $product) {
    294 			if ($product['image']) {
    295 				$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'));
    296 			} else {
    297 				$image = '';
    298 			}
    299 
    300 			$option_data = array();
    301 
    302 			foreach ($product['option'] as $option) {
    303 				if ($option['type'] != 'file') {
    304 					$value = $option['value'];
    305 				} else {
    306 					$upload_info = $this->model_tool_upload->getUploadByCode($option['value']);
    307 
    308 					if ($upload_info) {
    309 						$value = $upload_info['name'];
    310 					} else {
    311 						$value = '';
    312 					}
    313 				}
    314 
    315 				$option_data[] = array(
    316 					'name'  => $option['name'],
    317 					'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value),
    318 					'type'  => $option['type']
    319 				);
    320 			}
    321 
    322 			// Display prices
    323 			if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
    324 				$price = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']);
    325 			} else {
    326 				$price = false;
    327 			}
    328 
    329 			// Display prices
    330 			if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
    331 				$total = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')) * $product['quantity'], $this->session->data['currency']);
    332 			} else {
    333 				$total = false;
    334 			}
    335 
    336 			$data['products'][] = array(
    337 				'cart_id'   => $product['cart_id'],
    338 				'thumb'     => $image,
    339 				'name'      => $product['name'],
    340 				'model'     => $product['model'],
    341 				'option'    => $option_data,
    342 				'recurring' => ($product['recurring'] ? $product['recurring']['name'] : ''),
    343 				'quantity'  => $product['quantity'],
    344 				'price'     => $price,
    345 				'total'     => $total,
    346 				'href'      => $this->url->link('product/product', 'product_id=' . $product['product_id'])
    347 			);
    348 		}
    349 
    350 		// Gift Voucher
    351 		$data['vouchers'] = array();
    352 
    353 		if (!empty($this->session->data['vouchers'])) {
    354 			foreach ($this->session->data['vouchers'] as $key => $voucher) {
    355 				$data['vouchers'][] = array(
    356 					'key'         => $key,
    357 					'description' => $voucher['description'],
    358 					'amount'      => $this->currency->format($voucher['amount'], $this->session->data['currency'])
    359 				);
    360 			}
    361 		}
    362 
    363 		$totals = array();
    364 		$taxes = $this->cart->getTaxes();
    365 		$total = 0;
    366 
    367 		// Because __call can not keep var references so we put them into an array.
    368 		$total_data = array(
    369 			'totals' => &$totals,
    370 			'taxes'  => &$taxes,
    371 			'total'  => &$total
    372 		);
    373 
    374 		$this->load->model('setting/extension');
    375 
    376 		$sort_order = array();
    377 
    378 		$results = $this->model_setting_extension->getExtensions('total');
    379 
    380 		foreach ($results as $key => $value) {
    381 			$sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
    382 		}
    383 
    384 		array_multisort($sort_order, SORT_ASC, $results);
    385 
    386 		foreach ($results as $result) {
    387 			if ($this->config->get($result['code'] . '_status')) {
    388 				$this->load->model('extension/total/' . $result['code']);
    389 
    390 				// We have to put the totals in an array so that they pass by reference.
    391 				$this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
    392 			}
    393 		}
    394 
    395 		$sort_order = array();
    396 
    397 		foreach ($totals as $key => $value) {
    398 			$sort_order[$key] = $value['sort_order'];
    399 		}
    400 
    401 		array_multisort($sort_order, SORT_ASC, $totals);
    402 
    403 		$data['totals'] = array();
    404 
    405 		foreach ($totals as $total) {
    406 			$data['totals'][] = array(
    407 				'title' => $total['title'],
    408 				'text'  => $this->currency->format($total['value'], $this->session->data['currency'])
    409 			);
    410 		}
    411 
    412 		$this->response->setOutput($this->load->view('extension/payment/klarna_checkout_sidebar', $data));
    413 	}
    414 
    415 	public function shippingAddress() {
    416 		$this->load->model('extension/payment/klarna_checkout');
    417 		$this->load->model('localisation/zone');
    418 
    419 		if (!$this->config->get('klarna_checkout_status')) {
    420 			return false;
    421 		}
    422 
    423 		$json = array();
    424 
    425 		unset($this->session->data['shipping_address']);
    426 		unset($this->session->data['shipping_methods']);
    427 
    428 		if (($this->request->server['REQUEST_METHOD'] == 'POST') && isset($this->request->post['country'])) {
    429 			$country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode3($this->request->post['country']);
    430 
    431 			if ($country_info) {
    432 				// Set default zone for shipping calculations. Get overwritten by correct data when order is confirmed
    433 				$zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
    434 
    435 				$zone = array();
    436 				if (isset($this->request->post['region']) && !empty($this->request->post['region'])) {
    437 					$zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($this->request->post['region'], $country_info['country_id']);
    438 				}
    439 
    440 				if ($zone || $zones) {
    441 					$this->session->data['shipping_address'] = array(
    442 						'address_id'	 => null,
    443 						'firstname'		 => utf8_substr($this->request->post['given_name'], 0, 32),
    444 						'lastname'		 => utf8_substr($this->request->post['family_name'], 0, 32),
    445 						'company'		 => null,
    446 						'address_1'		 => utf8_substr($this->request->post['street_address'], 0, 128),
    447 						'address_2'		 => utf8_substr($this->request->post['street_address'], 129, 256),
    448 						'postcode'		 => utf8_substr($this->request->post['postal_code'], 0, 10),
    449 						'city'			 => utf8_substr($this->request->post['city'], 0, 128),
    450 						'zone_id'		 => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
    451 						'zone'			 => ($zone ? $zone['name'] : $zones[0]['name']),
    452 						'zone_code'		 => ($zone ? $zone['code'] : $zones[0]['code']),
    453 						'country_id'	 => $country_info['country_id'],
    454 						'country'		 => $country_info['name'],
    455 						'iso_code_2'	 => $country_info['iso_code_2'],
    456 						'iso_code_3'	 => $country_info['iso_code_3'],
    457 						'address_format' => $country_info['address_format'],
    458 						'custom_field'	 => array(),
    459 					);
    460 
    461 					$this->tax->unsetRates();
    462 					$this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
    463 					$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
    464 				}
    465 			} else {
    466 				$this->model_extension_payment_klarna_checkout->log('Couldnt find country: ' . $this->request->post['country']);
    467 			}
    468 		}
    469 
    470 		$this->response->addHeader('Content-Type: application/json');
    471 		$this->response->setOutput(json_encode($json));
    472 	}
    473 
    474 	public function cartTotal() {
    475 		$this->load->language('checkout/cart');
    476 
    477 		if (!$this->config->get('klarna_checkout_status')) {
    478 			return false;
    479 		}
    480 
    481 		// Totals
    482 		$this->load->model('setting/extension');
    483 
    484 		$totals = array();
    485 		$taxes = $this->cart->getTaxes();
    486 		$total = 0;
    487 
    488 		// Because __call can not keep var references so we put them into an array.
    489 		$total_data = array(
    490 			'totals' => &$totals,
    491 			'taxes'  => &$taxes,
    492 			'total'  => &$total
    493 		);
    494 
    495 		// Display prices
    496 		if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) {
    497 			$sort_order = array();
    498 
    499 			$results = $this->model_setting_extension->getExtensions('total');
    500 
    501 			foreach ($results as $key => $value) {
    502 				$sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order');
    503 			}
    504 
    505 			array_multisort($sort_order, SORT_ASC, $results);
    506 
    507 			foreach ($results as $result) {
    508 				if ($this->config->get($result['code'] . '_status')) {
    509 					$this->load->model('extension/total/' . $result['code']);
    510 
    511 					// We have to put the totals in an array so that they pass by reference.
    512 					$this->{'model_extension_total_' . $result['code']}->getTotal($total_data);
    513 				}
    514 			}
    515 
    516 			$sort_order = array();
    517 
    518 			foreach ($totals as $key => $value) {
    519 				$sort_order[$key] = $value['sort_order'];
    520 			}
    521 
    522 			array_multisort($sort_order, SORT_ASC, $totals);
    523 
    524 			$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']));
    525 		}
    526 
    527 		$this->response->addHeader('Content-Type: application/json');
    528 		$this->response->setOutput(json_encode($total));
    529 	}
    530 
    531 	public function addressUpdate() {
    532 		$this->load->language('extension/payment/klarna_checkout');
    533 
    534 		$this->load->model('account/customer');
    535 		$this->load->model('checkout/order');
    536 		$this->load->model('extension/payment/klarna_checkout');
    537 		$this->load->model('localisation/zone');
    538 
    539 		if (!$this->config->get('klarna_checkout_status')) {
    540 			return false;
    541 		}
    542 
    543 		$process = true;
    544 
    545 		$request = json_decode(file_get_contents('php://input'));
    546 
    547 		$json = array();
    548 
    549 		$http_response_code = 400;
    550 
    551 		// Check to see if request data is complete
    552 		if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address)) {
    553 			$this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
    554 			$this->model_extension_payment_klarna_checkout->log($request);
    555 			$process = false;
    556 		}
    557 
    558 		// Get Klarna order info from db
    559 		if ($process) {
    560 			$order_id = null;
    561 
    562 			foreach ($request->order_lines as $order_line) {
    563 				if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
    564 					$order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
    565 					break;
    566 				}
    567 			}
    568 
    569 			if ($order_id) {
    570 				// Get klarna order data from db
    571 				$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
    572 
    573 				if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
    574 					$this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
    575 					$process = false;
    576 				}
    577 			} else {
    578 				$process = false;
    579 			}
    580 		}
    581 
    582 		if ($process) {
    583 			$klarna_checkout_order_data = json_decode($this->encryption->decrypt($this->config->get('config_encryption'), $klarna_checkout_order['data']), true);
    584 
    585 			// Check credentials in request with ones stored in db
    586 			$valid_request = false;
    587 			foreach ($this->config->get('klarna_checkout_account') as $account) {
    588 				if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
    589 					$valid_request = true;
    590 					break;
    591 				}
    592 			}
    593 
    594 			if (!$valid_request) {
    595 				$this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
    596 				$process = false;
    597 			}
    598 		}
    599 
    600 		// Request is valid, we can spoof/simulate the customer to calculate shipping
    601 		if ($process) {
    602 			session_destroy();
    603 			session_id($klarna_checkout_order_data['session_id']);
    604 			session_start();
    605 			$this->session->start('default', $klarna_checkout_order_data['session_key']);
    606 
    607 			if ($klarna_checkout_order_data['customer_id']) {
    608 				$customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
    609 
    610 				if ($customer_info) {
    611 					$this->customer->login($customer_info['email'], '', true);
    612 				}
    613 			}
    614 
    615 			$order_info = $this->model_checkout_order->getOrder($order_id);
    616 
    617 			if (!$order_info) {
    618 				$this->model_extension_payment_klarna_checkout->log('No order found using order_id: ' . $order_id . '. Full request below:');
    619 				$this->model_extension_payment_klarna_checkout->log($request);
    620 				$process = false;
    621 			}
    622 
    623 			// Set more session data from the order
    624 			$this->session->data['currency'] = $order_info['currency_code'];
    625 			$this->session->data['language'] = $order_info['language_code'];
    626 
    627 			$country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
    628 
    629 			if (!$country_info) {
    630 				$this->model_extension_payment_klarna_checkout->log('No country found using: ' . $request->shipping_address->country . '. Full request below:');
    631 				$this->model_extension_payment_klarna_checkout->log($request);
    632 			}
    633 
    634 			if ($order_info && $country_info) {
    635 				$zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
    636 
    637 				$zone = array();
    638 				if (isset($request->shipping_address->region) && !empty($request->shipping_address->region)) {
    639 					$zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $country_info['country_id']);
    640 				}
    641 
    642 				if ($zone || $zones) {
    643 					$this->session->data['shipping_address'] = array(
    644 						'address_id'	 => null,
    645 						'firstname'		 => null,
    646 						'lastname'		 => null,
    647 						'company'		 => null,
    648 						'address_1'		 => null,
    649 						'address_2'		 => null,
    650 						'postcode'		 => null,
    651 						'city'			 => null,
    652 						'zone_id'		 => ($zone ? $zone['zone_id'] : $zones[0]['zone_id']),
    653 						'zone'			 => ($zone ? $zone['name'] : $zones[0]['name']),
    654 						'zone_code'		 => ($zone ? $zone['code'] : $zones[0]['code']),
    655 						'country_id'	 => $country_info['country_id'],
    656 						'country'		 => $country_info['name'],
    657 						'iso_code_2'	 => $country_info['iso_code_2'],
    658 						'iso_code_3'	 => $country_info['iso_code_3'],
    659 						'address_format' => '',
    660 						'custom_field'	 => array()
    661 					);
    662 
    663 					$this->session->data['klarna_checkout_data'] = array(
    664 						'email'		 => $request->billing_address->email,
    665 						'firstname'	 => $request->billing_address->given_name,
    666 						'lastname'	 => $request->billing_address->family_name,
    667 						'telephone'	 => $request->billing_address->phone,
    668 						'iso_code_2' => $this->session->data['shipping_address']['iso_code_2'],
    669 						'zone_code'  => $this->session->data['shipping_address']['zone_code']
    670 					);
    671 
    672 					// Unset $tax_rates
    673 					$this->tax->unsetRates();
    674 					$this->tax->setShippingAddress($country_info['country_id'], ($zone ? $zone['zone_id'] : $zones[0]['zone_id']));
    675 					$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
    676 
    677 					//Check if customer is US. If so, send taxes differently
    678 					if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
    679 						$include_taxes = false;
    680 					} else {
    681 						$include_taxes = true;
    682 					}
    683 
    684 					$method_data = array();
    685 
    686 					$this->load->model('setting/extension');
    687 
    688 					$results = $this->model_setting_extension->getExtensions('shipping');
    689 
    690 					foreach ($results as $result) {
    691 						if ($this->config->get('shipping_' . $result['code'] . '_status')) {
    692 							$this->load->model('extension/shipping/' . $result['code']);
    693 
    694 							$quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
    695 
    696 							if ($quote) {
    697 								$method_data[$result['code']] = array(
    698 									'title'      => $quote['title'],
    699 									'quote'      => $quote['quote'],
    700 									'sort_order' => $quote['sort_order'],
    701 									'error'      => $quote['error']
    702 								);
    703 							}
    704 						}
    705 					}
    706 
    707 					$sort_order = array();
    708 
    709 					foreach ($method_data as $key => $value) {
    710 						$sort_order[$key] = $value['sort_order'];
    711 					}
    712 
    713 					array_multisort($sort_order, SORT_ASC, $method_data);
    714 
    715 					$shipping_methods = $method_data;
    716 
    717 					if ($shipping_methods) {
    718 						list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
    719 
    720 						if ($klarna_account && $connector) {
    721 							list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
    722 
    723 							if ($this->cart->hasShipping()) {
    724 								$shipping_method = array();
    725 
    726 								if (isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
    727 									foreach ($shipping_methods as $individual_shipping_method) {
    728 										if ($individual_shipping_method['quote']) {
    729 											foreach ($individual_shipping_method['quote'] as $quote) {
    730 												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'])) {
    731 													$shipping_method = $quote;
    732 													break 2;
    733 												}
    734 											}
    735 										}
    736 									}
    737 								}
    738 
    739 								// If the current shipping method isn't in the available shipping methods, assign default
    740 								if (!$shipping_method) {
    741 									$this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($shipping_methods);
    742 								}
    743 
    744 								$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;
    745 
    746 								if ($include_taxes) {
    747 									$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;
    748 								} else {
    749 									$total_tax_amount = 0;
    750 								}
    751 
    752 								$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;
    753 
    754 								$tax_rate = 0;
    755 
    756 								if ($include_taxes && $total_tax_amount && $total_sub_amount) {
    757 									$tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
    758 								}
    759 
    760 								foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
    761 									if ($order_line['type'] == 'shipping_fee') {
    762 										unset($klarna_order_data['order_lines'][$key]);
    763 										break;
    764 									}
    765 								}
    766 
    767 								$klarna_order_data['order_lines'][] = array(
    768 									'type'					=> 'shipping_fee',
    769 									'name'					=> $this->session->data['shipping_method']['title'],
    770 									'quantity'				=> '1',
    771 									'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),
    772 									'tax_rate'				=> round($tax_rate * 100),
    773 									'total_amount'			=> round($total_amount),
    774 									'total_tax_amount'		=> round($total_tax_amount),
    775 									'total_discount_amount' => 0
    776 								);
    777 							}
    778 
    779 							list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
    780 
    781 							//If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
    782 							if (!$include_taxes) {
    783 								foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
    784 									if ($order_line['type'] == 'sales_tax') {
    785 										unset($klarna_order_data['order_lines'][$key]);
    786 										break;
    787 									}
    788 								}
    789 
    790 								$klarna_order_data['order_lines'][] = array(
    791 									'type'					=> 'sales_tax',
    792 									'name'					=> $this->language->get('text_sales_tax'),
    793 									'quantity'				=> '1',
    794 									'unit_price'			=> round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
    795 									'tax_rate'				=> 0,
    796 									'total_amount'			=> round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
    797 									'total_tax_amount'		=> 0,
    798 									'total_discount_amount' => 0
    799 								);
    800 							}
    801 
    802 							$http_response_code = 200;
    803 
    804 							$json = array(
    805 								'order_amount'     => round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100),
    806 								'order_tax_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100),
    807 								'order_lines'      => array_values($klarna_order_data['order_lines'])
    808 							);
    809 						}
    810 					}
    811 				}
    812 			}
    813 		}
    814 
    815 		$this->model_extension_payment_klarna_checkout->log($http_response_code);
    816 		$this->model_extension_payment_klarna_checkout->log($json);
    817 
    818 		http_response_code($http_response_code);
    819 		$this->response->addHeader('Content-Type: application/json');
    820 		$this->response->setOutput(json_encode($json));
    821 	}
    822 
    823 	public function notification() {
    824 		$this->load->model('extension/payment/klarna_checkout');
    825 		$this->load->model('checkout/order');
    826 
    827 		if (!$this->config->get('klarna_checkout_status')) {
    828 			return false;
    829 		}
    830 
    831 		$request = json_decode(file_get_contents('php://input'));
    832 
    833 		if (isset($request->order_id)) {
    834 			$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($request->order_id);
    835 
    836 			if ($klarna_checkout_order) {
    837 				$order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
    838 
    839 				if ($order_info) {
    840 					list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
    841 
    842 					if (!$klarna_account || !$connector) {
    843 						$this->model_extension_payment_klarna_checkout->log('Could not getConnector');
    844 					}
    845 
    846 					$retrieve = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $request->order_id);
    847 
    848 					$order_status_id = false;
    849 					if ($retrieve) {
    850 						switch ($request->event_type) {
    851 							case 'FRAUD_RISK_ACCEPTED':
    852 								$order_status_id = $this->config->get('klarna_checkout_order_status_fraud_accepted_id');
    853 								break;
    854 							case 'FRAUD_RISK_REJECTED':
    855 								$order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
    856 								break;
    857 						}
    858 					}
    859 
    860 					if ($order_status_id) {
    861 						$this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
    862 					}
    863 				}
    864 			} else {
    865 				$this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $request->order_id);
    866 			}
    867 		} else {
    868 			$this->model_extension_payment_klarna_checkout->log('$request->order_id is not set');
    869 		}
    870 	}
    871 
    872 	public function validation() {
    873 		$this->load->model('account/customer');
    874 		$this->load->model('checkout/order');
    875 		$this->load->model('extension/payment/klarna_checkout');
    876 
    877 		if (!$this->config->get('klarna_checkout_status')) {
    878 			return false;
    879 		}
    880 
    881 		$validate = true;
    882 
    883 		$request = json_decode(file_get_contents('php://input'));
    884 
    885 		$json = array();
    886 
    887 		// Check to see if request data is complete
    888 		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)) {
    889 			$this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
    890 			$this->model_extension_payment_klarna_checkout->log($request);
    891 			$validate = false;
    892 		}
    893 
    894 		// Get Klarna order info from db
    895 		if ($validate) {
    896 			$order_id = null;
    897 
    898 			foreach ($request->order_lines as $order_line) {
    899 				if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
    900 					$order_id = $this->encryption->decrypt($this->config->get('config_encryption'), $order_line->merchant_data);
    901 					break;
    902 				}
    903 			}
    904 
    905 			if ($order_id) {
    906 				// Get klarna order data from db
    907 				$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
    908 
    909 				if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
    910 					$this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
    911 					$validate = false;
    912 				}
    913 			} else {
    914 				$this->model_extension_payment_klarna_checkout->log('Cannot get decrypted order_id');
    915 				$validate = false;
    916 			}
    917 		}
    918 
    919 		if ($validate) {
    920 			$klarna_checkout_order_data = json_decode($this->encryption->decrypt($klarna_checkout_order['data']), true);
    921 
    922 			// Check credentials in request with ones stored in db
    923 			$valid_request = false;
    924 			foreach ($this->config->get('klarna_checkout_account') as $account) {
    925 				if (($account['merchant_id'] == $klarna_checkout_order_data['merchant_id']) && ($account['secret'] == $klarna_checkout_order_data['secret'])) {
    926 					$valid_request = true;
    927 					break;
    928 				}
    929 			}
    930 
    931 			if (!$valid_request) {
    932 				$this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
    933 				$validate = false;
    934 			}
    935 		}
    936 
    937 		// Spoof/simulate the customer to calculate shipping
    938 		if ($validate) {
    939 			session_destroy();
    940 			session_id($klarna_checkout_order_data['session_id']);
    941 			session_start();
    942 			$this->session->start('default', $klarna_checkout_order_data['session_key']);
    943 
    944 			if ($klarna_checkout_order_data['customer_id']) {
    945 				$customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
    946 
    947 				if ($customer_info) {
    948 					$this->customer->login($customer_info['email'], '', true);
    949 				}
    950 			}
    951 
    952 			// Validate cart has products and has stock.
    953 			if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
    954 				$this->model_extension_payment_klarna_checkout->log('Cart has no products or cart has no stock');
    955 				$validate = false;
    956 			}
    957 
    958 			// Validate minimum quantity requirements.
    959 			$products = $this->cart->getProducts();
    960 
    961 			foreach ($products as $product) {
    962 				$product_total = 0;
    963 
    964 				foreach ($products as $product_2) {
    965 					if ($product_2['product_id'] == $product['product_id']) {
    966 						$product_total += $product_2['quantity'];
    967 					}
    968 				}
    969 
    970 				if ($product['minimum'] > $product_total) {
    971 					$this->model_extension_payment_klarna_checkout->log('Cart doesnt meet minimum quantities');
    972 					$validate = false;
    973 				}
    974 			}
    975 
    976 			// Validate cart has recurring products
    977 			if ($this->cart->hasRecurringProducts()) {
    978 				$this->model_extension_payment_klarna_checkout->log('Cart has recurring products');
    979 				$validate = false;
    980 			}
    981 		}
    982 
    983 		// Check order total to see if session matches post data
    984 		if ($validate) {
    985 			$order_info = $this->model_checkout_order->getOrder($order_id);
    986 
    987 			if ($order_info) {
    988 				// Unset $tax_rates and set them again using correct shipping data
    989 				$this->tax->unsetRates();
    990 				$this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
    991 				$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
    992 
    993 				list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
    994 
    995 				// Check order_amount
    996 				if (round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_amount) {
    997 					$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));
    998 					$this->model_extension_payment_klarna_checkout->log($order_info);
    999 					$this->model_extension_payment_klarna_checkout->log($this->cart->getTaxes());
   1000 					$validate = false;
   1001 				}
   1002 
   1003 				// Check order_tax_amount
   1004 				if (round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_tax_amount) {
   1005 					$this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_tax_amount does not match session tax total. Totals below:');
   1006 					$this->model_extension_payment_klarna_checkout->log('Session taxes:');
   1007 					$this->model_extension_payment_klarna_checkout->log(round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100));
   1008 					$this->model_extension_payment_klarna_checkout->log('Request taxes:');
   1009 					$this->model_extension_payment_klarna_checkout->log($request->order_tax_amount);
   1010 					$validate = false;
   1011 				}
   1012 			} else {
   1013 				$this->model_extension_payment_klarna_checkout->log('Cannot find order using: ' . $order_id);
   1014 				$validate = false;
   1015 			}
   1016 		}
   1017 
   1018 		// If validates, add customer's email (if guest checkout) and then send 200 response
   1019 		if ($validate) {
   1020 			if (!$this->customer->isLogged()) {
   1021 				$this->model_extension_payment_klarna_checkout->updateOcOrderEmail($order_id, utf8_substr($request->shipping_address->email, 0, 96));
   1022 			}
   1023 
   1024 			// Update OpenCart order with payment and shipping details
   1025 			$payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->billing_address->country);
   1026 			$shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
   1027 
   1028 			//If region is passed, try to update OpenCart order with correct region/zone
   1029 			$payment_zone_info = array();
   1030 			if ($payment_country_info && isset($request->billing_address->region)) {
   1031 				$payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->billing_address->region, $payment_country_info['country_id']);
   1032 			}
   1033 
   1034 			$shipping_zone_info = array();
   1035 			if ($shipping_country_info && isset($request->shipping_address->region)) {
   1036 				$shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $shipping_country_info['country_id']);
   1037 			}
   1038 
   1039 			$order_data = array(
   1040 				'firstname'				  => utf8_substr($request->billing_address->given_name, 0, 32),
   1041 				'lastname'				  => utf8_substr($request->billing_address->family_name, 0, 32),
   1042 				'telephone'				  => utf8_substr($request->billing_address->phone, 0, 32),
   1043 				'payment_firstname'		  => utf8_substr($request->billing_address->given_name, 0, 32),
   1044 				'payment_lastname'		  => utf8_substr($request->billing_address->family_name, 0, 32),
   1045 				'payment_address_1'		  => utf8_substr($request->billing_address->street_address, 0, 128),
   1046 				'payment_address_2'		  => (isset($request->billing_address->street_address2) ? utf8_substr($request->billing_address->street_address2, 0, 128) : ''),
   1047 				'payment_city'			  => utf8_substr($request->billing_address->city, 0, 128),
   1048 				'payment_postcode'		  => utf8_substr($request->billing_address->postal_code, 0, 10),
   1049 				'payment_zone'			  => ($payment_zone_info ? $payment_zone_info['name'] : ''),
   1050 				'payment_zone_id'		  => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
   1051 				'payment_country'		  => ($payment_country_info ? $payment_country_info['name'] : ''),
   1052 				'payment_country_id'	  => ($payment_country_info ? $payment_country_info['country_id'] : ''),
   1053 				'payment_address_format'  => ($payment_country_info ? $payment_country_info['address_format'] : ''),
   1054 				'shipping_firstname'	  => utf8_substr($request->shipping_address->given_name, 0, 32),
   1055 				'shipping_lastname'		  => utf8_substr($request->shipping_address->family_name, 0, 32),
   1056 				'shipping_address_1'	  => utf8_substr($request->shipping_address->street_address, 0, 128),
   1057 				'shipping_address_2'	  => (isset($request->shipping_address->street_address2) ? utf8_substr($request->shipping_address->street_address2, 0, 128) : ''),
   1058 				'shipping_city'			  => utf8_substr($request->shipping_address->city, 0, 128),
   1059 				'shipping_postcode'		  => utf8_substr($request->shipping_address->postal_code, 0, 10),
   1060 				'shipping_zone'			  => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
   1061 				'shipping_zone_id'		  => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
   1062 				'shipping_country'		  => ($shipping_country_info ? $shipping_country_info['name'] : ''),
   1063 				'shipping_country_id'	  => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
   1064 				'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
   1065 			);
   1066 
   1067 			$this->model_extension_payment_klarna_checkout->updateOcOrder($order_id, $order_data);
   1068 
   1069 			$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
   1070 
   1071 			http_response_code(200);
   1072 		} else {
   1073 			http_response_code(303);
   1074 			$this->response->addHeader('Location: ' . $this->url->link('checkout/failure', '', true));
   1075 		}
   1076 
   1077 		$this->response->addHeader('Content-Type: application/json');
   1078 		$this->response->setOutput(json_encode($json));
   1079 	}
   1080 
   1081 	public function confirmation() {
   1082 		$this->load->language('extension/payment/klarna_checkout');
   1083 
   1084 		if (!$this->config->get('klarna_checkout_status')) {
   1085 			return false;
   1086 		}
   1087 
   1088 		if (isset($this->session->data['order_id'])) {
   1089 			$this->cart->clear();
   1090 
   1091 			unset($this->session->data['shipping_method']);
   1092 			unset($this->session->data['shipping_methods']);
   1093 			unset($this->session->data['payment_method']);
   1094 			unset($this->session->data['payment_methods']);
   1095 			unset($this->session->data['guest']);
   1096 			unset($this->session->data['comment']);
   1097 			unset($this->session->data['order_id']);
   1098 			unset($this->session->data['coupon']);
   1099 			unset($this->session->data['reward']);
   1100 			unset($this->session->data['voucher']);
   1101 			unset($this->session->data['vouchers']);
   1102 			unset($this->session->data['totals']);
   1103 
   1104 			unset($this->session->data['klarna_checkout_order_id']);
   1105 			unset($this->session->data['klarna_checkout_data']);
   1106 		}
   1107 
   1108 		$this->document->setTitle($this->language->get('heading_title_success'));
   1109 
   1110 		$data['breadcrumbs'] = array();
   1111 
   1112 		$data['breadcrumbs'][] = array(
   1113 			'text' => $this->language->get('text_home'),
   1114 			'href' => $this->url->link('common/home')
   1115 		);
   1116 
   1117 		$data['breadcrumbs'][] = array(
   1118 			'text' => $this->language->get('text_basket'),
   1119 			'href' => $this->url->link('checkout/cart')
   1120 		);
   1121 
   1122 		$data['breadcrumbs'][] = array(
   1123 			'text' => $this->language->get('text_checkout'),
   1124 			'href' => $this->url->link('checkout/checkout', '', true)
   1125 		);
   1126 
   1127 		$data['breadcrumbs'][] = array(
   1128 			'text' => $this->language->get('text_success'),
   1129 			'href' => $this->url->link('checkout/success')
   1130 		);
   1131 
   1132 		$data['continue'] = $this->url->link('common/home');
   1133 
   1134 		$data['column_left'] = $this->load->controller('common/column_left');
   1135 		$data['column_right'] = $this->load->controller('common/column_right');
   1136 		$data['content_top'] = $this->load->controller('common/content_top');
   1137 		$data['content_bottom'] = $this->load->controller('common/content_bottom');
   1138 		$data['footer'] = $this->load->controller('common/footer');
   1139 		$data['header'] = $this->load->controller('common/header');
   1140 
   1141 		$this->load->model('extension/payment/klarna_checkout');
   1142 		$this->load->model('checkout/order');
   1143 
   1144 		$klarna_checkout = false;
   1145 		$html_snippet = '';
   1146 
   1147 		if (isset($this->request->get['klarna_order_id'])) {
   1148 			$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
   1149 
   1150 			if ($klarna_checkout_order) {
   1151 				$order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
   1152 
   1153 				if ($order_info) {
   1154 					list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
   1155 
   1156 					if (!$klarna_account || !$connector) {
   1157 						$this->model_extension_payment_klarna_checkout->log('Could not getConnector');
   1158 						$this->response->redirect($this->url->link('checkout/failure', '', true));
   1159 					}
   1160 
   1161 					$retrieve = $this->model_extension_payment_klarna_checkout->orderRetrieve($connector, $this->request->get['klarna_order_id']);
   1162 
   1163 					if ($retrieve) {
   1164 						$klarna_checkout = $retrieve->fetch();
   1165 
   1166 						if ($klarna_checkout && $klarna_checkout['html_snippet']) {
   1167 							$html_snippet = $klarna_checkout['html_snippet'];
   1168 						}
   1169 					} else {
   1170 						$this->response->redirect($this->url->link('checkout/cart', '', true));
   1171 					}
   1172 				}
   1173 			} else {
   1174 				$this->model_extension_payment_klarna_checkout->log('Could not find order id using ' . $this->request->get['klarna_order_id']);
   1175 				$this->response->redirect($this->url->link('checkout/failure', '', true));
   1176 			}
   1177 		} else {
   1178 			$this->model_extension_payment_klarna_checkout->log('$this->request->get[\'klarna_order_id\'] is not set');
   1179 			$this->response->redirect($this->url->link('checkout/failure', '', true));
   1180 		}
   1181 
   1182 		$data['klarna_checkout'] = $html_snippet;
   1183 
   1184 		$this->response->setOutput($this->load->view('extension/payment/klarna_checkout_success', $data));
   1185 	}
   1186 
   1187 	public function push() {
   1188 		$this->load->model('extension/payment/klarna_checkout');
   1189 		$this->load->model('checkout/order');
   1190 
   1191 		if (!$this->config->get('klarna_checkout_status')) {
   1192 			return false;
   1193 		}
   1194 
   1195 		if (isset($this->request->get['klarna_order_id'])) {
   1196 			$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrder($this->request->get['klarna_order_id']);
   1197 
   1198 			if ($klarna_checkout_order) {
   1199 				$order_info = $this->model_checkout_order->getOrder($klarna_checkout_order['order_id']);
   1200 
   1201 				if ($order_info) {
   1202 					list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $order_info['currency_code']);
   1203 
   1204 					if ($klarna_account && $connector) {
   1205 						$order = $this->model_extension_payment_klarna_checkout->omOrderRetrieve($connector, $this->request->get['klarna_order_id']);
   1206 
   1207 						$this->model_extension_payment_klarna_checkout->log('Order details from push:');
   1208 						$this->model_extension_payment_klarna_checkout->log($order);
   1209 
   1210 						if ($order) {
   1211 							if ($order->acknowledge()) {
   1212 								// Update OpenCart order with payment and shipping details
   1213 								$payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['billing_address']['country']);
   1214 								$shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($order['shipping_address']['country']);
   1215 
   1216 								//If region is passed, try to update OpenCart order with correct region/zone
   1217 								$payment_zone_info = array();
   1218 								if ($payment_country_info && isset($order['billing_address']['region'])) {
   1219 									$payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['billing_address']['region'], $payment_country_info['country_id']);
   1220 								}
   1221 
   1222 								$shipping_zone_info = array();
   1223 								if ($shipping_country_info && isset($order['shipping_address']['region'])) {
   1224 									$shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($order['shipping_address']['region'], $shipping_country_info['country_id']);
   1225 								}
   1226 
   1227 								$order_data = array(
   1228 									'firstname'				  => utf8_substr($order['billing_address']['given_name'], 0, 32),
   1229 									'lastname'				  => utf8_substr($order['billing_address']['family_name'], 0, 32),
   1230 									'telephone'				  => utf8_substr($order['billing_address']['phone'], 0, 32),
   1231 									'payment_firstname'		  => utf8_substr($order['billing_address']['given_name'], 0, 32),
   1232 									'payment_lastname'		  => utf8_substr($order['billing_address']['family_name'], 0, 32),
   1233 									'payment_address_1'		  => utf8_substr($order['billing_address']['street_address'], 0, 128),
   1234 									'payment_address_2'		  => (isset($order['billing_address']['street_address2']) ? utf8_substr($order['billing_address']['street_address2'], 0, 128) : ''),
   1235 									'payment_city'			  => utf8_substr($order['billing_address']['city'], 0, 128),
   1236 									'payment_postcode'		  => utf8_substr($order['billing_address']['postal_code'], 0, 10),
   1237 									'payment_zone'			  => ($payment_zone_info ? $payment_zone_info['name'] : ''),
   1238 									'payment_zone_id'		  => ($payment_zone_info ? $payment_zone_info['zone_id'] : ''),
   1239 									'payment_country'		  => ($payment_country_info ? $payment_country_info['name'] : ''),
   1240 									'payment_country_id'	  => ($payment_country_info ? $payment_country_info['country_id'] : ''),
   1241 									'payment_address_format'  => ($payment_country_info ? $payment_country_info['address_format'] : ''),
   1242 									'shipping_firstname'	  => utf8_substr($order['shipping_address']['given_name'], 0, 32),
   1243 									'shipping_lastname'		  => utf8_substr($order['shipping_address']['family_name'], 0, 32),
   1244 									'shipping_address_1'	  => utf8_substr($order['shipping_address']['street_address'], 0, 128),
   1245 									'shipping_address_2'	  => (isset($order['shipping_address']['street_address2']) ? utf8_substr($order['shipping_address']['street_address2'], 0, 128) : ''),
   1246 									'shipping_city'			  => utf8_substr($order['shipping_address']['city'], 0, 128),
   1247 									'shipping_postcode'		  => utf8_substr($order['shipping_address']['postal_code'], 0, 10),
   1248 									'shipping_zone'			  => ($shipping_zone_info ? $shipping_zone_info['name'] : ''),
   1249 									'shipping_zone_id'		  => ($shipping_zone_info ? $shipping_zone_info['zone_id'] : ''),
   1250 									'shipping_country'		  => ($shipping_country_info ? $shipping_country_info['name'] : ''),
   1251 									'shipping_country_id'	  => ($shipping_country_info ? $shipping_country_info['country_id'] : ''),
   1252 									'shipping_address_format' => ($shipping_country_info ? $shipping_country_info['address_format'] : '')
   1253 								);
   1254 
   1255 								$this->model_extension_payment_klarna_checkout->updateOcOrder($klarna_checkout_order['order_id'], $order_data);
   1256 
   1257 								$order_status_id = false;
   1258 								switch ($order['status']) {
   1259 									case 'AUTHORIZED':
   1260 										$order_status_id = $this->config->get('klarna_checkout_order_status_authorised_id');
   1261 
   1262 										if ($order['fraud_status'] == 'PENDING') {
   1263 											$order_status_id = $this->config->get('klarna_checkout_order_status_fraud_pending_id');
   1264 										} elseif ($order['fraud_status'] == 'REJECTED') {
   1265 											$order_status_id = $this->config->get('klarna_checkout_order_status_fraud_rejected_id');
   1266 										}
   1267 										break;
   1268 									case 'PART_CAPTURED':
   1269 										$order_status_id = $this->config->get('klarna_checkout_order_status_part_captured_id');
   1270 										break;
   1271 									case 'CAPTURED':
   1272 										$order_status_id = $this->config->get('klarna_checkout_order_status_captured_id');
   1273 										break;
   1274 									case 'CANCELLED':
   1275 										$order_status_id = $this->config->get('klarna_checkout_order_status_cancelled_id');
   1276 										break;
   1277 								}
   1278 
   1279 								if ($order_status_id) {
   1280 									$this->model_checkout_order->addOrderHistory($klarna_checkout_order['order_id'], $order_status_id);
   1281 								}
   1282 							}
   1283 						} else {
   1284 							$this->model_extension_payment_klarna_checkout->log('Cannot retrieve KC order using order_id: ' . $this->request->get['klarna_order_id']);
   1285 						}
   1286 					}
   1287 				}
   1288 			} else {
   1289 				$this->model_extension_payment_klarna_checkout->log('Cannot find KC order using order_id: ' . $this->request->get['klarna_order_id']);
   1290 			}
   1291 		}
   1292 	}
   1293 
   1294 	private function setPayment() {
   1295 		$this->load->model('account/address');
   1296 		$this->load->model('localisation/country');
   1297 		$this->load->model('localisation/zone');
   1298 
   1299 		if (isset($this->session->data['payment_address']) && !empty($this->session->data['payment_address'])) {
   1300 			$this->session->data['payment_address'] = $this->session->data['payment_address'];
   1301 		} elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
   1302 			$this->session->data['payment_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
   1303 		} else {
   1304 			$country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
   1305 
   1306 			$zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
   1307 
   1308 			$this->session->data['payment_address'] = array(
   1309 				'address_id'	 => null,
   1310 				'firstname'		 => null,
   1311 				'lastname'		 => null,
   1312 				'company'		 => null,
   1313 				'address_1'		 => null,
   1314 				'address_2'		 => null,
   1315 				'postcode'		 => null,
   1316 				'city'			 => null,
   1317 				'zone_id'		 => $zone_info['zone_id'],
   1318 				'zone'			 => $zone_info['name'],
   1319 				'zone_code'		 => $zone_info['code'],
   1320 				'country_id'	 => $country_info['country_id'],
   1321 				'country'		 => $country_info['name'],
   1322 				'iso_code_2'	 => $country_info['iso_code_2'],
   1323 				'iso_code_3'	 => $country_info['iso_code_3'],
   1324 				'address_format' => '',
   1325 				'custom_field'	 => array()
   1326 			);
   1327 		}
   1328 
   1329 		$this->tax->setPaymentAddress($this->session->data['payment_address']['country_id'], $this->session->data['payment_address']['zone_id']);
   1330 		$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
   1331 	}
   1332 
   1333 	private function setShipping() {
   1334 		$this->load->model('account/address');
   1335 		$this->load->model('localisation/country');
   1336 		$this->load->model('localisation/zone');
   1337 
   1338 		if (isset($this->session->data['shipping_address']) && !empty($this->session->data['shipping_address'])) {
   1339 			$this->session->data['shipping_address'] = $this->session->data['shipping_address'];
   1340 		} elseif ($this->customer->isLogged() && $this->customer->getAddressId()) {
   1341 			$this->session->data['shipping_address'] = $this->model_account_address->getAddress($this->customer->getAddressId());
   1342 		} else {
   1343 			$country_info = $this->model_localisation_country->getCountry($this->config->get('config_country_id'));
   1344 
   1345 			$zone_info = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
   1346 
   1347 			$this->session->data['shipping_address'] = array(
   1348 				'address_id'	 => null,
   1349 				'firstname'		 => null,
   1350 				'lastname'		 => null,
   1351 				'company'		 => null,
   1352 				'address_1'		 => null,
   1353 				'address_2'		 => null,
   1354 				'postcode'		 => null,
   1355 				'city'			 => null,
   1356 				'zone_id'		 => $zone_info['zone_id'],
   1357 				'zone'			 => $zone_info['name'],
   1358 				'zone_code'		 => $zone_info['code'],
   1359 				'country_id'	 => $country_info['country_id'],
   1360 				'country'		 => $country_info['name'],
   1361 				'iso_code_2'	 => $country_info['iso_code_2'],
   1362 				'iso_code_3'	 => $country_info['iso_code_3'],
   1363 				'address_format' => '',
   1364 				'custom_field'	 => array()
   1365 			);
   1366 		}
   1367 
   1368 		$this->tax->unsetRates();
   1369 		$this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
   1370 		$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
   1371 
   1372 		if (isset($this->session->data['shipping_address'])) {
   1373 			// Shipping Methods
   1374 			$method_data = array();
   1375 
   1376 			$this->load->model('setting/extension');
   1377 
   1378 			$results = $this->model_setting_extension->getExtensions('shipping');
   1379 
   1380 			foreach ($results as $result) {
   1381 				if ($this->config->get('shipping_' . $result['code'] . '_status')) {
   1382 					$this->load->model('extension/shipping/' . $result['code']);
   1383 
   1384 					$quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
   1385 
   1386 					if ($quote) {
   1387 						$method_data[$result['code']] = array(
   1388 							'title'      => $quote['title'],
   1389 							'quote'      => $quote['quote'],
   1390 							'sort_order' => $quote['sort_order'],
   1391 							'error'      => $quote['error']
   1392 						);
   1393 					}
   1394 				}
   1395 			}
   1396 
   1397 			$sort_order = array();
   1398 
   1399 			foreach ($method_data as $key => $value) {
   1400 				$sort_order[$key] = $value['sort_order'];
   1401 			}
   1402 
   1403 			array_multisort($sort_order, SORT_ASC, $method_data);
   1404 
   1405 			$this->session->data['shipping_methods'] = $method_data;
   1406 		}
   1407 	}
   1408 
   1409 	private function createOrder() {
   1410 		//Klarna defaults:
   1411 		$this->session->data['comment'] = '';
   1412 
   1413 		if (!$this->customer->isLogged()) {
   1414 			$this->session->data['guest'] = array(
   1415 				'customer_group_id' => $this->config->get('config_customer_group_id'),
   1416 				'firstname'			=> '',
   1417 				'lastname'			=> '',
   1418 				'email'				=> '',
   1419 				'telephone'			=> '',
   1420 				'fax'				=> '',
   1421 				'custom_field'		=> array(),
   1422 			);
   1423 		}
   1424 
   1425 		//OpenCart:
   1426 		$order_data = array();
   1427 
   1428 		list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
   1429 
   1430 		$order_data['totals'] = $totals;
   1431 
   1432 		$this->load->language('checkout/checkout');
   1433 
   1434 		$order_data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
   1435 		$order_data['store_id'] = $this->config->get('config_store_id');
   1436 		$order_data['store_name'] = $this->config->get('config_name');
   1437 
   1438 		if ($order_data['store_id']) {
   1439 			$order_data['store_url'] = $this->config->get('config_url');
   1440 		} else {
   1441 			$order_data['store_url'] = HTTP_SERVER;
   1442 		}
   1443 
   1444 		if ($this->customer->isLogged()) {
   1445 			$this->load->model('account/customer');
   1446 
   1447 			$customer_info = $this->model_account_customer->getCustomer($this->customer->getId());
   1448 
   1449 			$order_data['customer_id'] = $this->customer->getId();
   1450 			$order_data['customer_group_id'] = $customer_info['customer_group_id'];
   1451 			$order_data['firstname'] = $customer_info['firstname'];
   1452 			$order_data['lastname'] = $customer_info['lastname'];
   1453 			$order_data['email'] = $customer_info['email'];
   1454 			$order_data['telephone'] = $customer_info['telephone'];
   1455 			$order_data['custom_field'] = json_decode($customer_info['custom_field'], true);
   1456 		} elseif (isset($this->session->data['guest'])) {
   1457 			$order_data['customer_id'] = 0;
   1458 			$order_data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
   1459 			$order_data['firstname'] = $this->session->data['guest']['firstname'];
   1460 			$order_data['lastname'] = $this->session->data['guest']['lastname'];
   1461 			$order_data['email'] = $this->session->data['guest']['email'];
   1462 			$order_data['telephone'] = $this->session->data['guest']['telephone'];
   1463 			$order_data['custom_field'] = $this->session->data['guest']['custom_field'];
   1464 		}
   1465 
   1466 		$order_data['payment_firstname'] = $this->session->data['payment_address']['firstname'];
   1467 		$order_data['payment_lastname'] = $this->session->data['payment_address']['lastname'];
   1468 		$order_data['payment_company'] = $this->session->data['payment_address']['company'];
   1469 		$order_data['payment_address_1'] = $this->session->data['payment_address']['address_1'];
   1470 		$order_data['payment_address_2'] = $this->session->data['payment_address']['address_2'];
   1471 		$order_data['payment_city'] = $this->session->data['payment_address']['city'];
   1472 		$order_data['payment_postcode'] = $this->session->data['payment_address']['postcode'];
   1473 		$order_data['payment_zone'] = $this->session->data['payment_address']['zone'];
   1474 		$order_data['payment_zone_id'] = $this->session->data['payment_address']['zone_id'];
   1475 		$order_data['payment_country'] = $this->session->data['payment_address']['country'];
   1476 		$order_data['payment_country_id'] = $this->session->data['payment_address']['country_id'];
   1477 		$order_data['payment_address_format'] = $this->session->data['payment_address']['address_format'];
   1478 		$order_data['payment_custom_field'] = (isset($this->session->data['payment_address']['custom_field']) ? $this->session->data['payment_address']['custom_field'] : array());
   1479 
   1480 		if (isset($this->session->data['payment_method']['title'])) {
   1481 			$order_data['payment_method'] = $this->session->data['payment_method']['title'];
   1482 		} else {
   1483 			$order_data['payment_method'] = '';
   1484 		}
   1485 
   1486 		if (isset($this->session->data['payment_method']['code'])) {
   1487 			$order_data['payment_code'] = $this->session->data['payment_method']['code'];
   1488 		} else {
   1489 			$order_data['payment_code'] = '';
   1490 		}
   1491 
   1492 		if ($this->cart->hasShipping()) {
   1493 			$order_data['shipping_firstname'] = $this->session->data['shipping_address']['firstname'];
   1494 			$order_data['shipping_lastname'] = $this->session->data['shipping_address']['lastname'];
   1495 			$order_data['shipping_company'] = $this->session->data['shipping_address']['company'];
   1496 			$order_data['shipping_address_1'] = $this->session->data['shipping_address']['address_1'];
   1497 			$order_data['shipping_address_2'] = $this->session->data['shipping_address']['address_2'];
   1498 			$order_data['shipping_city'] = $this->session->data['shipping_address']['city'];
   1499 			$order_data['shipping_postcode'] = $this->session->data['shipping_address']['postcode'];
   1500 			$order_data['shipping_zone'] = $this->session->data['shipping_address']['zone'];
   1501 			$order_data['shipping_zone_id'] = $this->session->data['shipping_address']['zone_id'];
   1502 			$order_data['shipping_country'] = $this->session->data['shipping_address']['country'];
   1503 			$order_data['shipping_country_id'] = $this->session->data['shipping_address']['country_id'];
   1504 			$order_data['shipping_address_format'] = $this->session->data['shipping_address']['address_format'];
   1505 			$order_data['shipping_custom_field'] = (isset($this->session->data['shipping_address']['custom_field']) ? $this->session->data['shipping_address']['custom_field'] : array());
   1506 
   1507 			if (isset($this->session->data['shipping_method']['title'])) {
   1508 				$order_data['shipping_method'] = $this->session->data['shipping_method']['title'];
   1509 			} else {
   1510 				$order_data['shipping_method'] = '';
   1511 			}
   1512 
   1513 			if (isset($this->session->data['shipping_method']['code'])) {
   1514 				$order_data['shipping_code'] = $this->session->data['shipping_method']['code'];
   1515 			} else {
   1516 				$order_data['shipping_code'] = '';
   1517 			}
   1518 		} else {
   1519 			$order_data['shipping_firstname'] = '';
   1520 			$order_data['shipping_lastname'] = '';
   1521 			$order_data['shipping_company'] = '';
   1522 			$order_data['shipping_address_1'] = '';
   1523 			$order_data['shipping_address_2'] = '';
   1524 			$order_data['shipping_city'] = '';
   1525 			$order_data['shipping_postcode'] = '';
   1526 			$order_data['shipping_zone'] = '';
   1527 			$order_data['shipping_zone_id'] = '';
   1528 			$order_data['shipping_country'] = '';
   1529 			$order_data['shipping_country_id'] = '';
   1530 			$order_data['shipping_address_format'] = '';
   1531 			$order_data['shipping_custom_field'] = array();
   1532 			$order_data['shipping_method'] = '';
   1533 			$order_data['shipping_code'] = '';
   1534 		}
   1535 
   1536 		$order_data['products'] = array();
   1537 
   1538 		foreach ($this->cart->getProducts() as $product) {
   1539 			$option_data = array();
   1540 
   1541 			foreach ($product['option'] as $option) {
   1542 				$option_data[] = array(
   1543 					'product_option_id'       => $option['product_option_id'],
   1544 					'product_option_value_id' => $option['product_option_value_id'],
   1545 					'option_id'               => $option['option_id'],
   1546 					'option_value_id'         => $option['option_value_id'],
   1547 					'name'                    => $option['name'],
   1548 					'value'                   => $option['value'],
   1549 					'type'                    => $option['type']
   1550 				);
   1551 			}
   1552 
   1553 			$order_data['products'][] = array(
   1554 				'product_id' => $product['product_id'],
   1555 				'name'       => $product['name'],
   1556 				'model'      => $product['model'],
   1557 				'option'     => $option_data,
   1558 				'download'   => $product['download'],
   1559 				'quantity'   => $product['quantity'],
   1560 				'subtract'   => $product['subtract'],
   1561 				'price'      => $product['price'],
   1562 				'total'      => $product['total'],
   1563 				'tax'        => $this->tax->getTax($product['price'], $product['tax_class_id']),
   1564 				'reward'     => $product['reward']
   1565 			);
   1566 		}
   1567 
   1568 		// Gift Voucher
   1569 		$order_data['vouchers'] = array();
   1570 
   1571 		if (!empty($this->session->data['vouchers'])) {
   1572 			foreach ($this->session->data['vouchers'] as $voucher) {
   1573 				$order_data['vouchers'][] = array(
   1574 					'description'      => $voucher['description'],
   1575 					'code'             => token(10),
   1576 					'to_name'          => $voucher['to_name'],
   1577 					'to_email'         => $voucher['to_email'],
   1578 					'from_name'        => $voucher['from_name'],
   1579 					'from_email'       => $voucher['from_email'],
   1580 					'voucher_theme_id' => $voucher['voucher_theme_id'],
   1581 					'message'          => $voucher['message'],
   1582 					'amount'           => $voucher['amount']
   1583 				);
   1584 			}
   1585 		}
   1586 
   1587 		$order_data['comment'] = $this->session->data['comment'];
   1588 		$order_data['total'] = $total;
   1589 
   1590 		if (isset($this->request->cookie['tracking'])) {
   1591 			$order_data['tracking'] = $this->request->cookie['tracking'];
   1592 
   1593 			$subtotal = $this->cart->getSubTotal();
   1594 
   1595 			// Affiliate
   1596 			$this->load->model('affiliate/affiliate');
   1597 
   1598 			$affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
   1599 
   1600 			if ($affiliate_info) {
   1601 				$order_data['affiliate_id'] = $affiliate_info['affiliate_id'];
   1602 				$order_data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
   1603 			} else {
   1604 				$order_data['affiliate_id'] = 0;
   1605 				$order_data['commission'] = 0;
   1606 			}
   1607 
   1608 			// Marketing
   1609 			$this->load->model('checkout/marketing');
   1610 
   1611 			$marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']);
   1612 
   1613 			if ($marketing_info) {
   1614 				$order_data['marketing_id'] = $marketing_info['marketing_id'];
   1615 			} else {
   1616 				$order_data['marketing_id'] = 0;
   1617 			}
   1618 		} else {
   1619 			$order_data['affiliate_id'] = 0;
   1620 			$order_data['commission'] = 0;
   1621 			$order_data['marketing_id'] = 0;
   1622 			$order_data['tracking'] = '';
   1623 		}
   1624 
   1625 		$order_data['language_id'] = $this->config->get('config_language_id');
   1626 		$order_data['currency_id'] = $this->currency->getId($this->session->data['currency']);
   1627 		$order_data['currency_code'] = $this->session->data['currency'];
   1628 		$order_data['currency_value'] = $this->currency->getValue($this->session->data['currency']);
   1629 		$order_data['ip'] = $this->request->server['REMOTE_ADDR'];
   1630 
   1631 		if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
   1632 			$order_data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
   1633 		} elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) {
   1634 			$order_data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
   1635 		} else {
   1636 			$order_data['forwarded_ip'] = '';
   1637 		}
   1638 
   1639 		if (isset($this->request->server['HTTP_USER_AGENT'])) {
   1640 			$order_data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
   1641 		} else {
   1642 			$order_data['user_agent'] = '';
   1643 		}
   1644 
   1645 		if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
   1646 			$order_data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
   1647 		} else {
   1648 			$order_data['accept_language'] = '';
   1649 		}
   1650 
   1651 		$this->load->model('checkout/order');
   1652 
   1653 		$this->session->data['order_id'] = $this->model_checkout_order->addOrder($order_data);
   1654 	}
   1655 
   1656 	private function klarnaOrderData($klarna_account) {
   1657 		$this->load->language('extension/payment/klarna_checkout');
   1658 
   1659 		$this->load->model('extension/payment/klarna_checkout');
   1660 		$this->load->model('localisation/country');
   1661 
   1662 		$currency_code = $this->session->data['currency'];
   1663 		$currency_value = $this->currency->getValue($this->session->data['currency']);
   1664 
   1665 		// Shipping
   1666 		$unset_shipping_method = true;
   1667 		if (isset($this->session->data['shipping_method']) && isset($this->session->data['shipping_methods'])) {
   1668 			foreach ($this->session->data['shipping_methods'] as $shipping_method) {
   1669 				if ($shipping_method['quote']) {
   1670 					foreach ($shipping_method['quote'] as $quote) {
   1671 						if ($quote == $this->session->data['shipping_method']) {
   1672 							$unset_shipping_method = false;
   1673 							break 2;
   1674 						}
   1675 					}
   1676 				}
   1677 			}
   1678 		}
   1679 
   1680 		if ($unset_shipping_method) {
   1681 			unset($this->session->data['shipping_method']);
   1682 		}
   1683 
   1684 		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']))) {
   1685 			$this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($this->session->data['shipping_methods']);
   1686 		}
   1687 
   1688 		//Check if customer is US. If so, send taxes differently
   1689 		if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
   1690 			$include_taxes = false;
   1691 		} else {
   1692 			$include_taxes = true;
   1693 		}
   1694 
   1695 		if ($this->cart->hasShipping() && isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
   1696 			$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;
   1697 
   1698 			if ($include_taxes) {
   1699 				$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;
   1700 			} else {
   1701 				$total_tax_amount = 0;
   1702 			}
   1703 
   1704 			$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;
   1705 
   1706 			$tax_rate = 0;
   1707 
   1708 			if ($include_taxes && $total_tax_amount && $total_sub_amount) {
   1709 				$tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
   1710 			}
   1711 
   1712 			$klarna_order_data['order_lines'][] = array(
   1713 				'type'					=> 'shipping_fee',
   1714 				'name'					=> $this->session->data['shipping_method']['title'],
   1715 				'quantity'				=> '1',
   1716 				'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),
   1717 				'tax_rate'				=> round($tax_rate * 100),
   1718 				'total_amount'			=> round($total_amount),
   1719 				'total_tax_amount'		=> round($total_tax_amount),
   1720 				'total_discount_amount' => 0
   1721 			);
   1722 		}
   1723 
   1724 		// Billing Address
   1725 		if (isset($this->session->data['klarna_checkout_data'])) {
   1726 			$klarna_order_data['billing_address'] = array(
   1727 				'given_name'  => $this->session->data['klarna_checkout_data']['firstname'],
   1728 				'family_name' => $this->session->data['klarna_checkout_data']['lastname'],
   1729 				'email'		  => $this->session->data['klarna_checkout_data']['email'],
   1730 				'phone'		  => $this->session->data['klarna_checkout_data']['telephone'],
   1731 				'postal_code' => $this->session->data['shipping_address']['postcode'],
   1732 				'region'	  => $this->session->data['shipping_address']['zone_code'],
   1733 				'country'	  => $this->session->data['shipping_address']['iso_code_2'],
   1734 			);
   1735 		} else {
   1736 			$klarna_order_data['billing_address'] = array(
   1737 				'given_name'	  => $this->session->data['shipping_address']['firstname'],
   1738 				'family_name'	  => $this->session->data['shipping_address']['lastname'],
   1739 				'email'			  => ($this->customer->isLogged() ? $this->customer->getEmail() : null),
   1740 				'phone'			  => ($this->customer->isLogged() ? $this->customer->getTelephone() : null)
   1741 			);
   1742 		}
   1743 
   1744 		// Order Total
   1745 		list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
   1746 
   1747 		$merchant_urls = array(
   1748 			'checkout'	     => html_entity_decode($this->url->link('extension/payment/klarna_checkout', 'klarna_order_id={checkout.order.id}', true)),
   1749 			'confirmation'   => html_entity_decode($this->url->link('extension/payment/klarna_checkout/confirmation', 'klarna_order_id={checkout.order.id}', true)),
   1750 			'push'			 => html_entity_decode($this->url->link('extension/payment/klarna_checkout/push', 'klarna_order_id={checkout.order.id}', true)),
   1751 			'validation'	 => html_entity_decode($this->url->link('extension/payment/klarna_checkout/validation', 'klarna_order_id={checkout.order.id}', true)),
   1752 			'address_update' => html_entity_decode($this->url->link('extension/payment/klarna_checkout/addressUpdate', 'klarna_order_id={checkout.order.id}', true)),
   1753 			'notification'	 => html_entity_decode($this->url->link('extension/payment/klarna_checkout/notification', 'klarna_order_id={checkout.order.id}', true)),
   1754 		);
   1755 
   1756 		if ($this->config->get('klarna_checkout_terms')) {
   1757 			$merchant_urls['terms'] = html_entity_decode($this->url->link('information/information', 'information_id=' . $this->config->get('klarna_checkout_terms'), true));
   1758 		}
   1759 
   1760 		$country_info = $this->model_localisation_country->getCountry($klarna_account['country']);
   1761 
   1762 		if ($country_info) {
   1763 			$klarna_order_data['purchase_country'] = $country_info['iso_code_2'];
   1764 		}
   1765 
   1766 		$klarna_order_data['purchase_currency'] = $currency_code;
   1767 		$klarna_order_data['locale'] = $klarna_account['locale'];
   1768 
   1769 		$klarna_order_data['order_amount'] = round($this->currency->format($total, $currency_code, $currency_value, false) * 100);
   1770 		$klarna_order_data['order_tax_amount'] = round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100);
   1771 
   1772 		$klarna_order_data['merchant_urls'] = $merchant_urls;
   1773 
   1774 		// Callback data to be used to spoof/simulate customer to accurately calculate shipping
   1775 		$encrypted_order_data = $this->encryption->encrypt($this->config->get('config_encryption'), json_encode(array(
   1776 			'session_id'  => session_id(),
   1777 			'session_key' => $this->session->getId(),
   1778 			'customer_id' => $this->customer->getId(),
   1779 			'order_id'	  => $this->session->data['order_id'],
   1780 			'merchant_id' => $klarna_account['merchant_id'],
   1781 			'secret'      => $klarna_account['secret']
   1782 		)));
   1783 
   1784 		$encrypted_order_id = $this->encryption->encrypt($this->config->get('config_encryption'), $this->session->data['order_id']);
   1785 
   1786 		$klarna_order_data['merchant_reference1'] = $this->session->data['order_id'];
   1787 
   1788 		$klarna_order_data['options'] = array();
   1789 
   1790 		if ($this->config->get('klarna_checkout_colour_button')) {
   1791 			$klarna_order_data['options']['color_button'] = $this->config->get('klarna_checkout_colour_button');
   1792 		}
   1793 
   1794 		if ($this->config->get('klarna_checkout_colour_button_text')) {
   1795 			$klarna_order_data['options']['color_button_text'] = $this->config->get('klarna_checkout_colour_button_text');
   1796 		}
   1797 
   1798 		if ($this->config->get('klarna_checkout_colour_checkbox')) {
   1799 			$klarna_order_data['options']['color_checkbox'] = $this->config->get('klarna_checkout_colour_checkbox');
   1800 		}
   1801 
   1802 		if ($this->config->get('klarna_checkout_colour_checkbox_checkmark')) {
   1803 			$klarna_order_data['options']['color_checkbox_checkmark'] = $this->config->get('klarna_checkout_colour_checkbox_checkmark');
   1804 		}
   1805 
   1806 		if ($this->config->get('klarna_checkout_colour_header')) {
   1807 			$klarna_order_data['options']['color_header'] = $this->config->get('klarna_checkout_colour_header');
   1808 		}
   1809 
   1810 		if ($this->config->get('klarna_checkout_colour_link')) {
   1811 			$klarna_order_data['options']['color_link'] = $this->config->get('klarna_checkout_colour_link');
   1812 		}
   1813 
   1814 		if ($this->config->get('klarna_checkout_separate_shipping_address')) {
   1815 			$klarna_order_data['options']['allow_separate_shipping_address'] = true;
   1816 		}
   1817 
   1818 		// Only pass DOB/title mandatory for UK stores
   1819 		if ($country_info['iso_code_2'] == 'GB') {
   1820 			if ($this->config->get('klarna_checkout_dob_mandatory')) {
   1821 				$klarna_order_data['options']['date_of_birth_mandatory'] = true;
   1822 			}
   1823 
   1824 			if ($this->config->get('klarna_checkout_title_mandatory')) {
   1825 				$klarna_order_data['options']['title_mandatory'] = true;
   1826 			}
   1827 		}
   1828 
   1829 		if ($this->config->get('klarna_checkout_additional_text_box') && $this->customer->isLogged() && !$this->customer->getNewsletter()) {
   1830 			$klarna_order_data['options']['additional_checkbox'] = array(
   1831 				'text'	   => $this->language->get('text_newsletter'),
   1832 				'checked'  => false,
   1833 				'required' => false
   1834 			);
   1835 		}
   1836 
   1837 		$shipping_countries = $this->model_extension_payment_klarna_checkout->getCountriesByGeoZone($klarna_account['shipping']);
   1838 
   1839 		$klarna_shipping_countries = array();
   1840 		foreach ($shipping_countries as $shipping_country) {
   1841 			$country_info = $this->model_localisation_country->getCountry($shipping_country['country_id']);
   1842 
   1843 			if ($country_info && $country_info['iso_code_2']) {
   1844 				$klarna_shipping_countries[] = $country_info['iso_code_2'];
   1845 			}
   1846 		}
   1847 
   1848 		$klarna_order_data['shipping_countries'] = $klarna_shipping_countries;
   1849 
   1850 		$average_product_tax_rate = array();
   1851 
   1852 		// Products (Add these last because we send encrypted session order_id)
   1853 		foreach ($this->cart->getProducts() as $product) {
   1854 			$total_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes) * $product['quantity'], $currency_code, $currency_value, false) * 100;
   1855 
   1856 			if ($include_taxes) {
   1857 				$total_tax_amount = $this->currency->format($this->tax->getTax($product['price'], $product['tax_class_id']) * $product['quantity'], $currency_code, $currency_value, false) * 100;
   1858 			} else {
   1859 				$total_tax_amount = 0;
   1860 			}
   1861 
   1862 			$total_sub_amount = $this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], false) * $product['quantity'], $currency_code, $currency_value, false) * 100;
   1863 
   1864 			$tax_rate = 0;
   1865 
   1866 			if ($include_taxes && $total_tax_amount && $total_sub_amount) {
   1867 				$tax_rate = ($total_tax_amount / $total_sub_amount) * 100;
   1868 			}
   1869 
   1870 			$average_product_tax_rate[] = round($tax_rate * 100);
   1871 
   1872 			$klarna_order_data['order_lines'][] = array(
   1873 				'type'					=> ($product['shipping'] ? 'physical' : 'digital'),
   1874 				'reference'				=> $product['model'],
   1875 				'name'					=> $product['name'],
   1876 				'quantity'				=> $product['quantity'],
   1877 				'quantity_unit'			=> 'pcs',
   1878 				'unit_price'			=> round($this->currency->format($this->tax->calculate($product['price'], $product['tax_class_id'], $include_taxes), $currency_code, $currency_value, false) * 100),
   1879 				'tax_rate'				=> round($tax_rate * 100),
   1880 				'total_amount'			=> round($total_amount),
   1881 				'total_tax_amount'		=> round($total_tax_amount),
   1882 				'merchant_data'         => $encrypted_order_id,
   1883 				'total_discount_amount' => 0
   1884 			);
   1885 		}
   1886 
   1887 		// Gift Voucher
   1888 		if (!empty($this->session->data['vouchers'])) {
   1889 			foreach ($this->session->data['vouchers'] as $key => $voucher) {
   1890 				$klarna_order_data['order_lines'][] = array(
   1891 					'type'					=> 'gift_card',
   1892 					'reference'				=> '',
   1893 					'name'					=> $voucher['description'],
   1894 					'quantity'				=> 1,
   1895 					'quantity_unit'			=> 'pcs',
   1896 					'unit_price'			=> round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
   1897 					'tax_rate'				=> 0,
   1898 					'total_amount'			=> round($this->currency->format($voucher['amount'], $currency_code, $currency_value, false) * 100),
   1899 					'total_tax_amount'		=> 0,
   1900 					'merchant_data'         => $encrypted_order_id,
   1901 					'total_discount_amount' => 0
   1902 				);
   1903 			}
   1904 		}
   1905 
   1906 		foreach ($totals as $result) {
   1907 			if ($result['code'] == 'coupon') {
   1908 				$discount_total_price = 0;
   1909 				$discount_sub_total_price = 0;
   1910 				foreach ($this->cart->getProducts() as $product) {
   1911 					$discount_total_price += $this->tax->calculate($result['value'], $product['tax_class_id'], $include_taxes);
   1912 					$discount_sub_total_price += $result['value'];
   1913 				}
   1914 
   1915 				$average_discount_total_price = $discount_total_price / count($average_product_tax_rate);
   1916 
   1917 				$average_discount_sub_total_price = $discount_sub_total_price / count($average_product_tax_rate);
   1918 
   1919 				$total_tax_amount = ($average_discount_sub_total_price / 100) * (array_sum($average_product_tax_rate) / count($average_product_tax_rate));
   1920 
   1921 				$klarna_order_data['order_lines'][] = array(
   1922 					'type'					=> 'discount',
   1923 					'name'					=> $result['title'],
   1924 					'quantity'				=> '1',
   1925 					'unit_price'			=> round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
   1926 					'tax_rate'				=> array_sum($average_product_tax_rate) / count($average_product_tax_rate),
   1927 					'total_amount'			=> round($this->currency->format($average_discount_total_price, $currency_code, $currency_value, false) * 100),
   1928 					'total_tax_amount'		=> round($total_tax_amount),
   1929 					'total_discount_amount' => 0
   1930 				);
   1931 			}
   1932 
   1933 			if ($result['code'] == 'voucher') {
   1934 				$klarna_order_data['order_lines'][] = array(
   1935 					'type'					=> 'discount',
   1936 					'name'					=> $result['title'],
   1937 					'quantity'				=> '1',
   1938 					'unit_price'			=> round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
   1939 					'tax_rate'				=> 0,
   1940 					'total_amount'			=> round($this->currency->format($result['value'], $currency_code, $currency_value, false) * 100),
   1941 					'total_tax_amount'		=> 0,
   1942 					'total_discount_amount' => 0
   1943 				);
   1944 			}
   1945 		}
   1946 
   1947 		//If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
   1948 		if (!$include_taxes) {
   1949 			$klarna_order_data['order_lines'][] = array(
   1950 				'type'					=> 'sales_tax',
   1951 				'name'					=> $this->language->get('text_sales_tax'),
   1952 				'quantity'				=> '1',
   1953 				'unit_price'			=> round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
   1954 				'tax_rate'				=> 0,
   1955 				'total_amount'			=> round($this->currency->format(array_sum($taxes), $currency_code, $currency_value, false) * 100),
   1956 				'total_tax_amount'		=> 0,
   1957 				'total_discount_amount' => 0
   1958 			);
   1959 		}
   1960 
   1961 		return array($klarna_order_data, $encrypted_order_data);
   1962 	}
   1963 }