public function addressUpdate()
{
$this->load->language('extension/payment/klarna_checkout');
$this->load->model('account/customer');
$this->load->model('checkout/order');
$this->load->model('extension/payment/klarna_checkout');
$this->load->model('localisation/zone');
if (!$this->config->get('klarna_checkout_status')) {
return false;
}
$process = true;
$request = json_decode(file_get_contents('php://input'));
$json = array();
$http_response_code = 400;
// Check to see if request data is complete
if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address)) {
$this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
$this->model_extension_payment_klarna_checkout->log($request);
$process = false;
}
// Get Klarna order info from db
if ($process) {
$order_id = null;
foreach ($request->order_lines as $order_line) {
if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
$order_id = $this->encryption->decrypt($order_line->merchant_data);
break;
}
}
if ($order_id) {
// Get klarna order data from db
$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
$this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
$process = false;
}
} else {
$process = false;
}
}
if ($process) {
$klarna_checkout_order_data = json_decode($this->encryption->decrypt($klarna_checkout_order['data']), true);
// Check credentials in request with ones stored in db
$valid_request = false;
foreach ($this->config->get('klarna_checkout_account') as $account) {
if ($account['merchant_id'] == $klarna_checkout_order_data['merchant_id'] && $account['secret'] == $klarna_checkout_order_data['secret']) {
$valid_request = true;
break;
}
}
if (!$valid_request) {
$this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
$process = false;
}
}
// Request is valid, we can spoof/simulate the customer to calculate shipping
if ($process) {
session_destroy();
session_id($klarna_checkout_order_data['session_id']);
session_start();
$this->session->start('default', $klarna_checkout_order_data['session_key']);
if ($klarna_checkout_order_data['customer_id']) {
$customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
if ($customer_info) {
$this->customer->login($customer_info['email'], '', true);
}
}
$order_info = $this->model_checkout_order->getOrder($order_id);
if (!$order_info) {
$this->model_extension_payment_klarna_checkout->log('No order found using order_id: ' . $order_id . '. Full request below:');
$this->model_extension_payment_klarna_checkout->log($request);
$process = false;
}
// Set more session data from the order
$this->session->data['currency'] = $order_info['currency_code'];
$this->session->data['language'] = $order_info['language_code'];
$country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
if (!$country_info) {
$this->model_extension_payment_klarna_checkout->log('No country found using: ' . $request->shipping_address->country . '. Full request below:');
$this->model_extension_payment_klarna_checkout->log($request);
}
if ($order_info && $country_info) {
$zones = $this->model_localisation_zone->getZonesByCountryId($country_info['country_id']);
$zone = array();
if (isset($request->shipping_address->region) && !empty($request->shipping_address->region)) {
$zone = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $country_info['country_id']);
}
if ($zone || $zones) {
$this->session->data['shipping_address'] = array('address_id' => null, 'firstname' => null, 'lastname' => null, 'company' => null, 'address_1' => null, 'address_2' => null, 'postcode' => null, 'city' => null, 'zone_id' => $zone ? $zone['zone_id'] : $zones[0]['zone_id'], 'zone' => $zone ? $zone['name'] : $zones[0]['name'], 'zone_code' => $zone ? $zone['code'] : $zones[0]['code'], 'country_id' => $country_info['country_id'], 'country' => $country_info['name'], 'iso_code_2' => $country_info['iso_code_2'], 'iso_code_3' => $country_info['iso_code_3'], 'address_format' => '', 'custom_field' => array());
$this->session->data['klarna_checkout_data'] = array('email' => $request->billing_address->email, 'firstname' => $request->billing_address->given_name, 'lastname' => $request->billing_address->family_name, 'telephone' => $request->billing_address->phone, 'iso_code_2' => $this->session->data['shipping_address']['iso_code_2'], 'zone_code' => $this->session->data['shipping_address']['zone_code']);
// Unset $tax_rates
$this->tax->unsetRates();
$this->tax->setShippingAddress($country_info['country_id'], $zone ? $zone['zone_id'] : $zones[0]['zone_id']);
$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
//Check if customer is US. If so, send taxes differently
if ($this->session->data['shipping_address']['iso_code_2'] === 'US') {
$include_taxes = false;
} else {
$include_taxes = true;
}
$method_data = array();
$this->load->model('extension/extension');
$results = $this->model_extension_extension->getExtensions('shipping');
foreach ($results as $result) {
if ($this->config->get($result['code'] . '_status')) {
$this->load->model('extension/shipping/' . $result['code']);
$quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($this->session->data['shipping_address']);
if ($quote) {
$method_data[$result['code']] = array('title' => $quote['title'], 'quote' => $quote['quote'], 'sort_order' => $quote['sort_order'], 'error' => $quote['error']);
}
}
}
$sort_order = array();
foreach ($method_data as $key => $value) {
$sort_order[$key] = $value['sort_order'];
}
array_multisort($sort_order, SORT_ASC, $method_data);
$shipping_methods = $method_data;
if ($shipping_methods) {
list($klarna_account, $connector) = $this->model_extension_payment_klarna_checkout->getConnector($this->config->get('klarna_checkout_account'), $this->session->data['currency']);
if ($klarna_account && $connector) {
list($klarna_order_data, $encrypted_order_data) = $this->klarnaOrderData($klarna_account);
if ($this->cart->hasShipping()) {
$shipping_method = array();
if (isset($this->session->data['shipping_method']) && !empty($this->session->data['shipping_method'])) {
foreach ($shipping_methods as $individual_shipping_method) {
if ($individual_shipping_method['quote']) {
foreach ($individual_shipping_method['quote'] as $quote) {
if ($this->session->data['shipping_method']['code'] == $quote['code'] && $this->session->data['shipping_method']['title'] == $quote['title'] && $this->session->data['shipping_method']['cost'] == $quote['cost'] && $this->session->data['shipping_method']['tax_class_id'] == $quote['tax_class_id']) {
$shipping_method = $quote;
break 2;
}
}
}
}
}
// If the current shipping method isn't in the available shipping methods, assign default
if (!$shipping_method) {
$this->session->data['shipping_method'] = $this->model_extension_payment_klarna_checkout->getDefaultShippingMethod($shipping_methods);
}
$total_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
if ($include_taxes) {
$total_tax_amount = $this->currency->format($this->tax->getTax($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id']), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
} else {
$total_tax_amount = 0;
}
$total_sub_amount = $this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], false), $order_info['currency_code'], $order_info['currency_value'], false) * 100;
$tax_rate = 0;
if ($include_taxes && $total_tax_amount && $total_sub_amount) {
$tax_rate = $total_tax_amount / $total_sub_amount * 100;
}
foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
if ($order_line['type'] == 'shipping_fee') {
unset($klarna_order_data['order_lines'][$key]);
break;
}
}
$klarna_order_data['order_lines'][] = array('type' => 'shipping_fee', 'name' => $this->session->data['shipping_method']['title'], 'quantity' => '1', 'unit_price' => round($this->currency->format($this->tax->calculate($this->session->data['shipping_method']['cost'], $this->session->data['shipping_method']['tax_class_id'], $include_taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100), 'tax_rate' => round($tax_rate * 100), 'total_amount' => round($total_amount), 'total_tax_amount' => round($total_tax_amount), 'total_discount_amount' => 0);
}
list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
//If $include_taxes is false, means customer is US so we add a new sales_tax order line with all the tax
if (!$include_taxes) {
foreach ($klarna_order_data['order_lines'] as $key => $order_line) {
if ($order_line['type'] == 'sales_tax') {
unset($klarna_order_data['order_lines'][$key]);
break;
}
}
$klarna_order_data['order_lines'][] = array('type' => 'sales_tax', 'name' => $this->language->get('text_sales_tax'), 'quantity' => '1', 'unit_price' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100), 'tax_rate' => 0, 'total_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100), 'total_tax_amount' => 0, 'total_discount_amount' => 0);
}
$http_response_code = 200;
$json = array('order_amount' => round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100), 'order_tax_amount' => round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100), 'order_lines' => array_values($klarna_order_data['order_lines']));
}
}
}
}
}
$this->model_extension_payment_klarna_checkout->log($http_response_code);
$this->model_extension_payment_klarna_checkout->log($json);
http_response_code($http_response_code);
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}