_loggable = TRUE; $this->tableFields = array_keys($this->getTableSQLFields()); $this->_tablepkey = 'id'; $this->_tableId = 'id'; $varsToPush = $this->getVarsToPush(); $this->setConfigParameterable($this->_configTableFieldName, $varsToPush); plgVmPaymentKlarnaCheckout::includeKlarnaFiles(); VmConfig::loadJLang('plg_vmpayment_klarna'); if (!JFactory::getApplication()->isSite()) { $doc = JFactory::getDocument(); $doc->addScript(JURI::root(true) . '/plugins/vmpayment/klarnacheckout/klarnacheckout/assets/js/admin.js'); $doc->addStyleSheet(JURI::root(true) . '/plugins/vmpayment/klarnacheckout/klarnacheckout/assets/css/admin.css'); } } /** * @return string */ public function getVmPluginCreateTableSQL () { return $this->createTableSQL('Payment KlarnaCheckout Table'); } /** * @return array */ function getTableSQLFields () { $SQLfields = array( 'id' => 'int(11) UNSIGNED NOT NULL AUTO_INCREMENT', 'virtuemart_order_id' => 'int(11) UNSIGNED', 'order_number' => 'char(64)', 'virtuemart_paymentmethod_id' => 'mediumint(1) UNSIGNED', 'payment_name' => 'varchar(1000)', 'payment_order_total' => 'decimal(15,5)', 'payment_currency' => 'smallint(1)', 'action' => 'varchar(20)', // BC 'format' => 'varchar(5)',// BC 'data' => 'mediumtext', // BC 'klarna_id' => 'varchar(64)', 'klarna_status' => 'varchar(64)', 'klarna_reservation' => 'varchar(64)', 'klarna_started_at' => 'varchar(64)', 'klarna_completed_at' => 'varchar(64)', 'klarna_expires_at' => 'varchar(64)', 'klarna_invoicenumber' => 'varchar(255)', 'klarna_invoicepdf' => 'varchar(512)', ); return $SQLfields; } /** * This shows the plugin for choosing in the payment list of the checkout process. * * @author Valerie Cartan Isaksen */ function plgVmDisplayListFEPayment (VirtueMartCart $cart, $selected = 0, &$htmlIn) { if ($this->getPluginMethods($cart->vendorId) === 0) { if (empty($this->_name)) { $app = JFactory::getApplication(); $app->enqueueMessage(vmText::_('COM_VIRTUEMART_CART_NO_' . strtoupper($this->_psType))); return false; } else { return false; } } $htmla = array(); $html = ''; $logo = ''; VmConfig::loadJLang('com_virtuemart'); $currency = CurrencyDisplay::getInstance(); $showallform = true; foreach ($this->methods as $this->_currentMethod) { if ($this->checkConditions($cart, $this->_currentMethod, $cart->pricesUnformatted)) { $methodSalesPrice = $this->calculateSalesPrice($cart, $this->_currentMethod, $cart->pricesUnformatted); if (empty($this->_currentMethod->payment_logos)) { $logo = ''; } $payment_cost = ''; if ($methodSalesPrice) { $payment_cost = $currency->priceDisplay($methodSalesPrice); } if ($selected == $this->_currentMethod->virtuemart_paymentmethod_id) { $checked = 'checked="checked"'; } else { $checked = ''; } if ($cart->virtuemart_paymentmethod_id == $this->_currentMethod->virtuemart_paymentmethod_id) { $showallform = false; } $html = $this->renderByLayout('display_payment', array( 'plugin' => $this->_currentMethod, 'checked' => $checked, 'payment_logo' => $logo, 'payment_cost' => $payment_cost, 'showallform' => $showallform )); $htmla[] = $html; } } if ($showallform) { $js = ' jQuery(document).ready(function( $ ) { $("#checkoutForm").show(); $(".billto-shipto").show(); $("#com-form-login").show(); }); '; $document = JFactory::getDocument(); $document->addScriptDeclaration($js); } if (!empty($htmla)) { $htmlIn[] = $htmla; } return true; } function getCartItems ($cart) { vmdebug('getProductItems', $cart->pricesUnformatted); //self::includeKlarnaFiles(); $i = 0; foreach ($cart->products as $pkey => $product) { $items[$i]['reference'] = !empty($product->sku) ? $product->sku : $product->virtuemart_product_id; $items[$i]['name'] = $product->product_name; $items[$i]['quantity'] = (int)$product->quantity; $price = !empty($product->prices['basePriceWithTax']) ? $product->prices['basePriceWithTax'] : $product->prices['basePriceVariant']; $itemInPaymentCurrency = vmPSPlugin::getAmountInCurrency($price, $this->_currentMethod->payment_currency); $items[$i]['unit_price'] = round($itemInPaymentCurrency['value'] * 100, 0); //$items[$i]['discount_rate'] = $discountRate; // Bug indoc: discount is not supported //$items[$i]['discount'] = abs($cart->pricesUnformatted[$pkey]['discountAmount']*100); $tax_rate = round($this->getVatTaxProduct($cart->pricesUnformatted[$pkey]['VatTax'])); $items[$i]['tax_rate'] = $tax_rate * 100; //$this->debugLog($unitPriceCentsInPaymentCurrency, 'getCartItems', 'debug'); //$this->debugLog($cart->pricesUnformatted[$pkey], 'getCartItems Products', 'debug'); $this->debugLog($items[$i], 'getCartItems', 'debug'); $i++; // ADD A DISCOUNT AS A NEGATIVE VALUE FOR THAT PRODUCT if ($cart->pricesUnformatted[$pkey]['discountAmount'] != 0.0) { $items[$i]['reference'] = $items[$i - 1]['reference']; $items[$i]['name'] = $items[$i - 1]['name'] . ' (' . vmText::_('VMPAYMENT_KLARNACHECKOUT_PRODUCTDISCOUNT') . ')'; $items[$i]['quantity'] = (int)$product->quantity; $discount_tax_percent = 0.0; $discountInPaymentCurrency = vmPSPlugin::getAmountInCurrency(abs($cart->pricesUnformatted[$pkey]['discountAmount']), $this->_currentMethod->payment_currency); $discountAmount = -abs(round($discountInPaymentCurrency['value'] * 100, 0)); if ($cart->pricesUnformatted[$pkey]['discountAmount'] > 0.0) { $items[$i]['tax_rate'] = $items[$i - 1]['tax_rate']; } else { $items[$i]['tax_rate'] = 0.0; $tax_rate = 0.0; } $items[$i]['unit_price'] = round($discountAmount * (1 + ($tax_rate * 0.01)), 0); $this->debugLog($items[$i], 'getCartItems', 'debug'); $i++; } } if ($cart->pricesUnformatted['salesPriceCoupon']) { $items[$i]['reference'] = 'COUPON'; $items[$i]['name'] = 'Coupon discount'; $items[$i]['quantity'] = 1; $couponInPaymentCurrency = vmPSPlugin::getAmountInCurrency($cart->pricesUnformatted['salesPriceCoupon'], $this->_currentMethod->payment_currency); $items[$i]['unit_price'] = round($couponInPaymentCurrency['value'] * 100, 0); $items[$i]['tax_rate'] = 0; $this->debugLog($cart->pricesUnformatted['salesPriceCoupon'], 'getCartItems Coupon', 'debug'); $this->debugLog($items[$i], 'getCartItems', 'debug'); $i++; } if ($cart->pricesUnformatted['salesPriceShipment']) { $items[$i]['reference'] = 'SHIPPING'; $items[$i]['name'] = 'Shipping Fee'; $items[$i]['quantity'] = 1; $shipmentInPaymentCurrency = vmPSPlugin::getAmountInCurrency($cart->pricesUnformatted['salesPriceShipment'], $this->_currentMethod->payment_currency); $items[$i]['unit_price'] = round($shipmentInPaymentCurrency['value'] * 100, 0); $items[$i]['tax_rate'] = $this->getTaxShipment($cart->pricesUnformatted['shipment_calc_id']); $this->debugLog($cart->pricesUnformatted['salesPriceShipment'], 'getCartItems Shipment', 'debug'); $this->debugLog($items[$i], 'getCartItems', 'debug'); } $currency = CurrencyDisplay::getInstance($cart->paymentCurrency); return $items; } function getTaxShipment ($shipment_calc_id) { // TO DO add shipmentTaxRate in the cart // assuming there is only one rule +% $db = JFactory::getDBO(); $q = 'SELECT * FROM #__virtuemart_calcs WHERE `virtuemart_calc_id`="' . $shipment_calc_id . '" '; $db->setQuery($q); $taxrule = $db->loadObject(); if ($taxrule->calc_value_mathop != "+%") { VmError('KlarnaCheckout getTaxShipment: expecting math operation to be +% but is ' . $taxrule->calc_value_mathop); $this->debugLog(var_export($taxrule,true), 'getTaxShipment', 'debug'); $this->debugLog($q , 'getTaxShipment query', 'debug'); } return $taxrule->calc_value * 100; } function getVatTaxProduct ($vatTax) { $countRules = count($vatTax); if ($countRules == 0) { return 0; } if ($countRules > 1) { VmError('KlarnaCheckout: More then one VATax for the product:' . $countRules); } $tax = current($vatTax); if ($tax[2] != "+%") { VmError('KlarnaCheckout: expecting math operation to be +% but is ' . $tax[2]); } return $tax[1]; } function getKlarnaUrl () { if ($this->_currentMethod->server == 'beta') { return 'https://checkout.testdrive.klarna.com/checkout/orders'; } else { return 'https://checkout.klarna.com/checkout/orders'; } } function plgVmOnCheckoutAdvertise ($cart, &$payment_advertise) { if (!class_exists('Klarna_Checkout_Order')) { require_once 'klarnacheckout/library/Checkout.php'; } // check we are in the correct payment if ($this->getPluginMethods($cart->vendorId) === 0) { return FALSE; } $virtuemart_paymentmethod_id = 0; foreach ($this->methods as $this->_currentMethod) { if ($cart->virtuemart_paymentmethod_id == $this->_currentMethod->virtuemart_paymentmethod_id) { $virtuemart_paymentmethod_id = $this->_currentMethod->virtuemart_paymentmethod_id; } } if ($virtuemart_paymentmethod_id == 0 or empty($cart->products)) { return; } if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } // Check if it is the same payment_method_id as the previous one. $klarna_paymentmethod_id_active = $this->getKlarnaPaymentMethodActive(); if ($klarna_paymentmethod_id_active != $cart->virtuemart_paymentmethod_id) { JFactory::getSession()->clear('klarnacheckout', 'vm'); } $return = $this->initKlarnaParams($this->_currentMethod); if (!$return) { return; } $message = ''; $snippet = ''; $hide_BTST = true; /* if ($cart->virtuemart_shipmentmethod_id == 0) { $message = vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_SELECT_SHIPMENT_FIRST', $this->_currentMethod->payment_name); $shipmentFormFields = $this->getShipmentFormFields($cart); } else { */ Klarna_Checkout_Order::$baseUri = $this->getKlarnaUrl(); Klarna_Checkout_Order::$contentType = "application/vnd.klarna.checkout.aggregated-order-v2+json"; $klarna_checkout_order = null; $klarna_checkout_connector = Klarna_Checkout_Connector::create($this->_currentMethod->sharedsecret); $klarna_checkout_uri = $this->getKlarnaCheckoutUriFromSession(); if (!empty($klarna_checkout_uri)) { // Resume session $klarna_checkout_order = new Klarna_Checkout_Order($klarna_checkout_connector, $klarna_checkout_uri); try { $klarna_checkout_order->fetch(); // Reset cart $update['cart']['items'] = array(); $update['cart']['items'] = $this->getCartItems($cart); if (!empty($cart->BT['email'])) { $update['shipping_address']['email'] = $cart->BT['email']; $hide_BTST = false; $address = (($cart->ST == 0) ? $cart->BT : $cart->ST); if (isset($address['zip']) and !empty($address['zip'])) { $update['shipping_address']['postal_code'] = $cart->BT['zip']; } } $klarna_checkout_order->update($update); } catch (Exception $e) { // Reset session $klarna_checkout_order = null; $this->clearKlarnaSession(); } } jimport('joomla.environment.browser'); $browser = JBrowser::getInstance(); if ($klarna_checkout_order == null) { // Start new session $create['purchase_country'] = $this->country_code_2; $create['purchase_currency'] = $this->currency_code_3; $create['locale'] = $this->locale; $create['merchant']['id'] = $this->merchantid; $create['merchant']['terms_uri'] = $this->getTermsURI($cart->vendorId); $create['gui']['layout'] = $browser->isMobile() ? 'mobile' : 'desktop'; $create['merchant']['checkout_uri'] = JURI::root() . 'index.php?option=com_virtuemart&view=cart' . '&Itemid=' . JRequest::getInt('Itemid'); $create['merchant']['confirmation_uri'] = JURI::root() . 'index.php?option=com_virtuemart&view=vmplg&task=pluginresponsereceived&pm=' . $virtuemart_paymentmethod_id . '&Itemid=' . JRequest::getInt('Itemid') . '&klarna_order={checkout.order.uri}'; // You can not receive push notification on non publicly available uri $create['merchant']['push_uri'] = JURI::root() . 'index.php?option=com_virtuemart&view=vmplg&task=pluginnotification&tmpl=component&pm=' . $virtuemart_paymentmethod_id . '&klarna_order={checkout.order.uri}'; $this->getTemplateOptions($create); if (!empty($cart->BT['email'])) { $create['shipping_address']['email'] = $cart->BT['email']; $hide_BTST = false; $address = (($cart->ST == 0) ? $cart->BT : $cart->ST); if (isset($address['zip']) and !empty($address['zip'])) { $create['shipping_address']['postal_code'] = $cart->BT['zip']; } } $create['cart']['items'] = $this->getCartItems($cart, $this->_currentMethod); try { $klarna_checkout_order = new Klarna_Checkout_Order($klarna_checkout_connector); $klarna_checkout_order->create($create); $klarna_checkout_order->fetch(); } catch (Exception $e) { $this->clearKlarnaSession(); $admin_msg = $e->getMessage(); vmError($admin_msg, vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->_currentMethod->payment_name)); return NULL; } } $this->setKlarnaParamsInSession($klarna_checkout_order->getLocation(), $virtuemart_paymentmethod_id); // Display checkout $snippet = $klarna_checkout_order['gui']['snippet']; // DESKTOP: Width of containing block shall be at least 750px // MOBILE: Width of containing block shall be 100% of browser window (No // padding or margin) //} $payment_advertise[] = $this->renderByLayout('cart_advertisement', array( 'snippet' => $snippet, 'message' => $message, 'payment_form_position' => isset($this->_currentMethod->payment_form_position) ? $this->_currentMethod->payment_form_position : 'bottom', 'hide_BTST' => $hide_BTST, )); } function getShipmentFormFields ($cart) { $userFields = $cart->BTaddress; $validFields = array('virtuemart_country_id', 'zip'); foreach ($userFields['fields'] as $key => $field) { if (in_array($key, $validFields)) { $shipmentFormFields[$key] = $field; } } return $shipmentFormFields; } function getTemplateOptions (&$create) { if (!empty($this->_currentMethod->button_color)) { $create['options']['color_button'] = $this->_currentMethod->button_color; } if (!empty($this->_currentMethod->color_button_text)) { $create['options']['color_button_text'] = $this->_currentMethod->color_button_text; } if (!empty($this->_currentMethod->color_checkbox)) { $create['options']['color_checkbox'] = $this->_currentMethod->color_checkbox; } if (!empty($this->_currentMethod->color_checkbox_checkmark)) { $create['options']['color_checkbox_checkmark'] = $this->_currentMethod->color_checkbox_checkmark; } if (!empty($this->_currentMethod->color_header)) { $create['options']['color_header'] = $this->_currentMethod->color_header; } if (!empty($this->_currentMethod->color_link)) { $create['options']['color_link'] = $this->_currentMethod->color_link; } } function clearKlarnaSession () { $this->debugLog('', 'clearKlarnaSession', 'debug'); JFactory::getSession()->clear('klarnacheckout', 'vm'); } function setKlarnaParamsInSession ($klarna_checkout_uri, $virtuemart_paymentmethod_id) { $this->debugLog($klarna_checkout_uri, 'setKlarnaParamsInSession', 'debug'); $sessionData['klarna_checkout_uri'] = $klarna_checkout_uri; $sessionData['klarna_paymentmethod_id_active'] = $virtuemart_paymentmethod_id; JFactory::getSession()->set('klarnacheckout', json_encode($sessionData), 'vm'); } function getKlarnaPaymentMethodActive () { $sessionData = JFactory::getSession()->get('klarnacheckout', 0, 'vm'); if (!empty($sessionData)) { $data = (object)json_decode($sessionData, true); return $data->klarna_paymentmethod_id_active; } return NULL; } function getKlarnaCheckoutUriFromSession () { $sessionData = JFactory::getSession()->get('klarnacheckout', 0, 'vm'); $this->debugLog(var_export($sessionData, true), 'getKlarnaCheckoutUriFromSession', 'debug'); if (!empty($sessionData)) { $data = (object)json_decode($sessionData, true); return $data->klarna_checkout_uri; } return NULL; } /** * cf https://docs.klarna.com/en/rest-api#supported_locales * @param $method */ function initKlarnaParams () { $return = true; $db = JFactory::getDBO(); $q = 'SELECT ' . $db->getEscaped('country_2_code') . ' , ' . $db->getEscaped('country_3_code') . ' FROM `#__virtuemart_countries` WHERE virtuemart_country_id = ' . (int)$this->_currentMethod->purchase_country; $db->setQuery($q); $country = $db->loadObject(); if (!$country) { vmError('Klarna Checkout: No country has been found with country id=' . $this->_currentMethod->purchase_country, vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->_currentMethod->payment_name)); $this->debugLog('No country has been found with country id=' . $this->_currentMethod->purchase_country, 'initKlarnaParams', 'debug'); $return = false; } $this->country_code_2 = $country->country_2_code; $this->country_code_3 = $country->country_3_code; $this->getPaymentCurrency($this->_currentMethod); $this->currency_code_3 = shopFunctions::getCurrencyByID($this->_currentMethod->payment_currency, 'currency_code_3'); if (!$this->currency_code_3) { vmError('Klarna Checkout: No currency has been found with currency id=' . $this->_currentMethod->payment_currency, vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->_currentMethod->payment_name)); $this->debugLog('No currency has been found with currency id=' . $this->_currentMethod->payment_currency, 'initKlarnaParams', 'debug'); $return = false; } $this->currency_id = $this->_currentMethod->payment_currency; if (empty($this->_currentMethod->sharedsecret) or empty($this->_currentMethod->merchantid)) { vmError('Klarna Checkout: Missing mandatory values merchant id=' . $this->_currentMethod->merchantid . ' shared secret=' . $this->_currentMethod->sharedsecret, vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->_currentMethod->payment_name)); $this->debugLog('Missing mandatory values merchant id=' . $this->_currentMethod->merchantid . ' shared secret=' . $this->_currentMethod->sharedsecret, 'initKlarnaParams', 'debug'); $return = false; } $this->locale = $this->_currentMethod->locale; $this->sharedsecret = $this->_currentMethod->sharedsecret; $this->merchantid = $this->_currentMethod->merchantid; if ($this->_currentMethod->server == 'beta') { $this->mode = Klarna::BETA; } else { $this->mode = Klarna::LIVE; } $this->ssl = KlarnaHandler::getKlarnaSSL($this->mode); return $return; } function getTermsURI ($vendorId) { return JURI::root() . 'index.php?option=com_virtuemart&view=vendor&layout=tos&virtuemart_vendor_id=' . $vendorId . '&lang=' . vRequest::getCmd('lang', '');; } /** * @param $method plugin * @param $where from where tis function is called */ protected function renderPluginName ($method, $where = 'checkout') { $payment_logo = ""; if ($method->payment_logos) { $payment_logo = ' '; } $payment_name = $method->payment_name; $html = $this->renderByLayout('render_pluginname', array( 'where' => $where, 'logo' => $payment_logo, 'payment_name' => $payment_name, 'payment_description' => $method->payment_desc, )); return $html; } /** * @return bool|null */ /** * @param $html * @return bool|null|string */ function plgVmOnPaymentResponseReceived (&$html) { if (!class_exists('VirtueMartCart')) { require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); } if (!class_exists('shopFunctionsF')) { require(JPATH_VM_SITE . DS . 'helpers' . DS . 'shopfunctionsf.php'); } if (!class_exists('VirtueMartModelOrders')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); } if (!class_exists('Klarna_Checkout_Order')) { require_once 'klarnacheckout/library/Checkout.php'; } // check we are in the good payment $virtuemart_paymentmethod_id = vRequest::getInt('pm', 0); if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return NULL; } $this->debugLog('BOF', 'plgVmOnPaymentResponseReceived', 'debug'); $klarna_checkout_uri = JRequest::getString('klarna_order', ''); if (empty($klarna_checkout_uri)) { // not the good payment ? $this->debugLog(' because no klarna_order ', 'plgVmOnPaymentResponseReceived ', 'debug'); //return NULL; $klarna_checkout_uri = $this->getKlarnaCheckoutUriFromSession(); if (empty($klarna_checkout_uri)) { $this->debugLog('Missing klarna_checkout in session', 'plgVmOnPaymentResponseReceived ', 'debug'); return NULL; } } // fetch the order at klarna Klarna_Checkout_Order::$contentType = "application/vnd.klarna.checkout.aggregated-order-v2+json"; //$this->initKlarnaParams($this->_currentMethod); $klarna_checkout_connector = Klarna_Checkout_Connector::create($this->_currentMethod->sharedsecret); $klarna_checkout_order = new Klarna_Checkout_Order($klarna_checkout_connector, $klarna_checkout_uri); $klarna_checkout_order->fetch(); $this->debugLog($klarna_checkout_order['status'], 'plgVmOnPaymentResponseReceived ' . ' klarna status', 'debug'); if ($klarna_checkout_order['status'] == 'checkout_incomplete') { JFactory::getApplication()->redirect(JRoute::_('index.php?option=com_virtuemart&view=cart', false), vmText::_('VMPAYMENT_KLARNACHECKOUT_INCOMPLETE')); } // update the cart with klarna infos $cart = VirtueMartCart::getCart(); $this->updateBTSTAddressInCart($cart, $klarna_checkout_order); // confirm and create the order in VM $cart->_confirmDone = TRUE; $cart->_dataValidated = TRUE; $cart->tosAccepted = TRUE; $cart->confirmDone(); if (!class_exists('VirtueMartModelOrders')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); } $this->debugLog($cart->order_number, 'plgVmOnPaymentResponseReceived ' . ' confirmDone', 'debug'); $orders = new VirtueMartModelOrders(); $virtuemart_order_id = $orders->getOrderIdByOrderNumber($cart->order_number); $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($virtuemart_order_id); $update_status['order_status'] = $this->_currentMethod->status_checkout_complete; $update_status['customer_notified'] = 1; $update_status['comments'] = vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_PAYMENT_STATUS_CONFIRMED', $cart->order_number); $orderModel->updateStatusForOneOrder($virtuemart_order_id, $update_status, TRUE); $this->clearKlarnaSession(); $cart->BT=0; $cart->ST=0; $cart->emptyCart(); $cart->removeCartFromSession(); // DESKTOP: Width of containing block shall be at least 750px // MOBILE: Width of containing block shall be 100% of browser window (No // padding or margin) $html = $this->renderByLayout('response_received', array( 'snippet' => $klarna_checkout_order['gui']['snippet'], 'order_number' => $order['details']['BT']->order_number, 'order_pass' => $order['details']['BT']->order_pass )); return TRUE; } /** * * Is triggered when doing $cart->confirmDone() which is done in plgVmOnPaymentResponseReceived * @param $cart * @param $order * @return bool|null */ function plgVmConfirmedOrder ($cart, $order) { // include what we need if (!class_exists('Klarna_Checkout_Order')) { require_once 'klarnacheckout/library/Checkout.php'; } // check if we should be triggered if (!($this->_currentMethod = $this->getVmPluginMethod($order['details']['BT']->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return FALSE; } $this->debugLog('', 'plgVmConfirmedOrder', 'debug'); // fetch klarna order Klarna_Checkout_Order::$baseUri = $this->getKlarnaUrl(); Klarna_Checkout_Order::$contentType = "application/vnd.klarna.checkout.aggregated-order-v2+json"; $klarna_checkout_connector = Klarna_Checkout_Connector::create($this->_currentMethod->sharedsecret); $klarna_checkout_uri = $this->getKlarnaCheckoutUriFromSession(); $klarna_order_uri = JRequest::getString('klarna_order', ''); if (empty($klarna_order_uri)) { // not the good payment ? return NULL; } $klarna_checkout_order = new Klarna_Checkout_Order($klarna_checkout_connector, $klarna_order_uri); $klarna_checkout_order->fetch(); // store data in VM payment table $dbValues['order_number'] = $order['details']['BT']->order_number; $dbValues['virtuemart_paymentmethod_id'] = $cart->virtuemart_paymentmethod_id; $dbValues['payment_name'] = $this->renderPluginName($this->_currentMethod, $order); $dbValues['payment_order_total'] = $klarna_checkout_order['cart']['total_price_including_tax'] / 100; $dbValues['payment_currency'] = ShopFunctions::getCurrencyIDByName($klarna_checkout_order['purchase_currency']);; $dbValues['email_currency'] = $this->getEmailCurrency($this->_currentMethod); $dbValues['klarna_id'] = $klarna_checkout_order['id']; $dbValues['klarna_status'] = $klarna_checkout_order['status']; $dbValues['klarna_reservation'] = $klarna_checkout_order['reservation']; $dbValues['klarna_reference'] = $klarna_checkout_order['reference']; $dbValues['klarna_started_at'] = $klarna_checkout_order['started_at']; $dbValues['klarna_completed_at'] = $klarna_checkout_order['completed_at']; $dbValues['klarna_expires_at'] = $klarna_checkout_order['expires_at']; $dbValues['format'] = 'none'; $this->debugLog(var_export($dbValues, true), 'plgVmConfirmedOrder storePSPluginInternalData', 'debug'); $this->storePSPluginInternalData($dbValues); } /** * @return bool|null */ function plgVmOnPaymentNotification () { if (!class_exists('Klarna_Checkout_Order')) { require_once 'klarnacheckout/library/Checkout.php'; } if (!class_exists('VirtueMartModelOrders')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); } $virtuemart_paymentmethod_id = vRequest::getInt('pm', ''); $klarna_checkout_uri = vRequest::getString('klarna_order', ''); if (preg_match("/\/([^\/]+)$/", $klarna_checkout_uri, $match)) { $klarna_checkout_id = $match[1]; } else { return NULL; } if (empty($virtuemart_paymentmethod_id) or !$this->selectedThisByMethodId($virtuemart_paymentmethod_id) or empty($klarna_checkout_uri)) { return NULL; } if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } sleep(2); $this->debugLog('here', 'plgVmOnPaymentNotification', 'debug'); Klarna_Checkout_Order::$contentType = "application/vnd.klarna.checkout.aggregated-order-v2+json"; $this->initKlarnaParams(); $klarna_checkout_connector = Klarna_Checkout_Connector::create($this->sharedsecret); $klarna_checkout_order = new Klarna_Checkout_Order($klarna_checkout_connector, $klarna_checkout_uri); $klarna_checkout_order->fetch(); $this->debugLog('fetch order', 'plgVmOnPaymentNotification', 'debug'); if ($klarna_checkout_order['status'] != "checkout_complete") { $this->debugLog($klarna_checkout_order, 'plgVmOnPaymentNotification Klarna_Checkout_Order', 'debug'); //return NULL; } // find the saved data in payment table $vm_payment_data = $this->getDataByKlarnaID($klarna_checkout_id); $this->debugLog(var_export($vm_payment_data, true), 'plgVmOnPaymentNotification getDataByKlarnaID', 'debug'); if ($vm_payment_data == NULL) { // will push again later // the order was not yet saved, will push again later return; } // send order number to klarna $klarna_update['status'] = 'created'; $klarna_update['merchant_reference'] = array( 'orderid1' => $vm_payment_data['order_number'] ); $klarna_checkout_order->update($klarna_update); // update vm payment table $db_values['virtuemart_order_id'] = $vm_payment_data['virtuemart_order_id']; $db_values['order_number'] = $vm_payment_data['order_number']; $db_values['klarna_status'] = $klarna_update['status']; $db_values['data'] = json_encode($klarna_update); $dbValues['format'] = 'json'; $this->storePluginInternalData($db_values); /* // update VM order status and send an email to client $modelOrder = VmModel::getModel('orders'); $order['customer_notified'] = 1; $order['order_status'] = $this->_currentMethod->status_checkout_complete; $order['comments'] = vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_PAYMENT_STATUS_CONFIRMED', $vm_payment_data['order_number']); $modelOrder->updateStatusForOneOrder($vm_payment_data['virtuemart_order_id'], $order, TRUE); */ } /** * Create the VM order with the saved cart, and the users infos from klarna * @param $klarna_order return data from Klarna * @param $cartData cart json_decoded saved in the table * @param $method * @param $cartId pkey of the cart saved in the table * */ function updateBTSTAddressInCart ($cart, $klarna_checkout_order) { $this->updateAddressInCart($cart, $klarna_checkout_order['billing_address'], 'BT'); $this->updateAddressInCart($cart, $klarna_checkout_order['shipping_address'], 'ST'); } function updateAddressInCart ($cart, $klarna_address, $address_type) { if ($address_type == 'BT') { $prefix = ''; $vmAddress = $cart->BT; } else { $prefix = 'shipto_'; $vmAddress = $cart->ST; } // Update the Shipping Address to what is specified in the register. $update_data = array( $prefix . 'address_type_name' => 'klarnacheckout', $prefix . 'company' => $klarna_address['company_name'], $prefix . 'first_name' => $klarna_address['given_name'], $prefix . 'last_name' => $klarna_address['family_name'], $prefix . 'address_1' => $klarna_address['street_address'], $prefix . 'zip' => $klarna_address['postal_code'], $prefix . 'city' => $klarna_address['city'], $prefix . 'virtuemart_country_id' => shopFunctions::getCountryIDByName($klarna_address['country']), $prefix . 'state' => '', $prefix . 'phone_1' => $klarna_address['phone'], 'address_type' => $address_type ); if ($address_type == 'BT') { $update_data ['email'] = $klarna_address['email']; } if (!empty($st)) { $update_data = array_merge($vmAddress, $update_data); } $cart->saveAddressInCart($update_data, $update_data['address_type'], FALSE); } function getKlarnaData ($klarna_order) { $push_params = $this->getKlarnaDisplayParams(); foreach ($push_params as $key => $value) { $klarna_data[$key] = $klarna_order[$key]; } return $klarna_data; } function getKlarnaDisplayParams () { return array( 'id' => 'debug', 'purchase_country' => 'display', 'purchase_currency' => 'display', 'locale' => 'debug', 'status' => 'display', 'reference' => 'display', 'reservation' => 'display', 'started_at' => 'debug', 'completed_at' => 'debug', 'last_modified_at' => 'debug', 'expires_at' => 'debug', 'cart' => 'debug', 'customer' => 'debug', 'shipping_address' => 'debug', 'billing_address' => 'debug', 'options' => 'debug', 'merchant' => 'debug', ); } /** * @param $virtuemart_paymentmethod_id * @param $paymentCurrencyId * @return bool|null */ function plgVmgetEmailCurrency ($virtuemart_paymentmethod_id, $virtuemart_order_id, &$emailCurrencyId) { if (!($this->method = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->method->payment_element)) { return FALSE; } if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) { return ''; } if (empty($payments[0]->email_currency)) { $vendorId = 1; //VirtueMartModelVendor::getLoggedVendor(); $db = JFactory::getDBO(); $q = 'SELECT `vendor_currency` FROM `#__virtuemart_vendors` WHERE `virtuemart_vendor_id`=' . $vendorId; $db->setQuery($q); $emailCurrencyId = $db->loadResult(); } else { $emailCurrencyId = $payments[0]->email_currency; } } /** * @param $virtuemart_paymentmethod_id * @param $paymentCurrencyId * @return bool|null */ function plgVmgetPaymentCurrency ($virtuemart_paymentmethod_id, &$paymentCurrencyId) { if (!($this->method = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->method->payment_element)) { return FALSE; } $this->getPaymentCurrency($this->method); $paymentCurrencyId = $this->method->payment_currency; } /** * Display stored payment data for an order * @param int $virtuemart_order_id * @param int $payment_method_id * @see components/com_virtuemart/helpers/vmPSPlugin::plgVmOnShowOrderBEPayment() */ function plgVmOnShowOrderBEPayment ($virtuemart_order_id, $payment_method_id) { if (!$this->selectedThisByMethodId($payment_method_id)) { return NULL; // Another method was selected, do nothing } if (!($this->_currentMethod = $this->getVmPluginMethod($payment_method_id))) { return NULL; // Another method was selected, do nothing } if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) { // JError::raiseWarning(500, $db->getErrorMsg()); return ''; } $html = '' . "\n"; $html .= $this->getHtmlHeaderBE(); $first = TRUE; $code = "klarna"; $prefix = "KLARNACHECKOUT_"; foreach ($payments as $payment) { if ($payment->klarna_status != 'created') { $html .= ''; // Now only the first entry has this data when creating the order if ($first) { $html .= $this->getHtmlRowBE('KLARNACHECKOUT_PAYMENT_NAME', $payment->payment_name); // keep that test to have it backwards compatible. Old version was deleting that column when receiving an IPN notification if ($payment->payment_order_total and $payment->payment_order_total != 0.00) { $html .= $this->getHtmlRowBE('KLARNACHECKOUT_PAYMENT_ORDER_TOTAL', $payment->payment_order_total . " " . shopFunctions::getCurrencyByID($payment->payment_currency, 'currency_code_3')); } if ($payment->email_currency and $payment->email_currency != 0) { $html .= $this->getHtmlRowBE('KLARNACHECKOUT_PAYMENT_EMAIL_CURRENCY', shopFunctions::getCurrencyByID($payment->email_currency, 'currency_code_3')); } $first = FALSE; } if ($payment->action) { $display_action = 'onShowOrderBE_' . $payment->action; $row_html = $this->$display_action($payment); if ($row_html) { //$html .= ''; $html .= $row_html; } } else { // TODO go though the SQL table to have the fields in the correct order foreach ($payment as $key => $value) { // only displays if there is a value or the value is different from 0.00 and the value if ($value) { if (substr($key, 0, strlen($code)) == $code) { $html .= $this->getHtmlRowBE($prefix . $key, $value); } } } } } } $html .= '
' . JText::_('VMPAYMENT_KLARNACHECKOUT_DATE') . '' . $payment->created_on . '
' . vmText::_('VMPAYMENT_KLARNACHECKOUT_DATE') . '' . $payment->created_on . '
' . "\n"; return $html; } function onShowOrderBE_activate ($payment) { if (!class_exists('VirtueMartModelOrders')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); } $html = $this->getHtmlRowBE(vmText::_('VMPAYMENT_KLARNACHECKOUT_STATUS'), $payment->klarna_status); $activate_data = $this->getStoredData($payment); $html .= $this->getHtmlRowBE(vmText::_('VMPAYMENT_KLARNACHECKOUT_INVOICE_NUMBER'), $activate_data->InvoiceNumber); if (!empty($activate_data->InvoicePdf)) { $invoicePdfLink = $this->getInvoicePdfLink($payment->virtuemart_order_id); $value = '' . vmText::_('VMPAYMENT_KLARNACHECKOUT_VIEW_INVOICE') . ''; $html .= $this->getHtmlRowBE("", $value); } return $html; } function onShowOrderBE_update ($payment) { $html = $this->getHtmlRowBE(vmText::_('VMPAYMENT_KLARNACHECKOUT_STATUS'), $payment->klarna_status); return $html; } function onShowOrderBE_cancelReservation ($payment) { return $this->getHtmlRowBE(vmText::_('VMPAYMENT_KLARNACHECKOUT_STATUS'), $payment->klarna_status); } /** * @param $type * @param $name * @param $render */ function plgVmOnSelfCallBE ($type, $name, &$render) { if ($name != $this->_name || $type != 'vmpayment') { return FALSE; } // fetches PClasses From XML file $call = vRequest::getCmd('call'); $this->$call(); // jexit(); } function onShowOrderBE_createOrder ($payment) { // we don't need to show that to merchant return; if ($this->_currentMethod->debug) { $show_fields = array("display", "debug"); } else { $show_fields = array("display"); } if (empty($payment->data)) { $html = "\n" . vmText::_('id') . "\n " . 'ERROR NO DATA' . "\n\n"; } else { $klarna_order = $this->getStoredData($payment); //$klarna_order = ($payment->data); $push_params = $this->getKlarnaDisplayParams(); $html = ''; $lang = JFactory::getLanguage(); foreach ($push_params as $key => $value) { if (in_array($value, $show_fields)) { $display_value = isset($klarna_order->$key) ? $klarna_order->$key : "???"; $text_key = strtoupper('VMPAYMENT_KLARNACHECKOUT_' . $key); if ($lang->hasKey($text_key)) { $text = vmText::_('VMPAYMENT_KLARNACHECKOUT_' . $key); } else { $text = $key; } if (!is_array($display_value)) { $html .= "\n" . $text . "\n " . $display_value . "\n\n"; } else { $html .= "\n" . $text . "\n \n\n"; foreach ($klarna_order->$key as $order_key => $order_value) { $text_key = strtoupper('VMPAYMENT_KLARNACHECKOUT_' . $order_key); if ($lang->hasKey($text_key)) { $text = vmText::_('VMPAYMENT_KLARNACHECKOUT_' . $order_key); } else { $text = $order_key; } if (!is_array($order_value)) { $display_order_value = isset($klarna_order->$key->$order_key) ? $klarna_order->$key->$order_key : "????"; $html .= "\n" . $text . "\n " . $display_order_value . "\n\n"; } else { $html .= "\n" . $text . "\n
" . var_export($klarna_order->$key->$order_key, true) . "
\n\n"; } } } } } } return $html; } function getStoredData ($payment) { if ($payment->format == 'json') { $data = (object)json_decode($payment->data, true); } elseif ($payment->format == 'none') { return $payment; } else { $data = unserialize($payment->data); } return $data; } /** * * Can be usefull for debugging * @param $payment * @return string */ function onShowOrderBE_storeCart ($payment) { return NULL; } /** * Check if the payment conditions are fulfilled for this payment method * * @author: Valerie Isaksen * * @param $cart_prices : cart prices * @param $payment * @return true: if the conditions are fulfilled, false otherwise * */ protected function checkConditions ($cart, $method, $cart_prices) { $this->convert($method); $address = $cart->BT; $amount = $cart_prices['salesPrice']; $amount_cond = ($amount >= $method->min_amount AND $amount <= $method->max_amount OR ($method->min_amount <= $amount AND ($method->max_amount == 0))); $countries = array(); if (!empty($method->purchase_country)) { if (!is_array($method->purchase_country)) { $countries[0] = $method->purchase_country; } else { $countries = $method->purchase_country; } } // probably did not gave his BT:ST address if (!is_array($address)) { $address = array(); $address['virtuemart_country_id'] = 0; } if (!isset($address['virtuemart_country_id'])) { $address['virtuemart_country_id'] = 0; } if ((!empty($address) or $address['virtuemart_country_id'] != 0) and in_array($address['virtuemart_country_id'], $countries) || count($countries) == 0) { if ($amount_cond) { return TRUE; } } elseif (empty($address) or $address['virtuemart_country_id'] == 0) { if ($amount_cond) { return TRUE; } } return FALSE; } /** * @param $method */ function convert ($method) { $method->min_amount = (float)$method->min_amount; $method->max_amount = (float)$method->max_amount; } /** * We must reimplement this triggers for joomla 1.7 */ /** * Create the table for this plugin if it does not yet exist. * This functions checks if the called plugin is active one. * When yes it is calling the standard method to create the tables * * @author Valérie Isaksen * */ function plgVmOnStoreInstallPaymentPluginTable ($jplugin_id) { return $this->onStoreInstallPluginTable($jplugin_id); } /** * This event is fired after the payment method has been selected. It can be used to store * additional payment info in the cart. * * @author Valérie isaksen * * @param VirtueMartCart $cart : the actual cart * @return null if the payment was not selected, true if the data is valid, error message if the data is not vlaid * */ public function plgVmOnSelectCheckPayment (VirtueMartCart $cart, &$msg) { if (!$this->selectedThisByMethodId($cart->virtuemart_paymentmethod_id)) { return NULL; // Another method was selected, do nothing } return true; } /** * @param VirtueMartCart $cart * @param array $cart_prices * @param $cart_prices_name * @return bool|null */ public function plgVmOnSelectedCalculatePricePayment (VirtueMartCart $cart, array &$cart_prices, &$cart_prices_name) { return $this->onSelectedCalculatePrice($cart, $cart_prices, $cart_prices_name); } /** * plgVmOnCheckAutomaticSelectedPayment * Checks how many plugins are available. If only one, the user will not have the choice. Enter edit_xxx page * The plugin must check first if it is the correct type * * @author Valerie Isaksen * @param VirtueMartCart cart: the cart object * @return null if no plugin was found, 0 if more then one plugin was found, virtuemart_xxx_id if only one plugin is found * */ function plgVmOnCheckAutomaticSelectedPayment (VirtueMartCart $cart, array $cart_prices = array(), &$paymentCounter) { return $this->onCheckAutomaticSelected($cart, $cart_prices, $paymentCounter); } /** * This method is fired when showing the order details in the frontend. * It displays the method-specific data. * * @param integer $order_id The order ID * @return mixed Null for methods that aren't active, text (HTML) otherwise * @author Valerie Isaksen */ public function plgVmOnShowOrderFEPayment ($virtuemart_order_id, $virtuemart_paymentmethod_id, &$payment_name) { $this->onShowOrderFE($virtuemart_order_id, $virtuemart_paymentmethod_id, $payment_name); } /** * This method is fired when showing when priting an Order * It displays the the payment method-specific data. * * @param integer $_virtuemart_order_id The order ID * @param integer $method_id method used for this order * @return mixed Null when for payment methods that were not selected, text (HTML) otherwise * @author Valerie Isaksen */ function plgVmonShowOrderPrintPayment ($order_number, $method_id) { return $this->onShowOrderPrint($order_number, $method_id); } /** * Triggered by updateStatusForOneOrder * When status= pre delivery, possible action CancelReservation or ChangeReservation * When status= delivery, possible action ActivateReservation * When status= post delivery, possible action CreditInvoice, Return Amount, CreditPart * * @param array $order order data * @return mixed, True on success, false on failures (the rest of the save-process will be * skipped!), or null when this method is not actived. */ public function plgVmOnUpdateOrderPayment (&$order, $old_order_status) { // get latest info from DB /*if (!$this->selectedThisByMethodId($order->virtuemart_paymentmethod_id)) { return NULL; // Another method was selected, do nothing }*/ if (!($this->_currentMethod = $this->getVmPluginMethod($order->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return NULL; } if (!($payments = $this->getDatasByOrderId($order->virtuemart_order_id))) { return NULL; } //plgVmPaymentKlarnaCheckout::includeKlarnaFiles(); $new_order_status = $order->order_status; $lastPayment = $payments[(count($payments)) - 1]; $klarna_status = $lastPayment->klarna_status; $actions = array('activate', 'cancelReservation', 'changeReservation', 'creditInvoice'); foreach ($actions as $action) { $status = 'status_' . $action; //vmError($action.' '.$this->method->$status.' '.$new_order_status); if ($this->_currentMethod->$status == $new_order_status and $this->authorizedAction($klarna_status, $new_order_status, $old_order_status, $action, $this->_currentMethod)) { $this->$action($order, $payments); return true; } } // may be it is another new order status unknown? // TO DO ... how can we disply that when not in push //vmError(vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ACTION_NOT_AUTHORIZED', $new_order_status, $lastPayment->klarna_status), vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->method->payment_name)); //$this->debugLog(vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ACTION_NOT_AUTHORIZED', $action, $lastPayment->klarna_status), 'plgVmOnUpdateOrderPayment', 'debug'); // true means plugin call was successfull return true; } function authorizedAction ($klarna_status, $new_order_status, $old_order_status, $action) { if ($old_order_status == $this->_currentMethod->status_checkout_complete) { $authorize = array( 'cancelReservation' => $this->_currentMethod->status_cancelReservation, 'changeReservation' => $this->_currentMethod->status_changeReservation, 'activate' => $this->_currentMethod->status_activate, ); if (in_array($new_order_status, $authorize)) { return TRUE; } } elseif ($old_order_status == $this->_currentMethod->status_activate) { $authorize = array( 'creditInvoice' => $this->_currentMethod->status_creditInvoice, 'returnAmount' => $this->_currentMethod->status_returnAmount, 'creditPart' => $this->_currentMethod->status_creditPart, ); if (in_array($new_order_status, $authorize)) { return TRUE; } } return FALSE; } /** * The following variables are no longer order specific and should be fixed: * pclass, -1 for all Klarna Checkout orders * pno, null for all Klarna Checkout orders * @param $order * @param $method * @param $payments * @return bool */ function activate ($order, $payments) { $rno = $this->getReservationNumber($payments); if (!$rno) { return; // error already sent } // TO DO ASK KLARNA ABOUT KLARNA MODE //$mode = KlarnaHandler::getKlarnaMode($method, $this->getPurchaseCountry($method)); //$ssl = KlarnaHandler::getKlarnaSSL($mode); // Instantiate klarna object. $this->initKlarnaParams($this->_currentMethod); $klarna = new Klarna_virtuemart(); $klarna->config($this->merchantid, $this->sharedsecret, $this->country_code_3, NULL, $this->currency_code_3, $this->mode, VMKLARNA_PC_TYPE, KlarnaHandler::getKlarna_pc_type(), $this->ssl); $modelOrder = VmModel::getModel('orders'); try { $return = $klarna->activate($rno); if ($return[0] == 'ok') { VmInfo(vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ACTIVATE_RESERVATION', $rno)); $vm_invoice_name = ''; $invoice_number = $return[1]; $invoiceURL = $this->getInvoice($invoice_number, $vm_invoice_name); $history = array(); $history['customer_notified'] = 0; $history['order_status'] = $this->_currentMethod->status_activate; $history['comments'] = vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_PAYMENT_STATUS_ACTIVATE', $rno); // $order['details']['BT']->order_number); $modelOrder->updateStatusForOneOrder($order->virtuemart_order_id, $history, TRUE); $dbValues['order_number'] = $order->order_number; $dbValues['virtuemart_order_id'] = $order->virtuemart_order_id; $dbValues['payment_name'] = ''; $dbValues['virtuemart_paymentmethod_id'] = $payments[0]->virtuemart_paymentmethod_id; $dbValues['action'] = 'activate'; $dbValues['klarna_status'] = 'activate'; $data["InvoiceNumber"] = $invoice_number; $data["InvoicePdf"] = $invoiceURL; $dbValues['format'] = 'json'; $dbValues['data'] = json_encode($data); $values = $this->storePSPluginInternalData($dbValues); } else { VmError('activate returned KO', vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->method->payment_name)); } } catch (Exception $e) { VmError($e->getMessage(), vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->method->payment_name)); $this->debugLog($e->getMessage(), 'activate', 'debug'); return FALSE; } return true; } /** * */ function cancelReservation ($order, $payments) { $rno = $this->getReservationNumber($payments); if (!$rno) { return; // error already sent } $this->initKlarnaParams($this->_currentMethod); $klarna = new Klarna_virtuemart(); $klarna->config($this->merchantid, $this->sharedsecret, $this->country_code_3, NULL, $this->currency_code_3, $this->mode, VMKLARNA_PC_TYPE, KlarnaHandler::getKlarna_pc_type(), $this->ssl); $modelOrder = VmModel::getModel('orders'); try { $result = $klarna->cancelReservation($rno); $info = vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_RESERVATION_CANCELED', $rno); VmInfo($info); $history = array(); $history['customer_notified'] = 1; //$history['order_status'] = $this->method->checkout_complete; $history['comments'] = $info; // $order['details']['BT']->order_number); $modelOrder->updateStatusForOneOrder($order->virtuemart_order_id, $history, TRUE); $dbValues['order_number'] = $order->order_number; $dbValues['virtuemart_order_id'] = $order->virtuemart_order_id; $dbValues['payment_name'] = ''; $dbValues['virtuemart_paymentmethod_id'] = $payments[0]->virtuemart_paymentmethod_id; $dbValues['action'] = 'cancelReservation'; $dbValues['klarna_status'] = 'cancelReservation'; $dbValues['data'] = $info; $dbValues['format'] = 'none'; $this->debugLog($dbValues, 'storePSPluginInternalData cancelReservation', 'debug'); $values = $this->storePSPluginInternalData($dbValues); } catch (Exception $e) { $error = $e->getMessage(); VmError($e->getMessage(), vmText::sprintf('VMPAYMENT_KLARNACHECKOUT_ERROR_OCCURRED', $this->method->payment_name)); $this->debugLog($e->getMessage(), 'cancelReservation', 'debug'); return FALSE; } //$dbValues['data'] = $vm_invoice_name; return true; } function changeReservation () { } function creditInvoice () { } function creditPart () { } function getReservationNumber ($payments) { foreach ($payments as $payment) { if ($payment->klarna_status == "checkout_complete") { $klarna_order = $this->getStoredData($payment); // BC if (isset($klarna_order->reservation)) { return $klarna_order->reservation; } else { return $klarna_order->klarna_reservation; } } } vmError('VMPAYMENT_KLARNACHECKOUT_ERROR_NO_RNO', 'VMPAYMENT_KLARNACHECKOUT_ERROR_NO_RNO'); return null; } /** * @param $orderDetails */ function plgVmOnUserOrder (&$orderDetails) { // the order has not been created, the payment table has not been updated return; if (!($this->_currentMethod = $this->getVmPluginMethod($orderDetails->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return NULL; } $klarna_checkout_uri = vRequest::getString('klarna_order', ''); if (preg_match("/\/([^\/]+)$/", $klarna_checkout_uri, $match)) { $klarna_checkout_id = $match[1]; } else { return NULL; } if (!($payment = $this->getDataByKlarnaID($klarna_checkout_id))) { return NULL; } if ($payment->klarna_status == "checkout_complete") { $orderDetails->order_number = $payment->klarna_reservation; } return NULL; } /** * @param $orderDetails * @param $data * @return null */ function plgVmOnUserInvoice ($orderDetails, &$data) { if (!($this->method = $this->getVmPluginMethod($orderDetails['virtuemart_paymentmethod_id']))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->method->payment_element)) { return NULL; } $data['invoice_number'] = 'reservedByPayment_' . $orderDetails['order_number']; // Never send the invoice via email } /** * Save updated orderline data to the method specific table * * @param array $_formData Form data * @return mixed, True on success, false on failures (the rest of the save-process will be * skipped!), or null when this method is not actived. */ public function plgVmOnUpdateOrderLine ($_formData) { return null; } /** * plgVmOnEditOrderLineBE * This method is fired when editing the order line details in the backend. * It can be used to add line specific package codes * * @param integer $_orderId The order ID * @param integer $_lineId * @return mixed Null for method that aren't active, text (HTML) otherwise * * public function plgVmOnEditOrderLineBE( $_orderId, $_lineId) { * return null; * } */ /** * This method is fired when showing the order details in the frontend, for every orderline. * It can be used to display line specific package codes, e.g. with a link to external tracking and * tracing systems * * @param integer $_orderId The order ID * @param integer $_lineId * @return mixed Null for method that aren't active, text (HTML) otherwise * * public function plgVmOnShowOrderLineFE( $_orderId, $_lineId) { * return null; * } */ function plgVmDeclarePluginParamsPayment ($name, $id, &$data) { return $this->declarePluginParams('payment', $name, $id, $data); } /** * @param $name * @param $id * @param $table * @return bool */ function plgVmSetOnTablePluginParamsPayment ($name, $id, &$table) { return $this->setOnTablePluginParams($name, $id, $table); } /** * @return mixed */ function _getVendorCurrencyId () { if (!class_exists('VirtueMartModelVendor')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'vendor.php'); } $vendor_id = 1; $vendor_currency = VirtueMartModelVendor::getVendorCurrency($vendor_id); return $vendor_currency->virtuemart_currency_id; } /** * */ static function includeKlarnaFiles () { require(JPATH_ROOT . DS . 'plugins' . DS . 'vmpayment' . DS . 'klarna' . DS . 'klarna' . DS . 'helpers' . DS . 'define.php'); if (!class_exists('KlarnaHandler')) { require(JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarnahandler.php'); } if (!class_exists('klarna_virtuemart')) { require(JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarna_virtuemart.php'); } require_once(JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'api' . DS . 'transport' . DS . 'xmlrpc-3.0.0.beta' . DS . 'lib' . DS . 'xmlrpc.inc'); require_once(JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'api' . DS . 'transport' . DS . 'xmlrpc-3.0.0.beta' . DS . 'lib' . DS . 'xmlrpc_wrappers.inc'); } /** * @param $klarna_invoice_pdf * @param $vm_invoice_name * @return bool */ function getInvoice ($invoice_number, &$vm_invoice_name) { //$klarna_invoice = explode ('/', $klarna_invoice_pdf); if ($this->method->server == 'live') { $klarna_invoice_name = "https://online.klarna.com/packslips/" . $invoice_number . '.pdf'; } else { $klarna_invoice_name = "https://online.testdrive.klarna.com/packslips/" . $invoice_number . '.pdf'; } $vm_invoice_name = 'klarna_' . $invoice_number . '.pdf'; return $klarna_invoice_name; } /** * @return int|null|string */ function getInvoicePdfLink ($virtuemart_order_id) { if (!class_exists('VirtueMartModelOrders')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); } if (!class_exists('JFile')) { require(JPATH_SITE . DS . 'libraries' . DS . 'joomla' . DS . 'filesystem' . DS . 'file.php'); } if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) { return ''; } foreach ($payments as $payment) { if ($payment->klarna_status == 'activate') { $data = $this->getStoredData($payment); $path = VmConfig::get('forSale_path', 0); $path .= 'invoices' . DS; $fileName = $data->InvoicePdf; break; } } return $fileName; } function getDataByKlarnaID ($klarna_id) { $db = JFactory::getDBO(); $q = 'SELECT * FROM `' . $this->_tablename . '` WHERE `klarna_id` = \'' . $klarna_id . '\''; $db->setQuery($q); $paymentData = $db->loadAssoc(); $this->debugLog($q, 'getDataByKlarnaID', 'debug'); $this->debugLog(var_export($paymentData, true), 'getDataByKlarnaID', 'debug'); return $paymentData; } } // No closing tag