public function validation()
{
$this->load->model('account/customer');
$this->load->model('checkout/order');
$this->load->model('extension/payment/klarna_checkout');
if (!$this->config->get('klarna_checkout_status')) {
return false;
}
$validate = true;
$request = json_decode(file_get_contents('php://input'));
$json = array();
// Check to see if request data is complete
if (!$request || !isset($request->order_lines) || empty($request->order_lines) || !isset($request->shipping_address) || empty($request->shipping_address) || !isset($request->billing_address) || empty($request->billing_address)) {
$this->model_extension_payment_klarna_checkout->log('Request data incomplete. Full request below:');
$this->model_extension_payment_klarna_checkout->log($request);
$validate = false;
}
// Get Klarna order info from db
if ($validate) {
$order_id = null;
foreach ($request->order_lines as $order_line) {
if ($order_line->type == 'physical' || $order_line->type == 'digital' || $order_line->type == 'gift_card') {
$order_id = $this->encryption->decrypt($order_line->merchant_data);
break;
}
}
if ($order_id) {
// Get klarna order data from db
$klarna_checkout_order = $this->model_extension_payment_klarna_checkout->getOrderByOrderId($order_id);
if (!$klarna_checkout_order || !$klarna_checkout_order['data']) {
$this->model_extension_payment_klarna_checkout->log('No klarna order found using order_id: ' . $order_id);
$validate = false;
}
} else {
$this->model_extension_payment_klarna_checkout->log('Cannot get decrypted order_id');
$validate = false;
}
}
if ($validate) {
$klarna_checkout_order_data = json_decode($this->encryption->decrypt($klarna_checkout_order['data']), true);
// Check credentials in request with ones stored in db
$valid_request = false;
foreach ($this->config->get('klarna_checkout_account') as $account) {
if ($account['merchant_id'] == $klarna_checkout_order_data['merchant_id'] && $account['secret'] == $klarna_checkout_order_data['secret']) {
$valid_request = true;
break;
}
}
if (!$valid_request) {
$this->model_extension_payment_klarna_checkout->log('Cannot validate request. Terminating.');
$validate = false;
}
}
// Spoof/simulate the customer to calculate shipping
if ($validate) {
session_destroy();
session_id($klarna_checkout_order_data['session_id']);
session_start();
$this->session->start('default', $klarna_checkout_order_data['session_key']);
if ($klarna_checkout_order_data['customer_id']) {
$customer_info = $this->model_account_customer->getCustomer($klarna_checkout_order_data['customer_id']);
if ($customer_info) {
$this->customer->login($customer_info['email'], '', true);
}
}
// Validate cart has products and has stock.
if (!$this->cart->hasProducts() && empty($this->session->data['vouchers']) || !$this->cart->hasStock() && !$this->config->get('config_stock_checkout')) {
$this->model_extension_payment_klarna_checkout->log('Cart has no products or cart has no stock');
$validate = false;
}
// Validate minimum quantity requirements.
$products = $this->cart->getProducts();
foreach ($products as $product) {
$product_total = 0;
foreach ($products as $product_2) {
if ($product_2['product_id'] == $product['product_id']) {
$product_total += $product_2['quantity'];
}
}
if ($product['minimum'] > $product_total) {
$this->model_extension_payment_klarna_checkout->log('Cart doesnt meet minimum quantities');
$validate = false;
}
}
// Validate cart has recurring products
if ($this->cart->hasRecurringProducts()) {
$this->model_extension_payment_klarna_checkout->log('Cart has recurring products');
$validate = false;
}
}
// Check order total to see if session matches post data
if ($validate) {
$order_info = $this->model_checkout_order->getOrder($order_id);
if ($order_info) {
// Unset $tax_rates and set them again using correct shipping data
$this->tax->unsetRates();
$this->tax->setShippingAddress($this->session->data['shipping_address']['country_id'], $this->session->data['shipping_address']['zone_id']);
$this->tax->setStoreAddress($this->config->get('config_country_id'), $this->config->get('config_zone_id'));
list($totals, $taxes, $total) = $this->model_extension_payment_klarna_checkout->getTotals();
// Check order_amount
if (round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_amount) {
$this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_amount does not match session order total. Klarna Request: ' . $request->order_amount . '. OpenCart: ' . round($this->currency->format($total, $order_info['currency_code'], $order_info['currency_value'], false) * 100));
$this->model_extension_payment_klarna_checkout->log($order_info);
$this->model_extension_payment_klarna_checkout->log($this->cart->getTaxes());
$validate = false;
}
// Check order_tax_amount
if (round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100) != $request->order_tax_amount) {
$this->model_extension_payment_klarna_checkout->log('Klarna Checkout order_tax_amount does not match session tax total. Totals below:');
$this->model_extension_payment_klarna_checkout->log('Session taxes:');
$this->model_extension_payment_klarna_checkout->log(round($this->currency->format(array_sum($taxes), $order_info['currency_code'], $order_info['currency_value'], false) * 100));
$this->model_extension_payment_klarna_checkout->log('Request taxes:');
$this->model_extension_payment_klarna_checkout->log($request->order_tax_amount);
$validate = false;
}
} else {
$this->model_extension_payment_klarna_checkout->log('Cannot find order using: ' . $order_id);
$validate = false;
}
}
// If validates, add customer's email (if guest checkout) and then send 200 response
if ($validate) {
if (!$this->customer->isLogged()) {
$this->model_extension_payment_klarna_checkout->updateOcOrderEmail($order_id, utf8_substr($request->shipping_address->email, 0, 96));
}
// Update OpenCart order with payment and shipping details
$payment_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->billing_address->country);
$shipping_country_info = $this->model_extension_payment_klarna_checkout->getCountryByIsoCode2($request->shipping_address->country);
//If region is passed, try to update OpenCart order with correct region/zone
$payment_zone_info = array();
if ($payment_country_info && isset($request->billing_address->region)) {
$payment_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->billing_address->region, $payment_country_info['country_id']);
}
$shipping_zone_info = array();
if ($shipping_country_info && isset($request->shipping_address->region)) {
$shipping_zone_info = $this->model_extension_payment_klarna_checkout->getZoneByCode($request->shipping_address->region, $shipping_country_info['country_id']);
}
$order_data = array('firstname' => utf8_substr($request->billing_address->given_name, 0, 32), 'lastname' => utf8_substr($request->billing_address->family_name, 0, 32), 'telephone' => utf8_substr($request->billing_address->phone, 0, 32), 'payment_firstname' => utf8_substr($request->billing_address->given_name, 0, 32), 'payment_lastname' => utf8_substr($request->billing_address->family_name, 0, 32), 'payment_address_1' => utf8_substr($request->billing_address->street_address, 0, 128), 'payment_address_2' => isset($request->billing_address->street_address2) ? utf8_substr($request->billing_address->street_address2, 0, 128) : '', 'payment_city' => utf8_substr($request->billing_address->city, 0, 128), 'payment_postcode' => utf8_substr($request->billing_address->postal_code, 0, 10), 'payment_zone' => $payment_zone_info ? $payment_zone_info['name'] : '', 'payment_zone_id' => $payment_zone_info ? $payment_zone_info['zone_id'] : '', 'payment_country' => $payment_country_info ? $payment_country_info['name'] : '', 'payment_country_id' => $payment_country_info ? $payment_country_info['country_id'] : '', 'payment_address_format' => $payment_country_info ? $payment_country_info['address_format'] : '', 'shipping_firstname' => utf8_substr($request->shipping_address->given_name, 0, 32), 'shipping_lastname' => utf8_substr($request->shipping_address->family_name, 0, 32), 'shipping_address_1' => utf8_substr($request->shipping_address->street_address, 0, 128), 'shipping_address_2' => isset($request->shipping_address->street_address2) ? utf8_substr($request->shipping_address->street_address2, 0, 128) : '', 'shipping_city' => utf8_substr($request->shipping_address->city, 0, 128), 'shipping_postcode' => utf8_substr($request->shipping_address->postal_code, 0, 10), 'shipping_zone' => $shipping_zone_info ? $shipping_zone_info['name'] : '', 'shipping_zone_id' => $shipping_zone_info ? $shipping_zone_info['zone_id'] : '', 'shipping_country' => $shipping_country_info ? $shipping_country_info['name'] : '', 'shipping_country_id' => $shipping_country_info ? $shipping_country_info['country_id'] : '', 'shipping_address_format' => $shipping_country_info ? $shipping_country_info['address_format'] : '');
$this->model_extension_payment_klarna_checkout->updateOcOrder($order_id, $order_data);
$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('config_order_status_id'));
http_response_code(200);
} else {
http_response_code(303);
$this->response->addHeader('Location: ' . $this->url->link('checkout/failure', '', true));
}
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}