AAAAhome/academiac/www/plugins/vmpayment/klarna/klarna.php 0000604 00000206122 15137551725 0017153 0 ustar 00 _loggable = TRUE;
$this->tableFields = array_keys ($this->getTableSQLFields ());
$this->_tablepkey = 'id';
$this->_tableId = 'id';
$varsToPush = $this->getVarsToPush ();
$this->setConfigParameterable ($this->_configTableFieldName, $varsToPush);
$jlang = JFactory::getLanguage ();
$jlang->load ('plg_vmpayment_klarna', JPATH_ADMINISTRATOR, 'en-GB', TRUE);
$jlang->load ('plg_vmpayment_klarna', JPATH_ADMINISTRATOR, $jlang->getDefault (), TRUE);
$jlang->load ('plg_vmpayment_klarna', JPATH_ADMINISTRATOR, NULL, TRUE);
}
/**
* @return string
*/
public function getVmPluginCreateTableSQL () {
return $this->createTableSQL ('Payment Klarna Table');
}
/**
* @return array
*/
function getTableSQLFields () {
$SQLfields = array(
'id' => 'int(11) UNSIGNED NOT NULL AUTO_INCREMENT',
'virtuemart_order_id' => 'int(1) UNSIGNED',
'order_number' => ' char(64)',
'virtuemart_paymentmethod_id' => 'mediumint(1) UNSIGNED',
'payment_name' => 'varchar(5000)',
'payment_order_total' => 'decimal(15,5) NOT NULL DEFAULT \'0.00000\'',
'payment_fee' => 'decimal(10,2)',
'tax_id' => 'smallint(1)',
'klarna_eid' => 'int(10)',
'klarna_status_code' => 'tinyint(4)',
'klarna_status_text' => 'varchar(255)',
'klarna_invoice_no' => 'varchar(255)',
'klarna_log' => 'varchar(255)',
'klarna_pclass' => 'int(1)',
'klarna_pdf_invoice' => 'varchar(512)',
);
return $SQLfields;
}
/**
* @param $name
* @param $id
* @param $data
* @return bool
*/
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);
}
/**
* @param $product
* @param $productDisplay
* @return bool
*/
function plgVmOnProductDisplayPayment ($product, &$productDisplay) {
$vendorId = 1;
if ($this->getPluginMethods ($vendorId) === 0) {
return FALSE;
}
if (!class_exists ('klarna_productPrice')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarna_productprice.php');
}
if (!class_exists ('VirtueMartCart')) {
require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php');
}
$cart = VirtueMartCart::getCart ();
foreach ($this->methods as $method) {
$type = NULL;
$cData = KlarnaHandler::getcData ($method, $this->getCartAddress ($cart, $type, FALSE));
if ($cData['active'] and in_array ('part', $cData['payments_activated'])) {
//if (!empty($product->prices)) { // no price is set
if (!empty($product->prices['salesPrice'])) {
$productPrice = new klarna_productPrice($cData);
if ($productViewData = $productPrice->showProductPrice ($product, $cart)) {
$productDisplayHtml = $this->renderByLayout ('productprice_layout', $productViewData, $method->payment_element, 'payment');
$productDisplay[] = $productDisplayHtml;
}
}
}
}
return TRUE;
}
/*
*
*/
/**
* @param $cart
* @param $countryCode
* @param $countryId
* @param string $fld
*/
function _getCountryCode ($cart = NULL, &$countryCode, &$countryId, $fld = 'country_3_code') {
if ($cart == '') {
if (!class_exists ('VirtueMartCart')) {
require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php');
}
$cart = VirtueMartCart::getCart ();
}
$type = NULL;
$address = $this->getCartAddress ($cart, $type, FALSE);
if (JRequest::getVar ('klarna_country_2_code') == 'se') {
$countryId = ShopFunctions::getCountryIDByName ('se');
$countryCode = shopFunctions::getCountryByID ($countryId, $fld);
} elseif (!isset($address['virtuemart_country_id']) or empty($address['virtuemart_country_id'])) {
$countryCode = KlarnaHandler::getVendorCountry ($fld);
$countryId = ShopFunctions::getCountryIDByName ($countryCode);
} else {
$countryId = $address['virtuemart_country_id'];
$countryCode = shopFunctions::getCountryByID ($address['virtuemart_country_id'], $fld);
}
}
/**
* @param $cart
* @param $type
* @param bool $STsameAsBT
* @return mixed
*/
function getCartAddress ($cart, &$type, $STsameAsBT = TRUE) {
if (VMKLARNA_SHIPTO_SAME_AS_BILLTO) {
$st = $cart->BT;
$type = 'BT';
if ($STsameAsBT and $cart->ST and !$cart->STsameAsBT) {
vmInfo (JText::_ ('VMPAYMENT_KLARNA_SHIPTO_SAME_AS_BILLTO'));
$cart->STsameAsBT = 1;
$cart->setCartIntoSession ();
}
} elseif ($cart->BT == 0 or empty($cart->BT)) {
$st = $cart->BT;
$type = 'BT';
} else {
$st = $cart->ST;
$type = 'ST';
}
return $st;
}
/**
* @param VirtueMartCart $cart
* @param string $fld
* @return null
*/
function _getCartAddressCountryId (VirtueMartCart $cart, $fld = 'country_3_code') {
$type = "";
$address = $this->getCartAddress ($cart, $type, FALSE);
if (!isset($address['virtuemart_country_id'])) {
return NULL;
}
return $address['virtuemart_country_id'];
}
/**
* @param $virtuemart_order_id
* @param string $fld
* @return string
*/
function getCountryCodeByOrderId ($virtuemart_order_id, $fld = 'country_3_code') {
$db = JFactory::getDBO ();
$q = 'SELECT `virtuemart_country_id`, `address_type` FROM #__virtuemart_order_userinfos WHERE virtuemart_order_id=' . $virtuemart_order_id;
$db->setQuery ($q);
$results = $db->loadObjectList ();
if (count ($results) == 1) {
$virtuemart_country_id = $results[0]->virtuemart_country_id;
} else {
foreach ($results as $result) {
if ($result->address_type == 'ST') {
$virtuemart_country_id = $result->virtuemart_country_id;
break;
}
}
}
return shopFunctions::getCountryByID ($virtuemart_country_id, $fld);
}
/**
* plgVmDisplayListFEPayment
* This event is fired to display the plugin methods in the cart (edit shipment/payment) for example
*
* @param object $cart Cart object
* @param integer $selected ID of the method selected
* @return boolean True on success, false on failures, null when this plugin was not selected.
* On errors, JError::raiseWarning (or JError::raiseError) must be used to set a message.
*
* @author Valerie Isaksen
*/
public function plgVmDisplayListFEPayment (VirtueMartCart $cart, $selected = 0, &$htmlIn) {
$html = $this->displayListFEPayment ($cart, $selected);
if (!empty($html)) {
$htmlIn[] = $html;
}
}
/**
* @param VirtueMartCart $cart VirtueMartCart
* @param $selected
* @return array|bool
*/
protected function displayListFEPayment (VirtueMartCart $cart, $selected) {
if (!class_exists ('Klarna_payments')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarna_payments.php');
}
if ($this->getPluginMethods ($cart->vendorId) === 0) {
if (empty($this->_name)) {
$app = JFactory::getApplication ();
$app->enqueueMessage (JText::_ ('COM_VIRTUEMART_CART_NO_' . strtoupper ($this->_psType)));
return FALSE;
} else {
return FALSE;
}
}
$html = array();
foreach ($this->methods as $method) {
$temp = $this->getListFEPayment ($cart, $method);
if (!empty($temp)) {
$html[] = $temp;
}
}
if (!empty($html)) {
$this->loadScriptAndCss ();
}
return $html;
}
/**
* @param VirtueMartCart $cart
* @param $method
* @return null|string
*/
protected function getListFEPayment (VirtueMartCart $cart, $method) {
$cart_currency_code = ShopFunctions::getCurrencyByID ($cart->pricesCurrency, 'currency_code_3');
$country_code = NULL;
$countryId = 0;
$this->_getCountryCode ($cart, $country_code, $countryId);
if (!($cData = $this->checkCountryCondition ($method, $country_code, $cart))) {
return NULL;
}
try {
$pclasses = KlarnaHandler::getPClasses (NULL, KlarnaHandler::getKlarnaMode ($method, $cData['country_code_3']), $cData);
}
catch (Exception $e) {
vmError ($e->getMessage (), $e->getMessage ());
return NULL;
}
$specCamp = 0;
$partPay = 0;
$this->getNbPClasses ($pclasses, $specCamp, $partPay);
$sessionKlarnaData = $this->getKlarnaSessionData ();
$klarna_paymentmethod = "";
if (isset($sessionKlarnaData->klarna_paymentmethod)) {
$klarna_paymentmethod = $sessionKlarnaData->klarna_paymentmethod;
}
$html = '';
$checked = 'checked="checked"';
$payments = new klarna_payments($cData, KlarnaHandler::getShipToAddress ($cart));
if (in_array ('invoice', $cData['payments_activated'])) {
$payment_params = $payments->get_payment_params ($method, 'invoice', $cart);
$payment_form = $this->renderByLayout ('payment_form', array('payment_params' => $payment_params, 'payment_currency_info' => $payment_params['payment_currency_info'],), 'klarna', 'payment');
$selected = ($klarna_paymentmethod == 'klarna_invoice' AND $method->virtuemart_paymentmethod_id == $cart->virtuemart_paymentmethod_id) ? $checked : "";
$html .= $this->renderByLayout ('displaypayment', array(
'stype' => 'invoice',
'id' => $payment_params['id'],
'module' => $payment_params['module'],
'klarna_form' => $payment_form,
'virtuemart_paymentmethod_id' => $method->virtuemart_paymentmethod_id,
'klarna_paymentmethod' => $klarna_paymentmethod,
'selected' => $selected
));
}
if (in_array ('part', $cData['payments_activated'])) {
if (strtolower ($country_code) == 'nld') {
// Since 12/09/12: merchants can sell goods with Klarna Invoice up to thousands of euros. So the price check has been moved here
if (!KlarnaHandler::checkPartNLpriceCondition ($cart)) {
// We can't show our payment options for Dutch customers
// if price exceeds 250 euro. Will be replaced with ILT in
// the future.
$partPay = 0;
}
}
if ($partPay > 0) {
if ($payment_params = $payments->get_payment_params ($method, 'part', $cart, $cData['virtuemart_currency_id'], $cData['vendor_currency'])) {
$payment_form = $this->renderByLayout ('payment_form', array('payment_params' => $payment_params, 'payment_currency_info' => $payment_params['payment_currency_info'],), 'klarna', 'payment');
$selected = ($klarna_paymentmethod == 'klarna_part' AND $method->virtuemart_paymentmethod_id == $cart->virtuemart_paymentmethod_id) ? $checked : "";
$html .= $this->renderByLayout ('displaypayment', array(
'stype' => 'part',
'id' => $payment_params['id'],
'module' => $payment_params['module'],
'klarna_form' => $payment_form,
'virtuemart_paymentmethod_id' => $method->virtuemart_paymentmethod_id,
'klarna_paymentmethod' => $klarna_paymentmethod,
'selected' => $selected
));
}
}
}
// not tested yet
/*
if ( $specCamp > 0) {
if ($payment_params = $payments->get_payment_params ($method, 'spec', $cart, $cData['virtuemart_currency_id'])) {
$payment_form = $this->renderByLayout ('payment_form', array('payment_params' => $payment_params, 'payment_currency_info' => $payment_params['payment_currency_info'],), 'klarna', 'payment');
$selected = ($klarna_paymentmethod == 'klarna_spec' AND $method->virtuemart_paymentmethod_id == $cart->virtuemart_paymentmethod_id) ? $checked : "";
$html .= $this->renderByLayout ('displaypayment', array(
'stype' => 'spec',
'id' => $payment_params['id'],
'module' => $payment_params['module'],
'klarna_form' => $payment_form,
'virtuemart_paymentmethod_id' => $method->virtuemart_paymentmethod_id,
'klarna_paymentmethod' => $klarna_paymentmethod,
'selected' => $selected
));
}
}
*/
return $html;
}
/**
* Count the number of Payment Classes: Partial Payments, and Special campaigns
*
* @param $pClasses
* @param $specCamp
* @param $partPay
*/
function getNbPClasses ($pClasses, &$specCamp, &$partPay) {
$specCamp = 0;
$partPay = 0;
foreach ($pClasses as $pClass) {
if ($pClass->getType () == KlarnaPClass::SPECIAL) {
$specCamp += 1;
}
if ($pClass->getType () == KlarnaPClass::CAMPAIGN ||
$pClass->getType () == KlarnaPClass::ACCOUNT ||
$pClass->getType () == KlarnaPClass::FIXED ||
$pClass->getType () == KlarnaPClass::DELAY
) {
$partPay += 1;
}
}
}
/**
* @return mixed|null
*/
function getKlarnaSessionData () {
$session = JFactory::getSession ();
$sessionKlarna = $session->get ('Klarna', 0, 'vm');
if ($sessionKlarna) {
$sessionKlarnaData = unserialize ($sessionKlarna);
return $sessionKlarnaData;
}
return NULL;
}
/**
* @param $method
* @param $country_code
* @param $cart
* @return array|bool|null
*/
function checkCountryCondition ($method, $country_code, $cart) {
if (!class_exists ('CurrencyDisplay')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'currencydisplay.php');
}
$active_country = "klarna_active_" . strtolower ($country_code);
if (!isset($method->$active_country) or !$method->$active_country) {
return FALSE;
}
if (empty($country_code)) {
$msg = JText::_ ('VMPAYMENT_KLARNA_GET_SWEDISH_ADDRESS');
$country_code = "swe";
vmWarn ($msg);
//return false;
}
/*
if (strtolower ($country_code) == 'nld') {
if(! KlarnaHandler::checkPartNLpriceCondition ($cart)) {
// We can't show our payment options for Dutch customers
// if price exceeds 250 euro. Will be replaced with ILT in
// the future.
return FALSE;
}
}
*/
// Get the country settings
if (!class_exists ('KlarnaHandler')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarnahandler.php');
}
$cData = KlarnaHandler::getCountryData ($method, $country_code);
if ($cData['eid'] == '' || $cData['eid'] == 0) {
return FALSE;
}
return $cData;
}
/**
* @param $cart
* @param $order
* @return bool|null
*/
function plgVmConfirmedOrder ($cart, $order) {
if (!($method = $this->getVmPluginMethod ($order['details']['BT']->virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!$this->selectedThisElement ($method->payment_element)) {
return FALSE;
}
if (!class_exists ('VirtueMartModelOrders')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
}
$sessionKlarnaData = $this->getKlarnaSessionData ();
try {
$result = KlarnaHandler::addTransaction ($method, $order, $sessionKlarnaData->KLARNA_DATA['pclass']);
}
catch (Exception $e) {
$log = $e->getMessage ();
vmError ($e->getMessage () . ' #' . $e->getCode (), $e->getMessage () . ' #' . $e->getCode ());
return;
//KlarnaHandler::redirectPaymentMethod('error', $e->getMessage() . ' #' . $e->getCode());
}
//vmdebug('addTransaction result', $result);
// Delete all Klarna data
//unset($sessionKlarnaData->KLARNA_DATA, $_SESSION['SSN_ADDR']);
$shipTo = KlarnaHandler::getShipToAddress ($cart);
$modelOrder = VmModel::getModel ('orders');
if ($result['status_code'] == KlarnaFlags::DENIED) {
$order['customer_notified'] = 0;
$order['order_status'] = $method->status_denied;
$order['comments'] = JText::sprintf ('VMPAYMENT_KLARNA_PAYMENT_KLARNA_STATUS_DENIED');
if ($method->delete_order) {
$order['comments'] .= "
" . $result['status_text'];
}
$modelOrder->updateStatusForOneOrder ($order['details']['BT']->virtuemart_order_id, $order, TRUE);
vmdebug ('addTransaction remove order?', $method->delete_order);
if ($method->delete_order) {
$modelOrder->remove (array('virtuemart_order_id' => $order['details']['BT']->virtuemart_order_id));
} else {
$dbValues['order_number'] = $order['details']['BT']->order_number;
$dbValues['payment_name'] = $this->renderKlarnaPluginName ($method, $order['details']['BT']->virtuemart_country_id, $shipTo, $order['details']['BT']->order_total, $order['order_currency']);
$dbValues['virtuemart_paymentmethod_id'] = $order['details']['BT']->virtuemart_paymentmethod_id;
$dbValues['order_payment'] = $order['details']['BT']->order_payment;
$dbValues['klarna_pclass'] = $sessionKlarnaData->KLARNA_DATA['PCLASS'];
$dbValues['klarna_log'] = '';
$dbValues['klarna_status_code'] = $result['status_code'];
$dbValues['klarna_status_text'] = $result['status_text'];
$this->storePSPluginInternalData ($dbValues);
}
$app = JFactory::getApplication ();
$app->enqueueMessage ($result['status_text']);
$app->redirect (JRoute::_ ('index.php?option=com_virtuemart&view=cart&task=editpayment'));
} else {
$invoiceno = $result[1];
if ($invoiceno && is_numeric ($invoiceno)) {
//Get address id used for this order.
//$country = $sessionKlarnaData->KLARNA_DATA['country'];
// $lang = KlarnaHandler::getLanguageForCountry($method, KlarnaHandler::convertToThreeLetterCode($country));
// $d['order_payment_name'] = $kLang->fetch('MODULE_INVOICE_TEXT_TITLE', $lang);
// Add a note in the log
$log = Jtext::sprintf ('VMPAYMENT_KLARNA_INVOICE_CREATED_SUCCESSFULLY', $invoiceno);
// Prepare data that should be stored in the database
$dbValues['order_number'] = $order['details']['BT']->order_number;
$dbValues['payment_name'] = $this->renderKlarnaPluginName ($method, $order['details']['BT']->virtuemart_country_id, $shipTo, $order['details']['BT']->order_total, $order['details']['BT']->order_currency);
$dbValues['virtuemart_paymentmethod_id'] = $order['details']['BT']->virtuemart_paymentmethod_id;
$dbValues['order_payment'] = $order['details']['BT']->order_payment;
$dbValues['order_payment_tax'] = $order['details']['BT']->order_payment_tax;
$dbValues['klarna_pclass'] = $sessionKlarnaData->KLARNA_DATA['pclass'];
$dbValues['klarna_invoice_no'] = $invoiceno;
$dbValues['klarna_log'] = $log;
$dbValues['klarna_eid'] = $result['eid'];
$dbValues['klarna_status_code'] = $result['status_code'];
$dbValues['klarna_status_text'] = $result['status_text'];
$this->storePSPluginInternalData ($dbValues);
/*
* Klarna's order status
* Integer - 1,2 or 3.
* 1 = OK: KlarnaFlags::ACCEPTED
* 2 = Pending: KlarnaFlags::PENDING
* 3 = Denied: KlarnaFlags::DENIED
*/
if ($result['status_code'] == KlarnaFlags::PENDING) {
/* if Klarna's order status is pending: add it in the history */
/* The order is under manual review and will be accepted or denied at a later stage.
Use cronjob with checkOrderStatus() or visit Klarna Online to check to see if the status has changed.
You should still show it to the customer as it was accepted, to avoid further attempts to fraud. */
$order['order_status'] = $method->status_pending;
} else {
$order['order_status'] = $method->status_success;
}
$order['customer_notified'] = 1;
$order['comments'] = $log;
$modelOrder->updateStatusForOneOrder ($order['details']['BT']->virtuemart_order_id, $order, TRUE);
$html = $this->renderByLayout ('orderdone', array(
'payment_name' => $dbValues['payment_name'],
'klarna_invoiceno' => $invoiceno));
if ($result['eid'] == VMPAYMENT_KLARNA_MERCHANT_ID_DEMO) {
$html .= "
" . JText::_ ('VMPAYMENT_KLARNA_WARNING') . "
";
}
$session = JFactory::getSession ();
$session->clear ('Klarna', 'vm');
//We delete the old stuff
$cart->emptyCart ();
JRequest::setVar ('html', $html);
return TRUE;
} else {
vmError ('Error with invoice number');
}
}
}
/**
* @param $orderDetails
* @param $data
* @return null
*/
function plgVmOnUserInvoice ($orderDetails, &$data) {
if (!($method = $this->getVmPluginMethod ($orderDetails['virtuemart_paymentmethod_id']))) {
return NULL; // Another method was selected, do nothing
}
if (!$this->selectedThisElement ($method->payment_element)) {
return NULL;
}
$data['invoice_number'] = 'reservedByPayment_' . $orderDetails['order_number']; // Nerver send the invoice via email
}
/**
* @param $virtuemart_paymentmethod_id
* @param $paymentCurrencyId
* @return bool|null
*/
function plgVmGetPaymentCurrency ($virtuemart_paymentmethod_id, &$paymentCurrencyId) {
if (!($method = $this->getVmPluginMethod ($virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!$this->selectedThisElement ($method->payment_element)) {
return FALSE;
}
$paymentCurrencyId = $this->getKlarnaPaymentCurrency ($method);
}
/**
* @param $method
* @return int
*/
function getKlarnaPaymentCurrency ($method) {
if (!class_exists ('VirtueMartCart')) {
require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php');
}
$cart = VirtueMartCart::getCart (FALSE);
$country = NULL;
$countryId = 0;
$this->_getCountryCode ($cart, $country, $countryId);
$cData = KlarnaHandler::countryData ($method, $country);
return shopFunctions::getCurrencyIDByName ($cData['currency_code']);
}
/**
*
* An order gets cancelled, because order status='X'
*
* @param $order
* @param $old_order_status
* @return bool|null
*/
function plgVmOnCancelPayment ($order, $old_order_status) {
if (!$this->selectedThisByMethodId ($order->virtuemart_paymentmethod_id)) {
return NULL; // Another method was selected, do nothing
}
if (!($method = $this->getVmPluginMethod ($order->virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!($payments = $this->_getKlarnaInternalData ($order->virtuemart_order_id))) {
vmError (JText::sprintf ('VMPAYMENT_KLARNA_ERROR_NO_DATA', $order->virtuemart_order_id));
return NULL;
}
// Status code is === 3==> active invoice. Cannot be be deleted
// the invoice is active
//if ($order->order_status == $method->status_success) {
if ($invNo = $this->_getKlarnaInvoiceNo ($payments)) {
//vmDebug('order',$order);return;
$country = $this->getCountryCodeByOrderId ($order->virtuemart_order_id);
$klarna = new Klarna_virtuemart();
$cData = KlarnaHandler::countryData ($method, $country);
$klarna->config ($cData['eid'], $cData['secret'], $cData['country_code'], NULL, $cData['currency_code'], $cData['mode']);
try {
//remove a passive invoice from Klarna.
$result = $klarna->deleteInvoice ($invNo);
if ($result) {
$message = Jtext::_ ('VMPAYMENT_KLARNA_INVOICE_DELETED') . ":" . $invNo;
} else {
$message = Jtext::_ ('VMPAYMENT_KLARNA_INVOICE_NOT_DELETED') . ":" . $invNo;
}
$dbValues['order_number'] = $order->order_number;
$dbValues['virtuemart_order_id'] = $order->virtuemart_order_id;
$dbValues['virtuemart_paymentmethod_id'] = $order->virtuemart_paymentmethod_id;
$dbValues['klarna_invoice_no'] = 0; // it has been deleted
$dbValues['klarna_pdf_invoice'] = 0; // it has been deleted
$dbValues['klarna_log'] = $message;
$dbValues['klarna_eid'] = $cData['eid'];
$this->storePSPluginInternalData ($dbValues);
VmInfo ($message);
}
catch (Exception $e) {
$log = $e->getMessage () . " (#" . $e->getCode () . ")";
if ($e->getCode () == '8113') {
VmError ('invoice_not_passive');
}
if ($e->getCode () != 8101) { // unkown_order
$this->_updateKlarnaInternalData ($order, $log, $invNo);
VmError ($e->getMessage () . " (#" . $e->getCode () . ")");
return FALSE;
}
}
}
return TRUE;
}
/**
* @param $payments
* @param string $primaryKey
* @return mixed
*/
function _getKlarnaInvoiceNo ($payments, &$primaryKey = '') {
$nb = count ($payments);
$primaryKey = $payments[$nb - 1]->id;
return $payments[$nb - 1]->klarna_invoice_no;
}
/**
* @param $payments
* @return mixed
*/
function _getKlarnaPlcass ($payments) {
$nb = count ($payments);
return $payments[$nb - 1]->klarna_pclass;
}
/**
* @param $payments
* @return mixed
*/
function _getKlarnaStatusCode ($payments) {
$nb = count ($payments);
return $payments[$nb - 1]->klarna_status_code;
}
/**
* @author Patrick Kohl
* @param $type
* @param $name
* @param $render
*/
function plgVmOnSelfCallFE ($type, $name, &$render) {
if ($name != $this->_name || $type != 'vmpayment') {
return FALSE;
}
//Klarna Ajax
require (JPATH_VMKLARNAPLUGIN . '/klarna/helpers/klarna_ajax.php');
if (!class_exists ('VmModel')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'vmmodel.php');
}
$model = VmModel::getModel ('paymentmethod');
$payment = $model->getPayment ();
if (!class_exists ('vmParameters')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'parameterparser.php');
}
$parameters = new vmParameters($payment, $payment->payment_element, 'plugin', 'vmpayment');
$method = $parameters->getParamByName ('data');
$country = JRequest::getWord ('country');
$country = KlarnaHandler::convertToThreeLetterCode ($country);
if (!class_exists ('klarna_virtuemart')) {
require (JPATH_VMKLARNAPLUGIN . '/klarna/helpers/klarna_virtuemart.php');
}
$settings = KlarnaHandler::getCountryData ($method, $country);
$klarna = new Klarna_virtuemart();
$klarna->config ($settings['eid'], $settings['secret'], $settings['country'], $settings['language'], $settings['currency'], KlarnaHandler::getKlarnaMode ($method, $settings['country_code_3']), VMKLARNA_PC_TYPE, KlarnaHandler::getKlarna_pc_type (), TRUE);
$SelfCall = new KlarnaAjax($klarna, (int)$settings['eid'], JPATH_VMKLARNAPLUGIN, Juri::base ());
$action = JRequest::getWord ('action');
$jlang = JFactory::getLanguage ();
$currentLang = substr ($jlang->getDefault (), 0, 2);
$newIso = JRequest::getWord ('newIso');
if ($currentLang != $newIso) {
$iso = array(
"sv" => "sv-SE",
"da" => "da-DK",
"en" => "en-GB",
"de" => "de-DE",
"nl" => "nl-NL",
"nb" => "nb-NO",
"fi" => "fi-FI");
if (array_key_exists ($newIso, $iso)) {
$jlang->load ('plg_vmpayment_klarna', JPATH_ADMINISTRATOR, $iso[$newIso], TRUE);
}
}
echo $SelfCall->$action();
jexit ();
}
/**
* @author Patrick Kohl
* @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 = jrequest::getWord ('call');
$this->$call();
// jexit();
}
/**
*
* Download Pdf Invoice
*
* @author Valérie Isaksen
*
*/
/**
* @return int|null|string
*/
function downloadInvoicePdf () {
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');
}
$payment_methodid = JRequest::getInt ('payment_methodid');
$orderNumber = JRequest::getString ('order_number');
$orderPass = JRequest::getString ('order_pass');
if (!($method = $this->getVmPluginMethod ($payment_methodid))) {
return NULL; // Another method was selected, do nothing
}
$modelOrder = VmModel::getModel ('orders');
// If the user is not logged in, we will check the order number and order pass
$virtuemart_order_id = $modelOrder->getOrderIdByOrderPass ($orderNumber, $orderPass);
if (empty($virtuemart_order_id)) {
VmError ('Invalid order_number/password ' . JText::_ ('COM_VIRTUEMART_RESTRICTED_ACCESS'), 'Invalid order_number/password ' . JText::_ ('COM_VIRTUEMART_RESTRICTED_ACCESS'));
return 0;
}
if (!($payments = $this->_getKlarnaInternalData ($virtuemart_order_id))) {
return '';
}
foreach ($payments as $payment) {
if (!empty($payment->klarna_pdf_invoice)) {
$path = VmConfig::get ('forSale_path', 0);
$path .= DS . 'invoices' . DS;
$fileName = $path . $payment->klarna_pdf_invoice;
break;
}
}
if (file_exists ($fileName)) {
header ("Cache-Control: public");
header ("Content-Transfer-Encoding: binary\n");
header ('Content-Type: application/pdf');
$contentDisposition = 'attachment';
$agent = strtolower ($_SERVER['HTTP_USER_AGENT']);
if (strpos ($agent, 'msie') !== FALSE) {
$fileName = preg_replace ('/\./', '%2e', $fileName, substr_count ($fileName, '.') - 1);
}
header ("Content-Disposition: $contentDisposition; filename=\"$payment->klarna_pdf_invoice\"");
$contents = file_get_contents ($fileName);
echo $contents;
}
return;
}
/*
* @author Valérie Isaksen
*
* @return int|null
*/
function checkOrderStatus () {
if (!class_exists ('VirtueMartModelOrders')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
}
$payment_methodid = JRequest::getInt ('payment_methodid');
//$invNo = JRequest::getWord ('invNo');
$orderNumber = JRequest::getString ('order_number');
$orderPass = JRequest::getString ('order_pass');
if (!($method = $this->getVmPluginMethod ($payment_methodid))) {
return NULL; // Another method was selected, do nothing
}
$modelOrder = VmModel::getModel ('orders');
// If the user is not logged in, we will check the order number and order pass
$orderId = $modelOrder->getOrderIdByOrderPass ($orderNumber, $orderPass);
if (empty($orderId)) {
VmError ('Invalid order_number/password ' . JText::_ ('COM_VIRTUEMART_RESTRICTED_ACCESS'), 'Invalid order_number/password ' . JText::_ ('COM_VIRTUEMART_RESTRICTED_ACCESS'));
return 0;
}
if (!($payments = $this->_getKlarnaInternalData ($orderId))) {
return '';
}
$invNo = $this->_getKlarnaInvoiceNo ($payments);
$country = $this->getCountryCodeByOrderID ($orderId);
$settings = KlarnaHandler::countryData ($method, $country);
$klarna_order_status = KlarnaHandler::checkOrderStatus ($settings, KlarnaHandler::getKlarnaMode ($method, $settings['country_code_3']), $orderNumber);
vmdebug ('Klarna status', $klarna_order_status, $invNo);
if ($klarna_order_status == KlarnaFlags::ACCEPTED) {
/* if Klarna's order status is pending: add it in the history */
/* The order is under manual review and will be accepted or denied at a later stage.
Use cronjob with checkOrderStatus() or visit Klarna Online to check to see if the status has changed.
You should still show it to the customer as it was accepted, to avoid further attempts to fraud. */
$order['order_status'] = $method->status_success;
$order['comments'] = JText::_ ('VMPAYMENT_KLARNA_PAYMENT_ACCEPTED');
$order['customer_notified'] = 0;
$dbValues['klarna_log'] = JText::_ ('VMPAYMENT_KLARNA_PAYMENT_ACCEPTED');
} elseif ($klarna_order_status == KlarnaFlags::DENIED) {
$order['order_status'] = $method->status_denied;
$order['customer_notified'] = 1;
$dbValues['klarna_log'] = JText::_ ('VMPAYMENT_KLARNA_PAYMENT_NOT_ACCEPTED');
$order['comments'] = JText::_ ('VMPAYMENT_KLARNA_PAYMENT_NOT_ACCEPTED');
} else {
if ($klarna_order_status == KlarnaFlags::PENDING) {
$dbValues['klarna_log'] = JText::_ ('VMPAYMENT_KLARNA_PAYMENT_PENDING');
} else {
$dbValues['klarna_log'] = $klarna_order_status;
}
$order['comments'] = $dbValues['klarna_log'];
$order['customer_notified'] = 0;
}
$dbValues['order_number'] = $orderNumber;
$dbValues['virtuemart_order_id'] = $orderId;
$dbValues['virtuemart_paymentmethod_id'] = $payment_methodid;
$dbValues['klarna_invoice_no'] = $invNo;
$this->storePSPluginInternalData ($dbValues);
$modelOrder->updateStatusForOneOrder ($orderId, $order, FALSE);
$app = JFactory::getApplication ();
$app->redirect ('index.php?option=com_virtuemart&view=orders&task=edit&virtuemart_order_id=' . $orderId);
// jexit();
}
/**
* @param $virtuemart_order_id
* @return mixed|string
*/
function _getTablepkeyValue ($virtuemart_order_id) {
$db = JFactory::getDBO ();
$q = 'SELECT ' . $this->_tablepkey . ' FROM `' . $this->_tablename . '` ' . 'WHERE `virtuemart_order_id` = ' . $virtuemart_order_id;
$db->setQuery ($q);
if (!($pkey = $db->loadResult ())) {
JError::raiseWarning (500, $db->getErrorMsg ());
return '';
}
return $pkey;
}
/**
* Display stored payment data for an order
*
* @see components/com_virtuemart/helpers/vmPSPlugin::plgVmOnShowOrderBEPayment()
*/
function plgVmOnShowOrderBEPayment ($virtuemart_order_id, $payment_method_id, $order) {
if (!($this->selectedThisByMethodId ($payment_method_id))) {
return NULL; // Another method was selected, do nothing
}
if (!($payments = $this->_getKlarnaInternalData ($virtuemart_order_id))) {
// JError::raiseWarning(500, $db->getErrorMsg());
return '';
}
if (!($method = $this->getVmPluginMethod ($payment_method_id))) {
return NULL; // Another method was selected, do nothing
}
$html = '
' . "\n";
$html .= $this->getHtmlHeaderBE ();
$code = "klarna_";
$class = 'class="row1"';
foreach ($payments as $payment) {
$html .= '| ' . JText::_ ('VMPAYMENT_KLARNA_DATE') . ' | ' . $payment->created_on . ' |
';
//$html .= $this->getHtmlRow('KLARNA_DATE', "".$payment->created_on."", $class);
if ($payment->payment_name) {
$html .= $this->getHtmlRowBE ('KLARNA_PAYMENT_NAME', $payment->payment_name);
}
foreach ($payment as $key => $value) {
if ($value) {
if (substr ($key, 0, strlen ($code)) == $code) {
if ($key == 'klarna_pdf_invoice' and !empty($value)) {
// backwards compatible
if (false) {
$invoicePdfLink = JURI::root () . 'administrator/index.php?option=com_virtuemart&view=plugin&type=vmpayment&name=klarna&call=downloadInvoicePdf&payment_methodid=' . (int)$payment_method_id . '&order_number=' . $order['details']['BT']->order_number . '&order_pass=' . $order['details']['BT']->order_pass;
$value = '' . JText::_ ('VMPAYMENT_KLARNA_DOWNLOAD_INVOICE') . '';
} else {
$value = '' . JText::_('VMPAYMENT_KLARNA_VIEW_INVOICE') . '';
}
}
$html .= $this->getHtmlRowBE ($key, $value);
}
}
}
}
if ($order['details']['BT']->order_status == $method->status_pending) {
if (!class_exists ('VirtueMartModelOrders')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
}
$country = $this->getCountryCodeByOrderId ($virtuemart_order_id);
$invNo = $this->_getKlarnaInvoiceNo ($payments);
vmDebug ('plgVmOnShowOrderBEPayment', $invNo);
$checkOrderStatus = JURI::root () . 'administrator/index.php?option=com_virtuemart&view=plugin&type=vmpayment&name=klarna&call=checkOrderStatus&payment_methodid=' . (int)$payment_method_id . '&order_number=' . $order['details']['BT']->order_number . '&order_pass=' . $order['details']['BT']->order_pass . '&country=' . $country;
$link = '' . JText::_ ('VMPAYMENT_KLARNA_GET_NEW_STATUS') . '';
$html .= $this->getHtmlRowBE ('KLARNA_PAYMENT_CHECK_ORDER_STATUS', $link);
}
$html .= '
' . "\n";
return $html;
}
/**
* @param $virtuemart_order_id
* @param string $order_number
* @return mixed|string
*/
function _getKlarnaInternalData ($virtuemart_order_id, $order_number = '') {
$db = JFactory::getDBO ();
$q = 'SELECT * FROM `' . $this->_tablename . '` WHERE ';
if ($order_number) {
$q .= " `order_number` = '" . $order_number . "'";
} else {
$q .= ' `virtuemart_order_id` = ' . $virtuemart_order_id;
}
$db->setQuery ($q);
if (!($payments = $db->loadObjectList ())) {
return '';
}
return $payments;
}
/**
* @param VirtueMartCart $cart
* @param $method
* @param $cart_prices
* @return int
*/
function getCosts (VirtueMartCart $cart, $method, $cart_prices) {
$country_code = NULL;
$countryId = 0;
$this->_getCountryCode ($cart, $country_code, $countryId);
return KlarnaHandler::getInvoiceFee ($method, $country_code);
}
/**
* Save updated order data to the method specific table
*
* @param array $order 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 plgVmOnUpdateOrderPayment (&$order, $old_order_status) {
if (!$this->selectedThisByMethodId ($order->virtuemart_paymentmethod_id)) {
return NULL; // Another method was selected, do nothing
}
if (!($method = $this->getVmPluginMethod ($order->virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!($payments = $this->_getKlarnaInternalData ($order->virtuemart_order_id))) {
vmError (JText::sprintf ('VMPAYMENT_KLARNA_ERROR_NO_DATA', $order->virtuemart_order_id));
return NULL;
}
if (!($invNo = $this->_getKlarnaInvoiceNo ($payments))) {
return NULL;
}
// to activate the order
if ($order->order_status == $method->status_shipped) {
$country = $this->getCountryCodeByOrderId ($order->virtuemart_order_id);
$klarna_vm = new Klarna_virtuemart();
$cData = KlarnaHandler::countryData ($method, $country);
/*
* The activateInvoice function is used to activate a passive invoice.
* Please note that this function call cannot activate an invoice created in test mode.
* It is however possible to manually activate that type of invoices.
*/
$force_emailInvoice = FALSE;
$klarna_vm->config ($cData['eid'], $cData['secret'], $cData['country_code'], NULL, $cData['currency_code'], KlarnaHandler::getKlarnaMode ($method, $cData['country_code_3']));
try {
//You can specify a new pclass ID if the customer wanted to change it before you activate.
$klarna_vm->activateInvoice ($invNo);
$invoice_url=$this->getInvoice($invNo, $invoice_url);
//The url points to a PDF file for the invoice.
//Invoice activated, proceed accordingly.
}
catch (Exception $e) {
$log = $e->getMessage () . " (#" . $e->getCode () . ")";
if ($e->getCode () != 8111) { // (invoice_not_passive_or_frozen)
$this->_updateKlarnaInternalData ($order, $log);
VmError ($e->getMessage () . " (#" . $e->getCode () . ")");
return FALSE;
} else {
$force_emailInvoice = TRUE;
}
}
$emailInvoice = $this->emailInvoice ($method, $klarna_vm, $invNo, $force_emailInvoice);
$dbValues['order_number'] = $order->order_number;
$dbValues['virtuemart_order_id'] = $order->virtuemart_order_id;
$dbValues['virtuemart_paymentmethod_id'] = $order->virtuemart_paymentmethod_id;
$dbValues['klarna_invoice_no'] = $invNo;
$dbValues['klarna_log'] = Jtext::sprintf ('VMPAYMENT_KLARNA_ACTIVATE_INVOICE', $invNo);
if ($emailInvoice) {
$dbValues['klarna_log'] .= "
" . Jtext::sprintf ('VMPAYMENT_KLARNA_EMAIL_INVOICE', $invNo);
} else {
$dbValues['klarna_log'] .= "
" . Jtext::_ ('VMPAYMENT_KLARNA_EMAIL_INVOICE_NOT_SENT');
}
$dbValues['klarna_eid'] = $cData['eid'];
//$dbValues['klarna_status_code'] = KLARNA_INVOICE_ACTIVE; // Invoice is active
//$dbValues['klarna_status_text'] = '';
$dbValues['klarna_pdf_invoice'] = $invoice_url;
$this->storePSPluginInternalData ($dbValues);
return TRUE;
}
return NULL;
}
/**
* @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/invoices/" . $invoice_number . '.pdf';
} else {
$klarna_invoice_name = "https://online.testdrive.klarna.com/invoices/" . $invoice_number . '.pdf';
}
$vm_invoice_name = 'klarna_' . $invoice_number . '.pdf';
return $klarna_invoice_name;
}
private function emailInvoice ($method, $klarna_vm, $invNo, $force_emailInvoice) {
if ($method->send_invoice or $force_emailInvoice) {
try {
$result = $klarna_vm->emailInvoice ($invNo);
/* Invoice sent to customer via email, proceed accordingly.
$result contains the invoice number of the emailed invoice. */
}
catch (Exception $e) {
//Something went wrong, print the message:
VmError ($e->getMessage () . " (#" . $e->getCode () . ")");
}
return TRUE;
}
return FALSE;
}
/**
* @param $order
* @param $log
*/
function _updateKlarnaInternalData ($order, $log) {
$dbValues['virtuemart_order_id'] = $order->virtuemart_order_id;
$dbValues['order_number'] = $order->order_number;
$dbValues['klarna_log'] = $log;
$this->storePSPluginInternalData ($dbValues);
}
/**
* 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
*
*/
function plgVmOnStoreInstallPaymentPluginTable ($jplugin_id) {
if ($jplugin_id != $this->_jid) {
return FALSE;
}
if (!class_exists ('JFile')) {
require(JPATH_SITE . DS . 'libraries' . DS . 'joomla' . DS . 'filesystem' . DS . 'file.php');
}
/*
* if the file Klarna.cfg does not exist, then create it
*/
$filename = VMKLARNA_CONFIG_FILE;
if (!JFile::exists ($filename)) {
$fileContents = "";
$result = JFile::write ($filename, $fileContents);
if (!$result) {
VmError (JText::sprintf ('VMPAYMENT_KLARNA_CANT_WRITE_CONFIG', $filename, $result));
}
}
$method = $this->getPluginMethod (JRequest::getInt ('virtuemart_paymentmethod_id'));
if (KlarnaHandler::createKlarnaFolder ()) {
$results = KlarnaHandler::fetchAllPClasses ($method);
if (is_array ($results) and $results['msg']) {
vmError ($results['msg']);
}
}
vmDebug ('PClasses fetched for : ', $results['notice']);
// we have to check that the following Shopper fields are there
$required_shopperfields_vm = Klarnahandler::getKlarnaVMGenericShopperFields ();
$required_shopperfields_bycountry = KlarnaHandler::getKlarnaSpecificShopperFields ();
$userFieldsModel = VmModel::getModel ('UserFields');
$switches['published'] = TRUE;
$userFields = $userFieldsModel->getUserFields ('', $switches);
// TEST that all Vm shopperfields are there
foreach ($userFields as $userField) {
$fields_name_vm[] = $userField->name;
}
$result = array_intersect ($fields_name_vm, $required_shopperfields_vm);
$vm_required_not_found = array_diff ($required_shopperfields_vm, $result);
if (count ($vm_required_not_found)) {
VmError (JText::sprintf ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_NOT_FOUND', implode (", ", $vm_required_not_found)));
} else {
VmInfo (JText::_ ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_OK'));
}
VmConfig::loadJLang('com_virtuemart_shoppers', true);
$klarna_required_not_found = array();
// TEST that all required Klarna shopper fields are there, if not create them
foreach ($required_shopperfields_bycountry as $key => $shopperfield_country) {
$active = 'klarna_active_' . strtolower ($key);
if ($method->$active) {
$resultByCountry = array_intersect ($fields_name_vm, $shopperfield_country);
$klarna_required_country_not_found = array_diff ($shopperfield_country, $resultByCountry);
$klarna_required_not_found = array_merge ($klarna_required_country_not_found, $klarna_required_not_found);
}
}
$klarna_required_not_found = array_unique ($klarna_required_not_found, SORT_STRING);
if (count ($klarna_required_not_found)) {
VmError (JText::sprintf ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_NOT_FOUND', implode (", ", $klarna_required_not_found)));
$shopperFieldsType = KlarnaHandler::getKlarnaShopperFieldsType ();
$userfieldsModel = VmModel::getModel ('userfields');
$data['virtuemart_userfield_id'] = 0;
$data['published'] = 1;
$data['required'] = 0;
$data['account'] = 1;
$data['shipment'] = 0;
$data['vNames'] = array();
$data['vValues'] = array();
VmConfig::loadJLang('com_virtuemart_shoppers', true);
foreach ($klarna_required_not_found as $requiredfield) {
$data['name'] = $requiredfield;
$data['type'] = $shopperFieldsType[$requiredfield];
$data['title'] = strtoupper ('COM_VIRTUEMART_SHOPPER_FORM_' . $requiredfield);
$ret = $userfieldsModel->store ($data);
if (!$ret) {
vmError (JText::_ ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_ERROR_STORING') . $requiredfield);
} else {
vmInfo (JText::_ ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_CREATE_OK') . $requiredfield);
}
}
} else {
VmInfo (JText::_ ('VMPAYMENT_KLARNA_REQUIRED_USERFIELDS_OK'));
}
$result = $this->onStoreInstallPluginTable ($jplugin_id);
return $result;
}
/**
* 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
}
if (!($method = $this->getVmPluginMethod ($cart->virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!class_exists ('KlarnaAddr')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'api' . DS . 'klarnaaddr.php');
}
$session = JFactory::getSession ();
$sessionKlarna = new stdClass();
//$post = JRequest::get('post');
$errors = array();
$klarnaData_paymentmethod = JRequest::getVar ('klarna_paymentmethod', '');
if ($klarnaData_paymentmethod == 'klarna_invoice') {
$sessionKlarna->klarna_option = 'invoice';
} elseif ($klarnaData_paymentmethod == 'klarna_partPayment') {
$sessionKlarna->klarna_option = 'part';
} elseif ($klarnaData_paymentmethod == 'klarna_speccamp') {
$sessionKlarna->klarna_option = 'spec';
} else {
return NULL;
}
// Store payment_method_id so we can activate the
// right payment in case something goes wrong.
$sessionKlarna->virtuemart_payment_method_id = $cart->virtuemart_paymentmethod_id;
$sessionKlarna->klarna_paymentmethod = $klarnaData_paymentmethod;
$country3 = NULL;
$countryId = 0;
$this->_getCountryCode ($cart, $country3, $countryId, 'country_3_code');
// $country2= strtolower($country2);
if (empty($country3)) {
$country3 = "SWE";
$countryId = ShopFunctions::getCountryIDByName ($country3);
}
$cData = KlarnaHandler::countryData ($method, strtoupper ($country3));
$klarnaData = KlarnaHandler::getDataFromEditPayment ();
if ($msg = KlarnaHandler::checkDataFromEditPayment ($klarnaData, $cData['country_code_3'])) {
//vmInfo($msg); // meanwhile the red baloon works
$session->set ('Klarna', serialize ($sessionKlarna), 'vm');
return FALSE;
}
$klarnaData['country'] = $cData['country_code'];
$klarnaData['country3'] = $cData['country_code_3'];
//$country = $cData['country_code']; //KlarnaHandler::convertCountry($method, $country2);
//$lang = $cData['language_code']; //KlarnaHandler::getLanguageForCountry($method, $country);
// Get the correct data
//Removes spaces, tabs, and other delimiters.
// If it is a swedish customer we use the information from getAddress
if (strtolower ($cData['country_code']) == "se") {
$swedish_addresses = KlarnaHandler::getAddresses ($klarnaData['socialNumber'], $cData, $method);
if (empty($swedish_addresses)) {
$msg = JText::_ ('VMPAYMENT_KLARNA_ERROR_TITLE_2');
$msg .= JText::_ ('VMPAYMENT_KLARNA_NO_GETADDRESS');
$session->set ('Klarna', serialize ($sessionKlarna), 'vm');
return FALSE;
}
//This example only works for GA_GIVEN.
foreach ($swedish_addresses as $address) {
if ($address->isCompany) {
$klarnaData['company_name'] = $address->getCompanyName ();
$klarnaData['first_name'] = "-";
$klarnaData['last_name'] = "-";
} else {
$klarnaData['first_name'] = $address->getFirstName ();
$klarnaData['last_name'] = $address->getLastName ();
}
$klarnaData['street'] = $address->getStreet ();
$klarnaData['zip'] = $address->getZipCode ();
$klarnaData['city'] = $address->getCity ();
$klarnaData['country'] = $address->getCountryCode ();
$countryId = $klarnaData['virtuemart_country_id'] = shopFunctions::getCountryIDByName ($klarnaData['country']);
}
foreach ($klarnaData as $key => $value) {
$klarnaData[$key] = mb_convert_encoding ($klarnaData[$key], 'UTF-8', 'ISO-8859-1');
}
}
$address_type = NULL;
$st = $this->getCartAddress ($cart, $address_type, TRUE);
vmDebug ('getCartAddress', $st);
if ($address_type == 'BT') {
$prefix = '';
} else {
$prefix = 'shipto_';
}
// Update the Shipping Address to what is specified in the register.
$update_data = array(
$prefix . 'address_type_name' => 'Klarna',
$prefix . 'company' => $klarnaData['company_name'],
$prefix . 'title' => $klarnaData['title'],
$prefix . 'first_name' => $klarnaData['first_name'],
$prefix . 'middle_name' => $st['middle_name'],
$prefix . 'last_name' => $klarnaData['last_name'],
$prefix . 'address_1' => $klarnaData['street'],
$prefix . 'address_2' => $klarnaData['house_ext'],
$prefix . 'house_no' => $klarnaData['house_no'],
$prefix . 'zip' => html_entity_decode ($klarnaData['zip']),
$prefix . 'city' => $klarnaData['city'],
$prefix . 'virtuemart_country_id' => $countryId, //$klarnaData['virtuemart_country_id'],
$prefix . 'state' => '',
$prefix . 'phone_1' => $klarnaData['phone'],
$prefix . 'phone_2' => $st['phone_2'],
$prefix . 'fax' => $st['fax'],
//$prefix . 'birthday' => empty($klarnaData['birthday']) ? $st['birthday'] : $klarnaData['birthday'],
//$prefix . 'socialNumber' => empty($klarnaData['pno']) ? $klarnaData['socialNumber'] : $klarnaData['pno'],
'address_type' => $address_type
);
if ($address_type == 'BT') {
$update_data ['email'] = $klarnaData['email'];
}
if (!empty($st)) {
$update_data = array_merge ($st, $update_data);
}
// save address in cart if different
// if (false) {
$cart->saveAddressInCart ($update_data, $update_data['address_type'], TRUE);
//vmdebug('plgVmOnSelectCheckPayment $cart',$cart);
//vmInfo(JText::_('VMPAYMENT_KLARNA_ADDRESS_UPDATED_NOTICE'));
// }
//}
// Store the Klarna data in a session variable so
// we can retrevie it later when we need it
//$klarnaData['pclass'] = ($klarnaData_paymentmethod == 'klarna_invoice' ? -1 : intval(JRequest::getVar($kIndex . "paymentPlan")));
$klarnaData['pclass'] = ($klarnaData_paymentmethod == 'klarna_invoice' ? -1 : intval (JRequest::getVar ("part_klarna_paymentPlan")));
$sessionKlarna->KLARNA_DATA = $klarnaData;
// 2 letters small
//$settings = KlarnaHandler::getCountryData($method, $cart_country2);
try {
$address = new KlarnaAddr(
$klarnaData['email'],
$klarnaData['phone'],
"", //mobile
$klarnaData['first_name'],
$klarnaData['last_name'], '',
$klarnaData['street'],
$klarnaData['zip'],
$klarnaData['city'],
$klarnaData['country'], // $settings['country'],
$klarnaData['house_no'],
$klarnaData['house_ext']
);
}
catch (Exception $e) {
VmInfo ($e->getMessage ());
return FALSE;
//KlarnaHandler::redirectPaymentMethod('message', $e->getMessage());
}
if (isset($errors) && count ($errors) > 0) {
$msg = JText::_ ('VMPAYMENT_KLARNA_ERROR_TITLE_1');
foreach ($errors as $error) {
$msg .= " -" . $error . "";
}
$msg .= JText::_ ('VMPAYMENT_KLARNA_ERROR_TITLE_2');
unset($errors);
VmError ($msg);
return FALSE;
//KlarnaHandler::redirectPaymentMethod('error', $msg);
}
$session->set ('Klarna', serialize ($sessionKlarna), 'vm');
return TRUE;
}
/**
* plgVmOnSelectedCalculatePricePayment
* Calculate the price (value, tax_id) of the selected method
* It is called by the calculator
* This function does NOT to be reimplemented. If not reimplemented, then the default values from this function are taken.
*
* @author Valerie Isaksen
* @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->onKlarnaSelectedCalculatePrice ($cart, $cart_prices, $cart_prices_name);
}
/**
* @param VirtuemartViewUser $user
* @param $html
* @param string $from_cart
* @return bool|null
*/
function plgVmDisplayLogin (VirtuemartViewUser $user, &$html, $from_cart = FALSE) {
// only to display it in the cart, not in list orders view
if (!$from_cart) {
return NULL;
}
$vendorId = 1;
if (!class_exists ('VirtueMartCart')) {
require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php');
}
$cart = VirtueMartCart::getCart ();
if ($cart->BT != 0 or $cart->virtuemart_paymentmethod_id) {
return;
}
if ($this->getPluginMethods ($vendorId) === 0) {
if (empty($this->_name)) {
$app = JFactory::getApplication ();
$app->enqueueMessage (JText::_ ('COM_VIRTUEMART_CART_NO_' . strtoupper ($this->_psType)));
return FALSE;
} else {
return FALSE;
}
}
//vmdebug('plgVmDisplayLogin', $user);
//$html = $this->renderByLayout('displaylogin', array('klarna_pm' => $klarna_pm, 'virtuemart_paymentmethod_id' => $method->virtuemart_paymentmethod_id, 'klarna_paymentmethod' => $klarna_paymentmethod));
$link = JRoute::_ ('index.php?option=com_virtuemart&view=cart&task=editpayment&klarna_country_2_code=se', false);
foreach ($this->methods as $method) {
if ($method->klarna_active_swe) {
$html .= $this->renderByLayout ('displaylogin', array('editpayment_link' => $link));
}
}
}
/**
* @param VirtueMartCart $cart
* @param array $cart_prices
* @param $cart_prices_name
* @return bool|null
*/
private function onKlarnaSelectedCalculatePrice (VirtueMartCart $cart, array &$cart_prices, &$cart_prices_name) {
if (!($method = $this->selectedThisByMethodId ($cart->virtuemart_paymentmethod_id))) {
return NULL; // Another method was selected, do nothing
}
if (!($method = $this->getVmPluginMethod ($cart->virtuemart_paymentmethod_id))) {
return NULL;
}
$sessionKlarnaData = $this->getKlarnaSessionData ();
if (empty($sessionKlarnaData)) {
return NULL;
}
$cart_prices_name = '';
$cart_prices[$this->_psType . '_tax_id'] = 0;
$cart_prices['cost'] = 0;
//vmdebug('cart prices', $cart_prices);
$country_code = NULL;
$countryId = 0;
$this->_getCountryCode ($cart, $country_code, $countryId, 'country_2_code');
if (isset($sessionKlarnaData->KLARNA_DATA) AND strcasecmp ($country_code, $sessionKlarnaData->KLARNA_DATA['country']) != 0) {
return FALSE;
}
//$paramsName = $this->_psType . '_params';
$type = NULL;
$address = $this->getCartAddress ($cart, $type, FALSE);
if (empty($address)) {
return FALSE;
}
$shipTo = KlarnaHandler::getShipToAddress ($cart);
$cart_prices_name = $this->renderKlarnaPluginName ($method, $address['virtuemart_country_id'], $shipTo, $cart_prices['withTax'], $cart->pricesCurrency);
if (isset($sessionKlarnaData->klarna_option) AND $sessionKlarnaData->klarna_option == 'invoice') {
$this->setCartPrices ($cart, $cart_prices, $method);
}
return TRUE;
}
/**
* update the plugin cart_prices
*
* @author Valérie Isaksen
* @param VirtueMartCart $cart
* @param $cart_prices
* @param $method
*/
function setCartPrices (VirtueMartCart $cart, &$cart_prices, $method) {
$country = NULL;
$countryId = 0;
$this->_getCountryCode (NULL, $country, $countryId);
$invoice_fee = KlarnaHandler::getInvoiceFee ($method, $country);
$invoice_tax_id = KlarnaHandler::getInvoiceTaxId ($method, $country);
$_psType = ucfirst ($this->_psType);
$taxrules = array();
if (!empty($invoice_tax_id)) {
$db = JFactory::getDBO ();
$q = 'SELECT * FROM #__virtuemart_calcs WHERE `virtuemart_calc_id`="' . $invoice_tax_id . '" ';
$db->setQuery ($q);
$taxrules = $db->loadAssocList ();
}
if (!class_exists ('calculationHelper')) {
require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'calculationh.php');
}
$calculator = calculationHelper::getInstance ();
if (count ($taxrules) > 0) {
$calculator->setRevert (TRUE);
$invoiceFeeWithoutTax = $calculator->roundInternal ($calculator->executeCalculation ($taxrules, $invoice_fee));
$cart_prices['salesPricePayment'] = $invoice_fee;
$cart_prices['paymentTax'] = $invoice_fee - $calculator->roundInternal ($invoiceFeeWithoutTax);
$cart_prices['paymentValue'] = $invoiceFeeWithoutTax;
$calculator->setRevert (FALSE);
$cart_prices[$this->_psType . '_calc_id'] = $taxrules[0]['virtuemart_calc_id'];
} else {
$cart_prices['paymentValue'] = $invoice_fee;
$cart_prices['salesPricePayment'] = $invoice_fee;
$cart_prices['paymentTax'] = 0;
$cart_prices[$this->_psType . '_calc_id'] = 0;
}
}
/**
* @param $method
* @param $virtuemart_country_id
* @param $shipTo
* @param $total
* @return string
*/
protected function renderKlarnaPluginName ($method, $virtuemart_country_id, $shipTo, $total, $cartPricesCurrency) {
$session = JFactory::getSession ();
$sessionKlarna = $session->get ('Klarna', 0, 'vm');
if (empty($sessionKlarna)) {
return '';
}
$sessionKlarnaData = unserialize ($sessionKlarna);
$address['virtuemart_country_id'] = $virtuemart_country_id;
$cData = KlarnaHandler::getcData ($method, $address);
$country2 = strtolower (shopFunctions::getCountryByID ($virtuemart_country_id, 'country_2_code'));
$text = "";
if (isset($sessionKlarnaData->klarna_option)) {
switch ($sessionKlarnaData->klarna_option) {
case 'invoice':
$sType='invoice';
$image = '/klarna_invoice_' . $country2 . '.png';
//$logo = VMKLARNAPLUGINWEBASSETS . '/images/' . 'logo/klarna_' . $sType . '_' . $code2 . '.png';
$image ="https://cdn.klarna.com/public/images/".strtoupper($country2)."/badges/v1/". $sType ."/".$country2."_". $sType ."_badge_std_blue.png?height=55&eid=".$cData['eid'];
$display_invoice_fee = NULL;
$invoice_fee = 0;
KlarnaHandler::getInvoiceFeeInclTax ($method, $cData['country_code_3'], $cartPricesCurrency, $cData['virtuemart_currency_id'], $display_invoice_fee, $invoice_fee);
$text = JText::sprintf ('VMPAYMENT_KLARNA_INVOICE_TITLE_NO_PRICE', $display_invoice_fee);
break;
case 'partpayment':
case 'part':
$sType='account';
//$image = '/klarna_part_' . $country2 . '.png';
$image ="https://cdn.klarna.com/public/images/".strtoupper($country2)."/badges/v1/". $sType ."/".$country2."_". $sType ."_badge_std_blue.png?height=55&eid=".$cData['eid'];
$address['virtuemart_country_id'] = $virtuemart_country_id;
//$pclasses = KlarnaHandler::getPClasses(NULL, KlarnaHandler::getKlarnaMode($method), $cData);
if (!class_exists ('Klarna_payments')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarna_payments.php');
}
$payments = new klarna_payments($cData, $shipTo);
//vmdebug('displaylogos',$cart_prices);
$totalInPaymentCurrency = KlarnaHandler::convertPrice ($total, $cData['vendor_currency'], $cData['virtuemart_currency_id']);
vmdebug ('totalInPaymentCurrency', $totalInPaymentCurrency);
if (isset($sessionKlarnaData->KLARNA_DATA)) {
$text = $payments->displayPclass ($sessionKlarnaData->KLARNA_DATA['pclass'], $totalInPaymentCurrency); // .' '.$total;
}
break;
case 'speccamp':
$image = 'klarna_logo.png';
$text = JText::_ ('VMPAYMENT_KLARNA_SPEC_TITLE');
break;
default:
$image = '';
$text = '';
break;
}
$plugin_name = $this->_psType . '_name';
$plugin_desc = $this->_psType . '_desc';
$payment_description = '';
if (!empty($method->$plugin_desc)) {
$payment_description = $method->$plugin_desc;
}
$payment_name = $method->$plugin_name;
$html = $this->renderByLayout ('payment_cart', array(
'logo' => $image,
'text' => $text,
'payment_description' => $payment_description,
'payment_name' => $payment_name
));
return $html;
}
}
/**
* 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) {
$nbMethod = 0;
if ($this->getPluginMethods ($cart->vendorId) === 0) {
return NULL;
}
foreach ($this->methods as $method) {
$type = NULL;
$cData = KlarnaHandler::getcData ($method, $this->getCartAddress ($cart, $type, FALSE));
if ($cData) {
if ($nb = (int)$this->checkCountryCondition ($method, $cData['country_code_3'], $cart)) {
$nbMethod = $nbMethod + $nb;
}
}
}
$paymentCounter = $paymentCounter + $nbMethod;
if ($nbMethod == 0) {
return NULL;
} else {
return 0;
}
}
/**
* This method is fired when showing the order details in the frontend.
* It displays the method-specific data.
*
* @param $virtuemart_order_id
* @param $virtuemart_paymentmethod_id
* @param $payment_name
* @internal param int $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) {
if ($this->onShowOrderFE ($virtuemart_order_id, $virtuemart_paymentmethod_id, $payment_name)) {
return FALSE;
}
return NULL;
}
function plgVmOnCheckoutAdvertise ($cart, &$payment_advertise) {
$vendorId = 1;
$loadScriptAndCss = FALSE;
if (!class_exists ('Klarna_payments')) {
require (JPATH_VMKLARNAPLUGIN . DS . 'klarna' . DS . 'helpers' . DS . 'klarna_payments.php');
}
$country_code = NULL;
$countryId = 0;
if ($this->getPluginMethods ($cart->vendorId) === 0) {
return FALSE;
}
$this->_getCountryCode ($cart, $country_code, $countryId);
foreach ($this->methods as $method) {
if ($cart->virtuemart_paymentmethod_id == $method->virtuemart_paymentmethod_id) {
continue;
}
if (!($cData = $this->checkCountryCondition ($method, $country_code, $cart))) {
return NULL;
}
if (strtolower ($country_code) == 'nld') {
// Since 12/09/12: merchants can sell goods with Klarna Invoice up to thousands of euros. So the price check has been moved here
if (!KlarnaHandler::checkPartNLpriceCondition ($cart)) {
// We can't show our payment options for Dutch customers
// if price exceeds 250 euro. Will be replaced with ILT in
// the future.
return NULL;
}
}
if (in_array ('part', $cData['payments_activated'])) {
$payments = new klarna_payments($cData, KlarnaHandler::getShipToAddress ($cart));
// TODO: change to there is a function in the API
$sFee = $payments->getCheapestMonthlyCost ($cart, $cData);
if ($sFee) {
$payment_advertise[] = $this->renderByLayout ('cart_advertisement',
array("sFee" => $sFee,
"eid" => $cData['eid'],
"country"=> $cData['country_code']
));
}
}
}
}
/**
* This method is fired when showing when printing an Order
* It displays the the payment method-specific data.
*
* @param integer $order_number The order Number
* @param integer $method_id method used for this order
* @return mixed Null when for payment methods that were not selected, text (HTML) otherwise
*/
function plgVmOnShowOrderPrintPayment ($order_number, $method_id) {
return $this->onShowOrderPrint ($order_number, $method_id);
}
/**
* @return mixed
*/
function _getVendorCurrency () {
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->currency_code_3;
}
/**
*
*/
function loadScriptAndCss () {
static $loaded = false;
if ($loaded) {
return;
}
$assetsPath = VMKLARNAPLUGINWEBROOT . '/klarna/assets/';
JHTML::stylesheet ('style.css', $assetsPath . 'css/', FALSE);
JHTML::stylesheet ('klarna.css', $assetsPath . 'css/', FALSE);
JHTML::script ('klarna_general.js', $assetsPath . 'js/', FALSE);
JHTML::script ('klarnaConsentNew.js', 'http://static.klarna.com/external/js/', FALSE);
$document = JFactory::getDocument ();
/*
$document->addScriptDeclaration ('
klarna.ajaxPath = "' . juri::root () . '/index.php?option=com_virtuemart&view=plugin&vmtype=vmpayment&name=klarna";
');
*/
$loaded=true;
}
}
// No closing tag
home/academiac/www/plugins/vmpayment/klarna/klarna/api/klarna.php 0000604 00000405552 15137554015 0021177 0 ustar 00
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* This API provides a way to integrate with Klarna's services over the
* XMLRPC protocol.
*
* All strings inputted need to be encoded with ISO-8859-1.
* In addition you need to decode HTML entities, if they exist.
*
* For more information see our
* {@link http://integration.klarna.com/en/api/step-by-step step by step} guide.
*
* Dependencies:
*
* xmlrpc-3.0.0.beta/lib/xmlrpc.inc
* from {@link http://phpxmlrpc.sourceforge.net/}
*
* xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc
* from {@link http://phpxmlrpc.sourceforge.net/}
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna
{
/**
* Klarna PHP API version identifier.
*
* @var string
*/
protected $VERSION = 'php:api:2.4.2';
/**
* Klarna protocol identifier.
*
* @var string
*/
protected $PROTO = '4.1';
/**
* Flag to indicate use of the report server Candice.
*
* @var bool
*/
private static $_candice = true;
/**
* URL/Address to the Candice server.
* Port used is 80.
*
* @var string
*/
private static $_c_addr = "clientstat.klarna.com";
/**
* Constants used with LIVE mode for the communications with Klarna.
*
* @var int
*/
const LIVE = 0;
/**
* URL/Address to the live Klarna Online server.
* Port used is 443 for SSL and 80 without.
*
* @var string
*/
private static $_live_addr = 'payment.klarna.com';
/**
* Constants used with BETA mode for the communications with Klarna.
*
* @var int
*/
const BETA = 1;
/**
* URL/Address to the beta test Klarna Online server.
* Port used is 443 for SSL and 80 without.
*
* @var string
*/
private static $_beta_addr = 'payment.testdrive.klarna.com';
/**
* Indicates whether the communications is over SSL or not.
*
* @var bool
*/
protected $ssl = false;
/**
* An object of xmlrpc_client, used to communicate with Klarna.
*
* @link http://phpxmlrpc.sourceforge.net/
*
* @var xmlrpc_client
*/
protected $xmlrpc;
/**
* Which server the Klarna API is using, LIVE or BETA (TESTING).
*
* @see Klarna::LIVE
* @see Klarna::BETA
*
* @var int
*/
protected $mode;
/**
* Associative array holding url information.
*
* @var array
*/
private $_url;
/**
* The estore's identifier received from Klarna.
*
* @var int
*/
private $_eid;
/**
* The estore's shared secret received from Klarna.
*
* Note:
* DO NOT SHARE THIS WITH ANYONE!
*
* @var string
*/
private $_secret;
/**
* KlarnaCountry constant.
*
* @see KlarnaCountry
*
* @var int
*/
private $_country;
/**
* KlarnaCurrency constant.
*
* @see KlarnaCurrency
*
* @var int
*/
private $_currency;
/**
* KlarnaLanguage constant.
*
* @see KlarnaLanguage
*
* @var int
*/
private $_language;
/**
* An array of articles for the current order.
*
* @var array
*/
protected $goodsList;
/**
* An array of article numbers and quantity.
*
* @var array
*/
protected $artNos;
/**
* An KlarnaAddr object containing the billing address.
*
* @var KlarnaAddr
*/
protected $billing;
/**
* An KlarnaAddr object containing the shipping address.
*
* @var KlarnaAddr
*/
protected $shipping;
/**
* Estore's user(name) or identifier.
* Only used in {@link Klarna::addTransaction()}.
*
* @var string
*/
protected $estoreUser = "";
/**
* External order numbers from other systems.
*
* @var string
*/
protected $orderid = array("", "");
/**
* Reference (person) parameter.
*
* @var string
*/
protected $reference = "";
/**
* Reference code parameter.
*
* @var string
*/
protected $reference_code = "";
/**
* An array of named extra info.
*
* @var array
*/
protected $extraInfo = array();
/**
* An array of named bank info.
*
* @var array
*/
protected $bankInfo = array();
/**
* An array of named income expense info.
*
* @var array
*/
protected $incomeInfo = array();
/**
* An array of named shipment info.
*
* @var array
*/
protected $shipInfo = array();
/**
* An array of named travel info.
*
* @ignore Do not show this in PHPDoc.
* @var array
*/
protected $travelInfo = array();
/**
* An array of named activate info
*
* @ignore
* @var array
*/
protected $activateInfo = array();
/**
* An array of named session id's.
* E.g. "dev_id_1" => ...
*
* @var array
*/
protected $sid = array();
/**
* A comment sent in the XMLRPC communications.
* This is resetted using clear().
*
* @var string
*/
protected $comment = "";
/**
* An array with all the checkoutHTML objects.
*
* @var array
*/
protected $coObjects = array();
/**
* Flag to indicate if the API should output verbose
* debugging information.
*
* @var bool
*/
public static $debug = false;
/**
* Turns on the internal XMLRPC debugging.
*
* @var bool
*/
public static $xmlrpcDebug = false;
/**
* If this is set to true, XMLRPC invocation is disabled.
*
* @var bool
*/
public static $disableXMLRPC = false;
/**
* If the estore is using a proxy which populates the clients IP to
* x_forwarded_for
* then and only then should this be set to true.
*
* Note:
* USE WITH CARE!
*
* @var bool
*/
public static $x_forwarded_for = false;
/**
* Array of HTML entities, used to create numeric htmlentities.
*
* @ignore Do not show this in PHPDoc.
* @var array
*/
protected static $htmlentities = false;
/**
* Populated with possible proxy information.
* A comma separated list of IP addresses.
*
* @var string
*/
private $_x_fwd;
/**
* The storage class for PClasses.
*
* Use 'xml' for xmlstorage.class.php.
* Use 'mysql' for mysqlstorage.class.php.
* Use 'json' for jsonstorage.class.php.
*
* @var string
*/
protected $pcStorage;
/**
* The storage URI for PClasses.
*
* Use the absolute or relative URI to a file if
* {@link Klarna::$pcStorage} is set as 'xml' or 'json'.
* Use a HTTP-auth similar URL if {@link Klarna::$pcStorage} is set
* as 'mysql',
* e.g. user:passwd@addr:port/dbName.dbTable.
* Or an associative array (recommended) {@see MySQLStorage}
*
* @var mixed
*/
protected $pcURI;
/**
* PCStorage instance.
*
* @ignore Do not show this in PHPDoc.
* @var PCStorage
*/
protected $pclasses;
/**
* ArrayAccess instance.
*
* @ignore Do not show this in PHPDoc.
* @var ArrayAccess
*/
protected $config;
/**
* Empty constructor, because sometimes it's needed.
*/
public function __construct()
{
}
/**
* Checks if the config has fields described in argument.
* Missing field(s) is in the exception message.
*
* To check that the config has eid and secret:
*
* try {
* $this->hasFields('eid', 'secret');
* }
* catch(Exception $e) {
* echo "Missing fields: " . $e->getMessage();
* }
*
*
* @throws Exception
* @return void
*/
protected function hasFields(/*variable arguments*/)
{
$missingFields = array();
$args = func_get_args();
foreach ($args as $field) {
if (!isset($this->config[$field])) {
$missingFields[] = $field;
}
}
if (count($missingFields) > 0) {
throw new Klarna_ConfigFieldMissingException(
implode(', ', $missingFields)
);
}
}
/**
* Initializes the Klarna object accordingly to the set config object.
*
* @throws KlarnaException
* @return void
*/
protected function init()
{
$this->hasFields('eid', 'secret', 'mode', 'pcStorage', 'pcURI');
if (!is_int($this->config['eid'])) {
$this->config['eid'] = intval($this->config['eid']);
}
if ($this->config['eid'] <= 0) {
throw new Klarna_ConfigFieldMissingException('eid');
}
if (!is_string($this->config['secret'])) {
$this->config['secret'] = strval($this->config['secret']);
}
if (strlen($this->config['secret']) == 0) {
throw new Klarna_ConfigFieldMissingException('secret');
}
//Set the shop id and secret.
$this->_eid = $this->config['eid'];
$this->_secret = $this->config['secret'];
//Set the country specific attributes.
try {
$this->hasFields('country', 'language', 'currency');
//If hasFields doesn't throw exception we can set them all.
$this->setCountry($this->config['country']);
$this->setLanguage($this->config['language']);
$this->setCurrency($this->config['currency']);
} catch(Exception $e) {
//fields missing for country, language or currency
$this->_country = $this->_language = $this->_currency = null;
}
//Set addr and port according to mode.
$this->mode = (int)$this->config['mode'];
$this->_url = array();
// If a custom url has been added to the config, use that as xmlrpc
// recipient.
if (isset($this->config['url'])) {
$this->_url = parse_url($this->config['url']);
if ($this->_url === false) {
$message = "Configuration value 'url' could not be parsed. " .
"(Was: '{$this->config['url']}')";
Klarna::printDebug(__METHOD__, $message);
throw new InvalidArgumentException($message);
}
} else {
$this->_url['scheme'] = 'https';
if ($this->mode === self::LIVE) {
$this->_url['host'] = self::$_live_addr;
} else {
$this->_url['host'] = self::$_beta_addr;
}
if (isset($this->config['ssl'])
&& (bool)$this->config['ssl'] === false
) {
$this->_url['scheme'] = 'http';
}
}
// If no port has been specified, deduce from url scheme
if (!array_key_exists('port', $this->_url)) {
if ($this->_url['scheme'] === 'https') {
$this->_url['port'] = 443;
} else {
$this->_url['port'] = 80;
}
}
try {
$this->hasFields('candice');
self::$_candice = (bool)$this->config['candice'];
} catch(Exception $e) {
//No 'candice' field ignore it...
}
try {
$this->hasFields('xmlrpcDebug');
Klarna::$xmlrpcDebug = $this->config['xmlrpcDebug'];
} catch(Exception $e) {
//No 'xmlrpcDebug' field ignore it...
}
try {
$this->hasFields('debug');
Klarna::$debug = $this->config['debug'];
} catch(Exception $e) {
//No 'debug' field ignore it...
}
$this->pcStorage = $this->config['pcStorage'];
$this->pcURI = $this->config['pcURI'];
// Default path to '/' if not set.
if (!array_key_exists('path', $this->_url)) {
$this->_url['path'] = '/';
}
$this->xmlrpc = new xmlrpc_client(
$this->_url['path'],
$this->_url['host'],
$this->_url['port'],
$this->_url['scheme']
);
$this->xmlrpc->request_charset_encoding = 'ISO-8859-1';
}
/**
* Method of ease for setting common config fields.
*
* The storage module for PClasses:
* Use 'xml' for xmlstorage.class.php.
* Use 'mysql' for mysqlstorage.class.php.
* Use 'json' for jsonstorage.class.php.
*
* The storage URI for PClasses:
* Use the absolute or relative URI to a file if {@link Klarna::$pcStorage}
* is set as 'xml' or 'json'.
* Use a HTTP-auth similar URL if {@link Klarna::$pcStorage} is set as
* mysql', e.g. user:passwd@addr:port/dbName.dbTable.
* Or an associative array (recommended) {@see MySQLStorage}
*
* Note:
* This disables the config file storage.
*
* @param int $eid Merchant ID/EID
* @param string $secret Secret key/Shared key
* @param int $country {@link KlarnaCountry}
* @param int $language {@link KlarnaLanguage}
* @param int $currency {@link KlarnaCurrency}
* @param int $mode {@link Klarna::LIVE} or {@link Klarna::BETA}
* @param string $pcStorage PClass storage module.
* @param string $pcURI PClass URI.
* @param bool $ssl Whether HTTPS (HTTP over SSL) or HTTP is used.
* @param bool $candice Error reporting to Klarna.
*
* @see Klarna::setConfig()
* @see KlarnaConfig
*
* @throws KlarnaException
* @return void
*/
public function config(
$eid, $secret, $country, $language, $currency,
$mode = Klarna::LIVE, $pcStorage = 'json', $pcURI = 'pclasses.json',
$ssl = true, $candice = true
) {
try {
KlarnaConfig::$store = false;
$this->config = new KlarnaConfig(null);
$this->config['eid'] = $eid;
$this->config['secret'] = $secret;
$this->config['country'] = $country;
$this->config['language'] = $language;
$this->config['currency'] = $currency;
$this->config['mode'] = $mode;
$this->config['ssl'] = $ssl;
$this->config['candice'] = $candice;
$this->config['pcStorage'] = $pcStorage;
$this->config['pcURI'] = $pcURI;
$this->init();
} catch(Exception $e) {
$this->config = null;
throw new KlarnaException(
$e->getMessage(),
$e->getCode()
);
}
}
/**
* Sets and initializes this Klarna object using the supplied config object.
*
* @param KlarnaConfig &$config Config object.
*
* @see KlarnaConfig
* @throws KlarnaException
* @return void
*/
public function setConfig(&$config)
{
$this->_checkConfig($config);
$this->config = $config;
$this->init();
}
/**
* Get the complete locale (country, language, currency) to use for the
* values passed, or the configured value if passing null.
*
* @param mixed $country country constant or code
* @param mixed $language language constant or code
* @param mixed $currency currency constant or code
*
* @throws KlarnaException
* @return array
*/
public function getLocale(
$country = null, $language = null, $currency = null
) {
$locale = array(
'country' => null,
'language' => null,
'currency' => null
);
if ($country === null) {
// Use the configured country / language / currency
$locale['country'] = $this->_country;
if ($this->_language !== null) {
$locale['language'] = $this->_language;
}
if ($this->_currency !== null) {
$locale['currency'] = $this->_currency;
}
} else {
// Use the given country / language / currency
if (!is_numeric($country)) {
$country = KlarnaCountry::fromCode($country);
}
$locale['country'] = intval($country);
if ($language !== null) {
if (!is_numeric($language)) {
$language = KlarnaLanguage::fromCode($language);
}
$locale['language'] = intval($language);
}
if ($currency !== null) {
if (!is_numeric($currency)) {
$currency = KlarnaCurrency::fromCode($currency);
}
$locale['currency'] = intval($currency);
}
}
// Complete partial structure with defaults
if ($locale['currency'] === null) {
$locale['currency'] = $this->getCurrencyForCountry(
$locale['country']
);
}
if ($locale['language'] === null) {
$locale['language'] = $this->getLanguageForCountry(
$locale['country']
);
}
$this->_checkCountry($locale['country']);
$this->_checkCurrency($locale['currency']);
$this->_checkLanguage($locale['language']);
return $locale;
}
/**
* Sets the country used.
*
* Note:
* If you input 'dk', 'fi', 'de', 'nl', 'no' or 'se',
* then currency and language will be set to mirror that country.
*
* @param string|int $country {@link KlarnaCountry}
*
* @see KlarnaCountry
*
* @throws KlarnaException
* @return void
*/
public function setCountry($country)
{
if (!is_numeric($country)
&& (strlen($country) == 2 || strlen($country) == 3)
) {
$country = KlarnaCountry::fromCode($country);
}
$this->_checkCountry($country);
$this->_country = $country;
}
/**
* Returns the country code for the set country constant.
*
* @param int $country {@link KlarnaCountry Country} constant.
*
* @return string Two letter code, e.g. "se", "no", etc.
*/
public function getCountryCode($country = null)
{
if ($country === null) {
$country = $this->_country;
}
$code = KlarnaCountry::getCode($country);
return (string) $code;
}
/**
* Returns the {@link KlarnaCountry country} constant from the country code.
*
* @param string $code Two letter code, e.g. "se", "no", etc.
*
* @throws KlarnaException
* @return int {@link KlarnaCountry Country} constant.
*/
public static function getCountryForCode($code)
{
$country = KlarnaCountry::fromCode($code);
if ($country === null) {
throw new Klarna_UnknownCountryException($code);
}
return $country;
}
/**
* Returns the country constant.
*
* @return int {@link KlarnaCountry}
*/
public function getCountry()
{
return $this->_country;
}
/**
* Sets the language used.
*
* Note:
* You can use the two letter language code instead of the constant.
* E.g. 'da' instead of using {@link KlarnaLanguage::DA}.
*
* @param string|int $language {@link KlarnaLanguage}
*
* @see KlarnaLanguage
*
* @throws KlarnaException
* @return void
*/
public function setLanguage($language)
{
if (!is_numeric($language) && strlen($language) == 2) {
$this->setLanguage(self::getLanguageForCode($language));
} else {
$this->_checkLanguage($language);
$this->_language = $language;
}
}
/**
* Returns the language code for the set language constant.
*
* @param int $language {@link KlarnaLanguage Language} constant.
*
* @return string Two letter code, e.g. "da", "de", etc.
*/
public function getLanguageCode($language = null)
{
if ($language === null) {
$language = $this->_language;
}
$code = KlarnaLanguage::getCode($language);
return (string) $code;
}
/**
* Returns the {@link KlarnaLanguage language} constant from the language code.
*
* @param string $code Two letter code, e.g. "da", "de", etc.
*
* @throws KlarnaException
* @return int {@link KlarnaLanguage Language} constant.
*/
public static function getLanguageForCode($code)
{
$language = KlarnaLanguage::fromCode($code);
if ($language === null) {
throw new Klarna_UnknownLanguageException($code);
}
return $language;
}
/**
* Returns the language constant.
*
* @return int {@link KlarnaLanguage}
*/
public function getLanguage()
{
return $this->_language;
}
/**
* Sets the currency used.
*
* Note:
* You can use the three letter shortening of the currency.
* E.g. "dkk", "eur", "nok" or "sek" instead of the constant.
*
* @param string|int $currency {@link KlarnaCurrency}
*
* @see KlarnaCurrency
*
* @throws KlarnaException
* @return void
*/
public function setCurrency($currency)
{
if (!is_numeric($currency) && strlen($currency) == 3) {
$this->setCurrency(self::getCurrencyForCode($currency));
} else {
$this->_checkCurrency($currency);
$this->_currency = $currency;
}
}
/**
* Returns the {@link KlarnaCurrency currency} constant from the currency
* code.
*
* @param string $code Two letter code, e.g. "dkk", "eur", etc.
*
* @throws KlarnaException
* @return int {@link KlarnaCurrency Currency} constant.
*/
public static function getCurrencyForCode($code)
{
$currency = KlarnaCurrency::fromCode($code);
if ($currency === null) {
throw new Klarna_UnknownCurrencyException($code);
}
return $currency;
}
/**
* Returns the the currency code for the set currency constant.
*
* @param int $currency {@link KlarnaCurrency Currency} constant.
*
* @return string Three letter currency code.
*/
public function getCurrencyCode($currency = null)
{
if ($currency === null) {
$currency = $this->_currency;
}
$code = KlarnaCurrency::getCode($currency);
return (string) $code;
}
/**
* Returns the set currency constant.
*
* @return int {@link KlarnaCurrency}
*/
public function getCurrency()
{
return $this->_currency;
}
/**
* Returns the {@link KlarnaLanguage language} constant for the specified
* or set country.
*
* @param int $country {@link KlarnaCountry Country} constant.
*
* @deprecated Do not use.
*
* @return int|false if no match otherwise KlarnaLanguage constant.
*/
public function getLanguageForCountry($country = null)
{
if ($country === null) {
$country = $this->_country;
}
// Since getLanguage defaults to EN, check so we actually have a match
$language = KlarnaCountry::getLanguage($country);
if (KlarnaCountry::checkLanguage($country, $language)) {
return $language;
}
return false;
}
/**
* Returns the {@link KlarnaCurrency currency} constant for the specified
* or set country.
*
* @param int $country {@link KlarnaCountry country} constant.
*
* @deprecated Do not use.
*
* @return int|false {@link KlarnaCurrency currency} constant.
*/
public function getCurrencyForCountry($country = null)
{
if ($country === null) {
$country = $this->_country;
}
return KlarnaCountry::getCurrency($country);
}
/**
* Sets the session id's for various device identification,
* behaviour identification software.
*
* Available named session id's:
* string - dev_id_1
* string - dev_id_2
* string - dev_id_3
* string - beh_id_1
* string - beh_id_2
* string - beh_id_3
*
* @param string $name Session ID identifier, e.g. 'dev_id_1'.
* @param string $sid Session ID.
*
* @throws KlarnaException
* @return void
*/
public function setSessionID($name, $sid)
{
$this->_checkArgument($name, "name");
$this->_checkArgument($sid, "sid");
$this->sid[$name] = $sid;
}
/**
* Sets the shipment information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* int - delay_adjust
* string - shipping_company
* string - shipping_product
* string - tracking_no
* array - warehouse_addr
*
* "warehouse_addr" is sent using {@link KlarnaAddr::toArray()}.
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @throws KlarnaException
* @return void
*/
public function setShipmentInfo($name, $value)
{
$this->_checkArgument($name, "name");
$this->shipInfo[$name] = $value;
}
/**
* Sets the Activation information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* int - flags
* int - bclass
* string - orderid1
* string - orderid2
* string - ocr
* string - reference
* string - reference_code
* string - cust_no
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @see setShipmentInfo
*
* @return void
*/
public function setActivateInfo($name, $value)
{
$this->activateInfo[$name] = $value;
}
/**
* Sets the extra information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* string - cust_no
* string - estore_user
* string - maiden_name
* string - place_of_birth
* string - password
* string - new_password
* string - captcha
* int - poa_group
* string - poa_pno
* string - ready_date
* string - rand_string
* int - bclass
* string - pin
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @throws KlarnaException
* @return void
*/
public function setExtraInfo($name, $value)
{
$this->_checkArgument($name, "name");
$this->extraInfo[$name] = $value;
}
/**
* Sets the income expense information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* int - yearly_salary
* int - no_people_in_household
* int - no_children_below_18
* int - net_monthly_household_income
* int - monthly_cost_accommodation
* int - monthly_cost_other_loans
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @throws KlarnaException
* @return void
*/
public function setIncomeInfo($name, $value)
{
$this->_checkArgument($name, "name");
$this->incomeInfo[$name] = $value;
}
/**
* Sets the bank information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* int - bank_acc_bic
* int - bank_acc_no
* int - bank_acc_pin
* int - bank_acc_tan
* string - bank_name
* string - bank_city
* string - iban
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @throws KlarnaException
* @return void
*/
public function setBankInfo($name, $value)
{
$this->_checkArgument($name, "name");
$this->bankInfo[$name] = $value;
}
/**
* Sets the travel information for the upcoming transaction.
*
* Using this method is optional.
*
* Available named values are:
* string - travel_company
* string - reseller_company
* string - departure_date
* string - return_date
* array - destinations
* array - passenger_list
* array - passport_no
* array - driver_license_no
*
* Make sure you send in the values as the right data type.
* Use strval, intval or similar methods to ensure the right type is sent.
*
* @param string $name key
* @param mixed $value value
*
* @throws KlarnaException
* @return void
*/
public function setTravelInfo($name, $value)
{
$this->_checkArgument($name, "name");
$this->travelInfo[$name] = $value;
}
/**
* Returns the clients IP address.
*
* @return string
*/
public function getClientIP()
{
$tmp_ip = '';
$x_fwd = null;
//Proxy handling.
if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
$tmp_ip = $_SERVER['REMOTE_ADDR'];
}
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$x_fwd = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
if (self::$x_forwarded_for && ($x_fwd !== null)) {
$forwarded = explode(",", $x_fwd);
return trim($forwarded[0]);
}
return $tmp_ip;
}
/**
* Sets the specified address for the current order.
*
* Address type can be:
* {@link KlarnaFlags::IS_SHIPPING}
* {@link KlarnaFlags::IS_BILLING}
*
* @param int $type Address type.
* @param KlarnaAddr $addr Specified address.
*
* @throws KlarnaException
* @return void
*/
public function setAddress($type, $addr)
{
if (!($addr instanceof KlarnaAddr)) {
throw new Klarna_InvalidKlarnaAddrException;
}
if ($addr->isCompany === null) {
$addr->isCompany = false;
}
if ($type === KlarnaFlags::IS_SHIPPING) {
$this->shipping = $addr;
self::printDebug("shipping address array", $this->shipping);
return;
}
if ($type === KlarnaFlags::IS_BILLING) {
$this->billing = $addr;
self::printDebug("billing address array", $this->billing);
return;
}
throw new Klarna_UnknownAddressTypeException($type);
}
/**
* Sets order id's from other systems for the upcoming transaction.
* User is only sent with {@link Klarna::addTransaction()}.
*
* @param string $orderid1 order id 1
* @param string $orderid2 order id 2
* @param string $user username
*
* @see Klarna::setExtraInfo()
*
* @throws KlarnaException
* @return void
*/
public function setEstoreInfo($orderid1 = "", $orderid2 = "", $user = "")
{
if (!is_string($orderid1)) {
$orderid1 = strval($orderid1);
}
if (!is_string($orderid2)) {
$orderid2 = strval($orderid2);
}
if (!is_string($user)) {
$user = strval($user);
}
if (strlen($user) > 0 ) {
$this->setExtraInfo('estore_user', $user);
}
$this->orderid[0] = $orderid1;
$this->orderid[1] = $orderid2;
}
/**
* Sets the reference (person) and reference code, for the upcoming
* transaction.
*
* If this is omitted, it can grab first name, last name from the address
* and use that as a reference person.
*
* @param string $ref Reference person / message to customer on invoice.
* @param string $code Reference code / message to customer on invoice.
*
* @return void
*/
public function setReference($ref, $code)
{
$this->_checkRef($ref, $code);
$this->reference = $ref;
$this->reference_code = $code;
}
/**
* Returns the reference (person).
*
* @return string
*/
public function getReference()
{
return $this->reference;
}
/**
* Returns an associative array used to send the address to Klarna.
* TODO: Kill it all
*
* @param KlarnaAddr $addr Address object to assemble.
*
* @throws KlarnaException
* @return array The address for the specified method.
*/
protected function assembleAddr($addr)
{
if (!($addr instanceof KlarnaAddr)) {
throw new Klarna_InvalidKlarnaAddrException;
}
return $addr->toArray();
}
/**
* Sets the comment field, which can be shown in the invoice.
*
* @param string $data comment to set
*
* @return void
*/
public function setComment($data)
{
$this->comment = $data;
}
/**
* Adds an additional comment to the comment field. Appends with a newline.
*
* @param string $data comment to add
*
* @see Klarna::setComment()
*
* @return void
*/
public function addComment($data)
{
$this->comment .= "\n".$data;
}
/**
* Returns the PNO/SSN encoding constant for currently set country.
*
* Note:
* Country, language and currency needs to match!
*
* @throws KlarnaException
* @return int {@link KlarnaEncoding} constant.
*/
public function getPNOEncoding()
{
$this->_checkLocale();
$country = KlarnaCountry::getCode($this->_country);
return KlarnaEncoding::get($country);
}
/**
* Purpose: The get_addresses function is used to retrieve a customer's
* address(es). Using this, the customer is not required to enter any
* information, only confirm the one presented to him/her.
*
* The get_addresses function can also be used for companies.
* If the customer enters a company number, it will return all the
* addresses where the company is registered at.
*
* The get_addresses function is ONLY allowed to be used for Swedish
* persons with the following conditions:
*
* -
* It can be only used if invoice or part payment is
* the default payment method
*
* -
* It has to disappear if the customer chooses another
* payment method
*
* -
* The button is not allowed to be called "get address", but
* "continue" or
* it can be picked up automatically when all the numbers have
* been typed.
*
*
*
* Type can be one of these:
* {@link KlarnaFlags::GA_ALL},
* {@link KlarnaFlags::GA_LAST},
* {@link KlarnaFlags::GA_GIVEN}.
*
* @param string $pno Social security number, personal number, ...
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
* @param int $type Specifies returned information.
*
* @link http://integration.klarna.com/en/api/standard-integration/functions
* /getaddresses
* @throws KlarnaException
* @return array An array of {@link KlarnaAddr} objects.
*/
public function getAddresses(
$pno, $encoding = null, $type = KlarnaFlags::GA_GIVEN
) {
if ($this->_country !== KlarnaCountry::SE) {
throw new Klarna_UnsupportedMarketException("Sweden");
}
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
$this->_checkPNO($pno, $encoding);
$digestSecret = self::digest(
$this->colon(
$this->_eid, $pno, $this->_secret
)
);
$paramList = array(
$pno,
$this->_eid,
$digestSecret,
$encoding,
$type,
$this->getClientIP()
);
self::printDebug("get_addresses array", $paramList);
$result = $this->xmlrpc_call('get_addresses', $paramList);
self::printDebug("get_addresses result array", $result);
$addrs = array();
foreach ($result as $tmpAddr) {
try {
$addr = new KlarnaAddr();
if ($type === KlarnaFlags::GA_GIVEN) {
$addr->isCompany = (count($tmpAddr) == 5) ? true : false;
if ($addr->isCompany) {
$addr->setCompanyName($tmpAddr[0]);
$addr->setStreet($tmpAddr[1]);
$addr->setZipCode($tmpAddr[2]);
$addr->setCity($tmpAddr[3]);
$addr->setCountry($tmpAddr[4]);
} else {
$addr->setFirstName($tmpAddr[0]);
$addr->setLastName($tmpAddr[1]);
$addr->setStreet($tmpAddr[2]);
$addr->setZipCode($tmpAddr[3]);
$addr->setCity($tmpAddr[4]);
$addr->setCountry($tmpAddr[5]);
}
} else if ($type === KlarnaFlags::GA_LAST) {
// Here we cannot decide if it is a company or not?
// Assume private person.
$addr->setLastName($tmpAddr[0]);
$addr->setStreet($tmpAddr[1]);
$addr->setZipCode($tmpAddr[2]);
$addr->setCity($tmpAddr[3]);
$addr->setCountry($tmpAddr[4]);
} else if ($type === KlarnaFlags::GA_ALL) {
if (strlen($tmpAddr[0]) > 0) {
$addr->setFirstName($tmpAddr[0]);
$addr->setLastName($tmpAddr[1]);
} else {
$addr->isCompany = true;
$addr->setCompanyName($tmpAddr[1]);
}
$addr->setStreet($tmpAddr[2]);
$addr->setZipCode($tmpAddr[3]);
$addr->setCity($tmpAddr[4]);
$addr->setCountry($tmpAddr[5]);
} else {
continue;
}
$addrs[] = $addr;
} catch(Exception $e) {
//Silently fail
}
}
return $addrs;
}
/**
* Adds an article to the current goods list for the current order.
*
* Note:
* It is recommended that you use {@link KlarnaFlags::INC_VAT}.
*
* Flags can be:
* {@link KlarnaFlags::INC_VAT}
* {@link KlarnaFlags::IS_SHIPMENT}
* {@link KlarnaFlags::IS_HANDLING}
* {@link KlarnaFlags::PRINT_1000}
* {@link KlarnaFlags::PRINT_100}
* {@link KlarnaFlags::PRINT_10}
* {@link KlarnaFlags::NO_FLAG}
*
* Some flags can be added to each other for multiple options.
*
* @param int $qty Quantity.
* @param string $artNo Article number.
* @param string $title Article title.
* @param int $price Article price.
* @param float $vat VAT in percent, e.g. 25% is inputted as 25.
* @param float $discount Possible discount on article.
* @param int $flags Options which specify the article
* ({@link KlarnaFlags::IS_HANDLING}) and it's price
* ({@link KlarnaFlags::INC_VAT})
*
* @see Klarna::addTransaction()
* @see Klarna::reserveAmount()
* @see Klarna::activateReservation()
*
* @throws KlarnaException
* @return void
*/
public function addArticle(
$qty, $artNo, $title, $price, $vat, $discount = 0,
$flags = KlarnaFlags::INC_VAT
) {
$this->_checkQty($qty);
// Either artno or title has to be set
if ((($artNo === null ) || ($artNo == ""))
&& (($title === null ) || ($title == ""))
) {
throw new Klarna_ArgumentNotSetException('Title and ArtNo', 50026);
}
$this->_checkPrice($price);
$this->_checkVAT($vat);
$this->_checkDiscount($discount);
$this->_checkInt($flags, 'flags');
//Create goodsList array if not set.
if (!$this->goodsList || !is_array($this->goodsList)) {
$this->goodsList = array();
}
//Populate a temp array with the article details.
$tmpArr = array(
"artno" => $artNo,
"title" => $title,
"price" => $price,
"vat" => $vat,
"discount" => $discount,
"flags" => $flags
);
//Add the temp array and quantity field to the internal goods list.
$this->goodsList[] = array(
"goods" => $tmpArr,
"qty" => $qty
);
if (count($this->goodsList) > 0) {
self::printDebug(
"article added",
$this->goodsList[count($this->goodsList)-1]
);
}
}
/**
* Assembles and sends the current order to Klarna.
* This clears all relevant data if $clear is set to true.
*
* This method returns an array with:
* Invoice number
* Order status flag
*
* If the flag {@link KlarnaFlags::RETURN_OCR} is used:
* Invoice number
* OCR number
* Order status flag
*
* Order status can be:
* {@link KlarnaFlags::ACCEPTED}
* {@link KlarnaFlags::PENDING}
* {@link KlarnaFlags::DENIED}
*
* Gender is only required for Germany and Netherlands.
*
* Flags can be:
* {@link KlarnaFlags::NO_FLAG}
* {@link KlarnaFlags::TEST_MODE}
* {@link KlarnaFlags::AUTO_ACTIVATE}
* {@link KlarnaFlags::SENSITIVE_ORDER}
* {@link KlarnaFlags::RETURN_OCR}
* {@link KlarnaFlags::M_PHONE_TRANSACTION}
* {@link KlarnaFlags::M_SEND_PHONE_PIN}
*
* Some flags can be added to each other for multiple options.
*
* Note:
* Normal shipment type is assumed unless otherwise specified,
* ou can do this by calling:
* {@link Klarna::setShipmentInfo() setShipmentInfo('delay_adjust', ...)}
* with either:
* {@link KlarnaFlags::NORMAL_SHIPMENT NORMAL_SHIPMENT} or
* {@link KlarnaFlags::EXPRESS_SHIPMENT EXPRESS_SHIPMENT}
*
* @param string $pno Personal number, SSN, date of birth, etc.
* @param int $gender {@link KlarnaFlags::FEMALE} or
* {@link KlarnaFlags::MALE},
* null or "" for unspecified.
* @param int $flags Options which affect the behaviour.
* @param int $pclass PClass id used for this invoice.
* @param int $encoding {@link KlarnaEncoding Encoding} constant for the
* PNO parameter.
* @param bool $clear Whether customer info should be cleared after
* this call or not.
*
* @link http://integration.klarna.com/en/api/standard-integration/functions/
* addtransaction
*
* @throws KlarnaException
* @return array An array with invoice number and order status. [string, int]
*/
public function addTransaction(
$pno, $gender, $flags = KlarnaFlags::NO_FLAG,
$pclass = KlarnaPClass::INVOICE, $encoding = null, $clear = true
) {
$this->_checkLocale(50023);
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
if (!($flags & KlarnaFlags::PRE_PAY)) {
$this->_checkPNO($pno, $encoding);
}
if ($gender === 'm') {
$gender = KlarnaFlags::MALE;
} else if ($gender === 'f') {
$gender = KlarnaFlags::FEMALE;
}
if ($gender !== null && strlen($gender) > 0) {
$this->_checkInt($gender, 'gender');
}
$this->_checkInt($flags, 'flags');
$this->_checkInt($pclass, 'pclass');
//Check so required information is set.
$this->_checkGoodslist();
//We need at least one address set
if (!($this->billing instanceof KlarnaAddr)
&& !($this->shipping instanceof KlarnaAddr)
) {
throw new Klarna_MissingAddressException;
}
//If only one address is set, copy to the other address.
if (!($this->shipping instanceof KlarnaAddr)
&& ($this->billing instanceof KlarnaAddr)
) {
$this->shipping = $this->billing;
} else if (!($this->billing instanceof KlarnaAddr)
&& ($this->shipping instanceof KlarnaAddr)
) {
$this->billing = $this->shipping;
}
//Assume normal shipment unless otherwise specified.
if (!isset($this->shipInfo['delay_adjust'])) {
$this->setShipmentInfo('delay_adjust', KlarnaFlags::NORMAL_SHIPMENT);
}
//Make sure we get any session ID's or similar
$this->initCheckout();
//function add_transaction_digest
$string = "";
foreach ($this->goodsList as $goods) {
$string .= $goods['goods']['title'] .':';
}
$digestSecret = self::digest($string . $this->_secret);
//end function add_transaction_digest
$billing = $this->assembleAddr($this->billing);
$shipping = $this->assembleAddr($this->shipping);
//Shipping country must match specified country!
if (strlen($shipping['country']) > 0
&& ($shipping['country'] !== $this->_country)
) {
throw new Klarna_ShippingCountryException;
}
$paramList = array(
$pno,
$gender,
$this->reference,
$this->reference_code,
$this->orderid[0],
$this->orderid[1],
$shipping,
$billing,
$this->getClientIP(),
$flags,
$this->_currency,
$this->_country,
$this->_language,
$this->_eid,
$digestSecret,
$encoding,
$pclass,
$this->goodsList,
$this->comment,
$this->shipInfo,
$this->travelInfo,
$this->incomeInfo,
$this->bankInfo,
$this->sid,
$this->extraInfo
);
self::printDebug('add_invoice', $paramList);
$result = $this->xmlrpc_call('add_invoice', $paramList);
if ($clear === true) {
//Make sure any stored values that need to be unique between
//purchases are cleared.
foreach ($this->coObjects as $co) {
$co->clear();
}
$this->clear();
}
self::printDebug('add_invoice result', $result);
return $result;
}
/**
* Activates previously created invoice
* (from {@link Klarna::addTransaction()}).
*
* Note:
* If you want to change the shipment type, you can specify it using:
* {@link Klarna::setShipmentInfo() setShipmentInfo('delay_adjust', ...)}
* with either: {@link KlarnaFlags::NORMAL_SHIPMENT NORMAL_SHIPMENT} or
* {@link KlarnaFlags::EXPRESS_SHIPMENT EXPRESS_SHIPMENT}
*
* @param string $invNo Invoice number.
* @param int $pclass PClass id used for this invoice.
* @param bool $clear Whether customer info should be cleared after this
* call.
*
* @see Klarna::setShipmentInfo()
* @link http://integration.klarna.com/en/api/standard-integration/functions
* /activateinvoice
*
* @throws KlarnaException
* @return string An URL to the PDF invoice.
*/
public function activateInvoice(
$invNo, $pclass = KlarnaPClass::INVOICE, $clear = true
) {
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret,
$pclass,
$this->shipInfo
);
self::printDebug('activate_invoice', $paramList);
$result = $this->xmlrpc_call('activate_invoice', $paramList);
if ($clear === true) {
$this->clear();
}
self::printDebug('activate_invoice result', $result);
return $result;
}
/**
* Removes a passive invoices which has previously been created with
* {@link Klarna::addTransaction()}.
* True is returned if the invoice was successfully removed, otherwise an
* exception is thrown.
*
* @param string $invNo Invoice number.
*
* @throws KlarnaException
* @return bool
*/
public function deleteInvoice($invNo)
{
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret
);
self::printDebug('delete_invoice', $paramList);
$result = $this->xmlrpc_call('delete_invoice', $paramList);
return ($result == 'ok') ? true : false;
}
/**
* Summarizes the prices of the held goods list
*
* @return int total amount
*/
public function summarizeGoodsList()
{
$amount = 0;
if (!is_array($this->goodsList)) {
return $amount;
}
foreach ($this->goodsList as $goods) {
$price = $goods['goods']['price'];
// Add VAT if price is Excluding VAT
if (($goods['goods']['flags'] & KlarnaFlags::INC_VAT) === 0) {
$vat = $goods['goods']['vat'] / 100.0;
$price *= (1.0 + $vat);
}
// Reduce discounts
if ($goods['goods']['discount'] > 0) {
$discount = $goods['goods']['discount'] / 100.0;
$price *= (1.0 - $discount);
}
$amount += $price * (int)$goods['qty'];
}
return $amount;
}
/**
* Reserves a purchase amount for a specific customer.
* The reservation is valid, by default, for 7 days.
*
* This method returns an array with:
* A reservation number (rno)
* Order status flag
*
* Order status can be:
* {@link KlarnaFlags::ACCEPTED}
* {@link KlarnaFlags::PENDING}
* {@link KlarnaFlags::DENIED}
*
* Please note:
* Activation must be done with activate_reservation, i.e. you cannot
* activate through Klarna Online.
*
* Gender is only required for Germany and Netherlands.
*
* Flags can be set to:
* {@link KlarnaFlags::NO_FLAG}
* {@link KlarnaFlags::TEST_MODE}
* {@link KlarnaFlags::RSRV_SENSITIVE_ORDER}
* {@link KlarnaFlags::RSRV_PHONE_TRANSACTION}
* {@link KlarnaFlags::RSRV_SEND_PHONE_PIN}
*
* Some flags can be added to each other for multiple options.
*
* Note:
* Normal shipment type is assumed unless otherwise specified, you can do
* this by calling:
* {@link Klarna::setShipmentInfo() setShipmentInfo('delay_adjust', ...)}
* with either: {@link KlarnaFlags::NORMAL_SHIPMENT NORMAL_SHIPMENT} or
* {@link KlarnaFlags::EXPRESS_SHIPMENT EXPRESS_SHIPMENT}
*
* @param string $pno Personal number, SSN, date of birth, etc.
* @param int $gender {@link KlarnaFlags::FEMALE} or
* {@link KlarnaFlags::MALE}, null for unspecified.
* @param int $amount Amount to be reserved, including VAT.
* @param int $flags Options which affect the behaviour.
* @param int $pclass {@link KlarnaPClass::getId() PClass ID}.
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
* @param bool $clear Whether customer info should be cleared after
* this call.
*
* @link http://integration.klarna.com/en/api/advanced-integration
* /functions/reserveamount
*
* @throws KlarnaException
* @return array An array with reservation number and order
* status. [string, int]
*/
public function reserveAmount(
$pno, $gender, $amount, $flags = 0, $pclass = KlarnaPClass::INVOICE,
$encoding = null, $clear = true
) {
$this->_checkLocale();
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
$this->_checkPNO($pno, $encoding);
if ($gender === 'm') {
$gender = KlarnaFlags::MALE;
} else if ($gender === 'f') {
$gender = KlarnaFlags::FEMALE;
}
if ($gender !== null && strlen($gender) > 0) {
$this->_checkInt($gender, 'gender');
}
$this->_checkInt($flags, 'flags');
$this->_checkInt($pclass, 'pclass');
//Check so required information is set.
$this->_checkGoodslist();
//Calculate automatically the amount from goodsList.
if ($amount === -1) {
$amount = (int)round($this->summarizeGoodsList());
} else {
$this->_checkAmount($amount);
}
if ($amount < 0) {
throw new Klarna_InvalidPriceException($amount);
}
//No addresses used for phone transactions
if ($flags & KlarnaFlags::RSRV_PHONE_TRANSACTION) {
$billing = $shipping = '';
} else {
$billing = $this->assembleAddr($this->billing);
$shipping = $this->assembleAddr($this->shipping);
if (strlen($shipping['country']) > 0
&& ($shipping['country'] !== $this->_country)
) {
throw new Klarna_ShippingCountryException;
}
}
//Assume normal shipment unless otherwise specified.
if (!isset($this->shipInfo['delay_adjust'])) {
$this->setShipmentInfo('delay_adjust', KlarnaFlags::NORMAL_SHIPMENT);
}
//Make sure we get any session ID's or similar
$this->initCheckout($this, $this->_eid);
$digestSecret = self::digest(
"{$this->_eid}:{$pno}:{$amount}:{$this->_secret}"
);
$paramList = array(
$pno,
$gender,
$amount,
$this->reference,
$this->reference_code,
$this->orderid[0],
$this->orderid[1],
$shipping,
$billing,
$this->getClientIP(),
$flags,
$this->_currency,
$this->_country,
$this->_language,
$this->_eid,
$digestSecret,
$encoding, $pclass,
$this->goodsList,
$this->comment,
$this->shipInfo,
$this->travelInfo,
$this->incomeInfo,
$this->bankInfo,
$this->sid,
$this->extraInfo
);
self::printDebug('reserve_amount', $paramList);
$result = $this->xmlrpc_call('reserve_amount', $paramList);
if ($clear === true) {
//Make sure any stored values that need to be unique between
//purchases are cleared.
foreach ($this->coObjects as $co) {
$co->clear();
}
$this->clear();
}
self::printDebug('reserve_amount result', $result);
return $result;
}
/**
* Cancels a reservation.
*
* @param string $rno Reservation number.
*
* @link http://integration.klarna.com/en/api/advanced-integration/functions
* /cancelreservation
*
* @throws KlarnaException
* @return bool True, if the cancellation was successful.
*/
public function cancelReservation($rno)
{
$this->_checkRNO($rno);
$digestSecret = self::digest(
$this->colon($this->_eid, $rno, $this->_secret)
);
$paramList = array(
$rno,
$this->_eid,
$digestSecret
);
self::printDebug('cancel_reservation', $paramList);
$result = $this->xmlrpc_call('cancel_reservation', $paramList);
return ($result == 'ok');
}
/**
* Changes specified reservation to a new amount.
*
* Flags can be either of these:
* {@link KlarnaFlags::NEW_AMOUNT}
* {@link KlarnaFlags::ADD_AMOUNT}
*
* @param string $rno Reservation number.
* @param int $amount Amount including VAT.
* @param int $flags Options which affect the behaviour.
*
* @link http://integration.klarna.com/en/api/advanced-integration/functions
* /changereservation
*
* @throws KlarnaException
* @return bool True, if the change was successful.
*/
public function changeReservation(
$rno, $amount, $flags = KlarnaFlags::NEW_AMOUNT
) {
$this->_checkRNO($rno);
$this->_checkAmount($amount);
$this->_checkInt($flags, 'flags');
$digestSecret = self::digest(
$this->colon($this->_eid, $rno, $amount, $this->_secret)
);
$paramList = array(
$rno,
$amount,
$this->_eid,
$digestSecret,
$flags
);
self::printDebug('change_reservation', $paramList);
$result = $this->xmlrpc_call('change_reservation', $paramList);
return ($result == 'ok') ? true : false;
}
/**
* Update the reservation matching the given reservation number.
*
* @param string $rno Reservation number
* @param boolean $clear clear set data aftre updating. Defaulted to true.
*
* @throws KlarnaException if no RNO is given, or if an error is recieved
* from Klarna Online.
*
* @return true if the update was successful
*/
public function update($rno, $clear = true)
{
$rno = strval($rno);
// All info that is sent in is part of the digest secret, in this order:
// [
// proto_vsn, client_vsn, eid, rno, careof, street, zip, city,
// country, fname, lname, careof, street, zip, city, country,
// fname, lname, artno, qty, orderid1, orderid2
// ].
// The address part appears twice, that is one per address that
// changes. If no value is sent in for an optional field, there
// is no entry for this field in the digest secret. Shared secret
// is added at the end of the digest secret.
$digestArray = array(
str_replace('.', ':', $this->PROTO),
$this->VERSION,
$this->_eid,
$rno
);
$digestArray = array_merge(
$digestArray, $this->_addressDigestPart($this->shipping)
);
$digestArray = array_merge(
$digestArray, $this->_addressDigestPart($this->billing)
);
if (is_array($this->goodsList) && $this->goodsList !== array()) {
foreach ($this->goodsList as $goods) {
if (strlen($goods["goods"]["artno"]) > 0) {
$digestArray[] = $goods["goods"]["artno"];
} else {
$digestArray[] = $goods["goods"]["title"];
}
$digestArray[] = $goods["qty"];
}
}
foreach ($this->orderid as $orderid) {
$digestArray[] = $orderid;
}
$digestArray[] = $this->_secret;
$digestSecret = $this->digest(
call_user_func_array(
array('self', 'colon'), $digestArray
)
);
$shipping = array();
$billing = array();
if ($this->shipping !== null && $this->shipping instanceof KlarnaAddr) {
$shipping = $this->shipping->toArray();
}
if ($this->billing !== null && $this->billing instanceof KlarnaAddr) {
$billing = $this->billing->toArray();
}
$paramList = array(
$this->_eid,
$digestSecret,
$rno,
array(
'goods_list' => $this->goodsList,
'dlv_addr' => $shipping,
'bill_addr' => $billing,
'orderid1' => $this->orderid[0],
'orderid2' => $this->orderid[1]
)
);
self::printDebug('update array', $paramList);
$result = $this->xmlrpc_call('update', $paramList);
self::printDebug('update result', $result);
return ($result === 'ok');
}
/**
* Help function to sort the address for update digest.
*
* @param KlarnaAddr|null $address KlarnaAddr object or null
*
* @return array
*/
private function _addressDigestPart(KlarnaAddr $address = null)
{
if ($address === null) {
return array();
}
$keyOrder = array(
'careof', 'street', 'zip', 'city', 'country', 'fname', 'lname'
);
$holder = $address->toArray();
$digest = array();
foreach ($keyOrder as $key) {
if ($holder[$key] != "") {
$digest[] = $holder[$key];
}
}
return $digest;
}
/**
* Activate the reservation matching the given reservation number.
* Optional information should be set in ActivateInfo.
*
* To perform a partial activation, use the addArtNo function to specify
* which items in the reservation to include in the activation.
*
* @param string $rno Reservation number
* @param string $ocr optional OCR number to attach to the reservation when
* activating. Overrides OCR specified in activateInfo.
* @param string $flags optional flags to affect behavior. If specified it
* will overwrite any flag set in activateInfo.
* @param boolean $clear clear set data after activating. Defaulted to true.
*
* @throws KlarnaException when the RNO is not specified, or if an error
* is recieved from Klarna Online.
* @return A string array with risk status and reservation number.
*/
public function activate(
$rno, $ocr = null, $flags = null, $clear = true
) {
$this->_checkRNO($rno);
// Overwrite any OCR set on activateInfo if supplied here since this
// method call is more specific.
if ($ocr !== null) {
$this->setActivateInfo('ocr', $ocr);
}
// If flags is specified set the flag supplied here to activateInfo.
if ($flags !== null) {
$this->setActivateInfo('flags', $flags);
}
//Assume normal shipment unless otherwise specified.
if (!array_key_exists('delay_adjust', $this->shipInfo)) {
$this->setShipmentInfo('delay_adjust', KlarnaFlags::NORMAL_SHIPMENT);
}
// Append shipment info to activateInfo
$this->activateInfo['shipment_info'] = $this->shipInfo;
// Unlike other calls, if NO_FLAG is specified it should not be sent in
// at all.
if (array_key_exists('flags', $this->activateInfo)
&& $this->activateInfo['flags'] === KlarnaFlags::NO_FLAG
) {
unset($this->activateInfo['flags']);
}
// Build digest. Any field in activateInfo that is set is included in
// the digest.
$digestArray = array(
str_replace('.', ':', $this->PROTO),
$this->VERSION,
$this->_eid,
$rno
);
$optionalDigestKeys = array(
'bclass',
'cust_no',
'flags',
'ocr',
'orderid1',
'orderid2',
'reference',
'reference_code'
);
foreach ($optionalDigestKeys as $key) {
if (array_key_exists($key, $this->activateInfo)) {
$digestArray[] = $this->activateInfo[$key];
}
}
if (array_key_exists('delay_adjust', $this->activateInfo['shipment_info'])) {
$digestArray[] = $this->activateInfo['shipment_info']['delay_adjust'];
}
// If there are any artnos added with addArtNo, add them to the digest
// and to the activateInfo
if (is_array($this->artNos)) {
foreach ($this->artNos as $artNo) {
$digestArray[] = $artNo['artno'];
$digestArray[] = $artNo['qty'];
}
$this->setActivateInfo('artnos', $this->artNos);
}
$digestArray[] = $this->_secret;
$digestSecret = self::digest(
call_user_func_array(
array('self', 'colon'), $digestArray
)
);
// Create the parameter list.
$paramList = array(
$this->_eid,
$digestSecret,
$rno,
$this->activateInfo
);
self::printDebug('activate array', $paramList);
$result = $this->xmlrpc_call('activate', $paramList);
self::printDebug('activate result', $result);
// Clear the state if specified.
if ($clear) {
$this->clear();
}
return $result;
}
/**
* Activates a previously created reservation.
*
* This method returns an array with:
* Risk status ("no_risk", "ok")
* Invoice number
*
* Gender is only required for Germany and Netherlands.
*
* Use of the OCR parameter is optional.
* An OCR number can be retrieved by using:
* {@link Klarna::reserveOCR()} or {@link Klarna::reserveOCRemail()}.
*
* Flags can be set to:
* {@link KlarnaFlags::NO_FLAG}
* {@link KlarnaFlags::TEST_MODE}
* {@link KlarnaFlags::RSRV_SEND_BY_MAIL}
* {@link KlarnaFlags::RSRV_SEND_BY_EMAIL}
* {@link KlarnaFlags::RSRV_PRESERVE_RESERVATION}
* {@link KlarnaFlags::RSRV_SENSITIVE_ORDER}
*
* Some flags can be added to each other for multiple options.
*
* Note:
* Normal shipment type is assumed unless otherwise specified, you can
* do this by calling:
* {@link Klarna::setShipmentInfo() setShipmentInfo('delay_adjust', ...)}
* with either: {@link KlarnaFlags::NORMAL_SHIPMENT NORMAL_SHIPMENT} or
* {@link KlarnaFlags::EXPRESS_SHIPMENT EXPRESS_SHIPMENT}
*
* @param string $pno Personal number, SSN, date of birth, etc.
* @param string $rno Reservation number.
* @param int $gender {@link KlarnaFlags::FEMALE} or
* {@link KlarnaFlags::MALE}, null for unspecified.
* @param string $ocr A OCR number.
* @param int $flags Options which affect the behaviour.
* @param int $pclass {@link KlarnaPClass::getId() PClass ID}.
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
* @param bool $clear Whether customer info should be cleared after
* this call.
*
* @link http://integration.klarna.com/en/api/advanced-integration/functions
* /activatereservation
* @see Klarna::reserveAmount()
*
* @throws KlarnaException
* @return array An array with risk status and invoice number [string, string].
*/
public function activateReservation(
$pno, $rno, $gender, $ocr = "", $flags = KlarnaFlags::NO_FLAG,
$pclass = KlarnaPClass::INVOICE, $encoding = null, $clear = true
) {
$this->_checkLocale();
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
// Only check PNO if it is not explicitly null.
if ($pno !== null) {
$this->_checkPNO($pno, $encoding);
}
$this->_checkRNO($rno);
if ($gender !== null && strlen($gender) > 0) {
$this->_checkInt($gender, 'gender');
}
$this->_checkOCR($ocr);
$this->_checkRef($this->reference, $this->reference_code);
$this->_checkGoodslist();
//No addresses used for phone transactions
$billing = $shipping = '';
if ( !($flags & KlarnaFlags::RSRV_PHONE_TRANSACTION) ) {
$billing = $this->assembleAddr($this->billing);
$shipping = $this->assembleAddr($this->shipping);
if (strlen($shipping['country']) > 0
&& ($shipping['country'] !== $this->_country)
) {
throw new Klarna_ShippingCountryException;
}
}
//activate digest
$string = $this->_eid . ":" . $pno . ":";
foreach ($this->goodsList as $goods) {
$string .= $goods["goods"]["artno"] . ":" . $goods["qty"] . ":";
}
$digestSecret = self::digest($string . $this->_secret);
//end digest
//Assume normal shipment unless otherwise specified.
if (!isset($this->shipInfo['delay_adjust'])) {
$this->setShipmentInfo('delay_adjust', KlarnaFlags::NORMAL_SHIPMENT);
}
$paramList = array(
$rno,
$ocr,
$pno,
$gender,
$this->reference,
$this->reference_code,
$this->orderid[0],
$this->orderid[1],
$shipping,
$billing,
"0.0.0.0",
$flags,
$this->_currency,
$this->_country,
$this->_language,
$this->_eid,
$digestSecret,
$encoding,
$pclass,
$this->goodsList,
$this->comment,
$this->shipInfo,
$this->travelInfo,
$this->incomeInfo,
$this->bankInfo,
$this->extraInfo
);
self::printDebug('activate_reservation', $paramList);
$result = $this->xmlrpc_call('activate_reservation', $paramList);
if ($clear === true) {
$this->clear();
}
self::printDebug('activate_reservation result', $result);
return $result;
}
/**
* Splits a reservation due to for example outstanding articles.
*
* For flags usage see:
* {@link Klarna::reserveAmount()}
*
* @param string $rno Reservation number.
* @param int $amount The amount to be subtracted from the reservation.
* @param int $flags Options which affect the behaviour.
*
* @link http://integration.klarna.com/en/api/advanced-integration/functions
* /splitreservation
*
* @throws KlarnaException
* @return string A new reservation number.
*/
public function splitReservation(
$rno, $amount, $flags = KlarnaFlags::NO_FLAG
) {
//Check so required information is set.
$this->_checkRNO($rno);
$this->_checkAmount($amount);
if ($amount <= 0) {
throw new Klarna_InvalidPriceException($amount);
}
$digestSecret = self::digest(
$this->colon($this->_eid, $rno, $amount, $this->_secret)
);
$paramList = array(
$rno,
$amount,
$this->orderid[0],
$this->orderid[1],
$flags,
$this->_eid,
$digestSecret
);
self::printDebug('split_reservation array', $paramList);
$result = $this->xmlrpc_call('split_reservation', $paramList);
self::printDebug('split_reservation result', $result);
return $result;
}
/**
* Reserves a specified number of OCR numbers.
* For the specified country or the {@link Klarna::setCountry() set country}.
*
* @param int $no The number of OCR numbers to reserve.
* @param int $country {@link KlarnaCountry} constant.
*
* @link http://integration.klarna.com/en/api/advanced-integration/functions
* /reserveocrnums
*
* @throws KlarnaException
* @return array An array of OCR numbers.
*/
public function reserveOCR($no, $country = null)
{
$this->_checkNo($no);
if ($country === null) {
if (!$this->_country) {
throw new Klarna_MissingCountryException;
}
$country = $this->_country;
} else {
$this->_checkCountry($country);
}
$digestSecret = self::digest(
$this->colon($this->_eid, $no, $this->_secret)
);
$paramList = array(
$no,
$this->_eid,
$digestSecret,
$country
);
self::printDebug('reserve_ocr_nums array', $paramList);
return $this->xmlrpc_call('reserve_ocr_nums', $paramList);
}
/**
* Reserves the number of OCRs specified and sends them to the given email.
*
* @param int $no Number of OCR numbers to reserve.
* @param string $email address.
* @param int $country {@link KlarnaCountry} constant.
*
* @return bool True, if the OCRs were reserved and sent.
*/
public function reserveOCRemail($no, $email, $country = null)
{
$this->_checkNo($no);
$this->_checkPNO($email, KlarnaEncoding::EMAIL);
if ($country === null) {
if (!$this->_country) {
throw new Klarna_MissingCountryException;
}
$country = $this->_country;
} else {
$this->_checkCountry($country);
}
$digestSecret = self::digest(
$this->colon($this->_eid, $no, $this->_secret)
);
$paramList = array(
$no,
$email,
$this->_eid,
$digestSecret,
$country
);
self::printDebug('reserve_ocr_nums_email array', $paramList);
$result = $this->xmlrpc_call('reserve_ocr_nums_email', $paramList);
return ($result == 'ok');
}
/**
* Checks if the specified SSN/PNO has an part payment account with Klarna.
*
* @param string $pno Social security number, Personal number, ...
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
*
* @link http://integration.klarna.com/en/api/standard-integration/functions
* /hasaccount
*
* @throws KlarnaException
* @return bool True, if customer has an account.
*/
public function hasAccount($pno, $encoding = null)
{
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
$this->_checkPNO($pno, $encoding);
$digest = self::digest(
$this->colon($this->_eid, $pno, $this->_secret)
);
$paramList = array(
$this->_eid,
$pno,
$digest,
$encoding
);
self::printDebug('has_account', $paramList);
$result = $this->xmlrpc_call('has_account', $paramList);
return ($result === 'true');
}
/**
* Adds an article number and quantity to be used in
* {@link Klarna::activatePart()}, {@link Klarna::creditPart()}
* and {@link Klarna::invoicePartAmount()}.
*
* @param int $qty Quantity of specified article.
* @param string $artNo Article number.
*
* @link http://integration.klarna.com/en/api/invoice-handling-functions/
* functions/mkartno
*
* @throws KlarnaException
* @return void
*/
public function addArtNo($qty, $artNo)
{
$this->_checkQty($qty);
$this->_checkArtNo($artNo);
if (!is_array($this->artNos)) {
$this->artNos = array();
}
$this->artNos[] = array('artno' => $artNo, 'qty' => $qty);
}
/**
* Partially activates a passive invoice.
*
* Returned array contains index "url" and "invno".
* The value of "url" is a URL pointing to a temporary PDF-version of the
* activated invoice.
* The value of "invno" is either 0 if the entire invoice was activated or
* the number on the new passive invoice.
*
* Note:
* You need to call {@link Klarna::addArtNo()} first, to specify which
* articles and how many you want to partially activate.
* If you want to change the shipment type, you can specify it using:
* {@link Klarna::setShipmentInfo() setShipmentInfo('delay_adjust', ...)}
* with either: {@link KlarnaFlags::NORMAL_SHIPMENT NORMAL_SHIPMENT}
* or {@link KlarnaFlags::EXPRESS_SHIPMENT EXPRESS_SHIPMENT}
*
* @param string $invNo Invoice numbers.
* @param int $pclass PClass id used for this invoice.
* @param bool $clear Whether customer info should be cleared after
* this call.
*
* @see Klarna::addArtNo()
* @see Klarna::activateInvoice()
* @link http://integration.klarna.com/en/api/standard-integration/functions
* /activatepart
*
* @throws KlarnaException
* @return array An array with invoice URL and invoice number.
* ['url' => val, 'invno' => val]
*/
public function activatePart(
$invNo, $pclass = KlarnaPClass::INVOICE, $clear = true
) {
$this->_checkInvNo($invNo);
$this->_checkArtNos($this->artNos);
self::printDebug('activate_part artNos array', $this->artNos);
//function activate_part_digest
$string = $this->_eid . ":" . $invNo . ":";
foreach ($this->artNos as $artNo) {
$string .= $artNo["artno"] . ":". $artNo["qty"] . ":";
}
$digestSecret = self::digest($string . $this->_secret);
//end activate_part_digest
$paramList = array(
$this->_eid,
$invNo,
$this->artNos,
$digestSecret,
$pclass,
$this->shipInfo
);
self::printDebug('activate_part array', $paramList);
$result = $this->xmlrpc_call('activate_part', $paramList);
if ($clear === true) {
$this->clear();
}
self::printDebug('activate_part result', $result);
return $result;
}
/**
* Retrieves the total amount for an active invoice.
*
* @param string $invNo Invoice number.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /invoiceamount
*
* @throws KlarnaException
* @return float The total amount.
*/
public function invoiceAmount($invNo)
{
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret
);
self::printDebug('invoice_amount array', $paramList);
$result = $this->xmlrpc_call('invoice_amount', $paramList);
//Result is in cents, fix it.
return ($result / 100);
}
/**
* Changes the order number of a purchase that was set when the order was
* made online.
*
* @param string $invNo Invoice number.
* @param string $orderid Estores order number.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /updateorderno
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function updateOrderNo($invNo, $orderid)
{
$this->_checkInvNo($invNo);
$this->_checkEstoreOrderNo($orderid);
$digestSecret = self::digest(
$this->colon($invNo, $orderid, $this->_secret)
);
$paramList = array(
$this->_eid,
$digestSecret,
$invNo,
$orderid
);
self::printDebug('update_orderno array', $paramList);
$result = $this->xmlrpc_call('update_orderno', $paramList);
return $result;
}
/**
* Sends an activated invoice to the customer via e-mail.
* The email is sent in plain text format and contains a link to a
* PDF-invoice.
*
* Please note!
* Regular postal service is used if the customer has not entered his/her
* e-mail address when making the purchase (charges may apply).
*
* @param string $invNo Invoice number.
*
* @link http://integration.klarna.com/en/api/invoice-handling-functions
* /functions/emailinvoice
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function emailInvoice($invNo)
{
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret
);
self::printDebug('email_invoice array', $paramList);
return $this->xmlrpc_call('email_invoice', $paramList);
}
/**
* Requests a postal send-out of an activated invoice to a customer by
* Klarna (charges may apply).
*
* @param string $invNo Invoice number.
*
* @link http://integration.klarna.com/en/api/invoice-handling-functions
* /functions/sendinvoice
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function sendInvoice($invNo)
{
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret
);
self::printDebug('send_invoice array', $paramList);
return $this->xmlrpc_call('send_invoice', $paramList);
}
/**
* Gives discounts on invoices.
* If you are using standard integration and the purchase is not yet
* activated (you have not yet delivered the goods),
* just change the article list in our online interface Klarna Online.
*
* Flags can be:
* {@link KlarnaFlags::INC_VAT}
* {@link KlarnaFlags::NO_FLAG}, NOT RECOMMENDED!
*
* @param string $invNo Invoice number.
* @param int $amount The amount given as a discount.
* @param float $vat VAT in percent, e.g. 22.2 for 22.2%.
* @param int $flags If amount is
* {@link KlarnaFlags::INC_VAT including} or
* {@link KlarnaFlags::NO_FLAG excluding} VAT.
* @param string $description Optional custom text to present as discount
* in the invoice.
*
* @link http://integration.klarna.com/en/api/invoice-handling-functions
* /functions/returnamount
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function returnAmount(
$invNo, $amount, $vat, $flags = KlarnaFlags::INC_VAT, $description = ""
) {
$this->_checkInvNo($invNo);
$this->_checkAmount($amount);
$this->_checkVAT($vat);
$this->_checkInt($flags, 'flags');
if ($description == null) {
$description = "";
}
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$amount,
$vat,
$digestSecret,
$flags,
$description
);
self::printDebug('return_amount', $paramList);
return $this->xmlrpc_call('return_amount', $paramList);
}
/**
* Performs a complete refund on an invoice, part payment and mobile
* purchase.
*
* @param string $invNo Invoice number.
* @param string $credNo Credit number.
*
* @link http://integration.klarna.com/en/api/invoice-handling-functions
* /functions/creditinvoice
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function creditInvoice($invNo, $credNo = "")
{
$this->_checkInvNo($invNo);
$this->_checkCredNo($credNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$credNo,
$digestSecret
);
self::printDebug('credit_invoice', $paramList);
return $this->xmlrpc_call('credit_invoice', $paramList);
}
/**
* Performs a partial refund on an invoice, part payment or mobile purchase.
*
* Note:
* You need to call {@link Klarna::addArtNo()} first.
*
* @param string $invNo Invoice number.
* @param string $credNo Credit number.
*
* @see Klarna::addArtNo()
* @link http://integration.klarna.com/en/api/invoice-handling-functions
* /functions/creditpart
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function creditPart($invNo, $credNo = "")
{
$this->_checkInvNo($invNo);
$this->_checkCredNo($credNo);
if ($this->goodsList === null || empty($this->goodsList)) {
$this->_checkArtNos($this->artNos);
}
//function activate_part_digest
$string = $this->_eid . ":" . $invNo . ":";
if ($this->artNos !== null && !empty($this->artNos)) {
foreach ($this->artNos as $artNo) {
$string .= $artNo["artno"] . ":". $artNo["qty"] . ":";
}
}
$digestSecret = self::digest($string . $this->_secret);
//end activate_part_digest
$paramList = array(
$this->_eid,
$invNo,
$this->artNos,
$credNo,
$digestSecret
);
if ($this->goodsList !== null && !empty($this->goodsList)) {
$paramList[] = 0;
$paramList[] = $this->goodsList;
}
$this->artNos = array();
self::printDebug('credit_part', $paramList);
return $this->xmlrpc_call('credit_part', $paramList);
}
/**
* Changes the quantity of a specific item in a passive invoice.
*
* @param string $invNo Invoice number.
* @param string $artNo Article number.
* @param int $qty Quantity of specified article.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /updategoodsqty
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function updateGoodsQty($invNo, $artNo, $qty)
{
$this->_checkInvNo($invNo);
$this->_checkQty($qty);
$this->_checkArtNo($artNo);
$digestSecret = self::digest(
$this->colon($invNo, $artNo, $qty, $this->_secret)
);
$paramList = array(
$this->_eid,
$digestSecret,
$invNo,
$artNo,
$qty
);
self::printDebug('update_goods_qty', $paramList);
return $this->xmlrpc_call('update_goods_qty', $paramList);
}
/**
* Changes the amount of a fee (e.g. the invoice fee) in a passive invoice.
*
* Type can be:
* {@link KlarnaFlags::IS_SHIPMENT}
* {@link KlarnaFlags::IS_HANDLING}
*
* @param string $invNo Invoice number.
* @param int $type Charge type.
* @param int $newAmount The new amount for the charge.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /updatechargeamount
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function updateChargeAmount($invNo, $type, $newAmount)
{
$this->_checkInvNo($invNo);
$this->_checkInt($type, 'type');
$this->_checkAmount($newAmount);
if ($type === KlarnaFlags::IS_SHIPMENT) {
$type = 1;
} else if ($type === KlarnaFlags::IS_HANDLING) {
$type = 2;
}
$digestSecret = self::digest(
$this->colon($invNo, $type, $newAmount, $this->_secret)
);
$paramList = array(
$this->_eid,
$digestSecret,
$invNo,
$type,
$newAmount
);
self::printDebug('update_charge_amount', $paramList);
return $this->xmlrpc_call('update_charge_amount', $paramList);
}
/**
* The invoice_address function is used to retrieve the address of a
* purchase.
*
* @param string $invNo Invoice number.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /invoiceaddress
*
* @throws KlarnaException
* @return KlarnaAddr
*/
public function invoiceAddress($invNo)
{
$this->_checkInvNo($invNo);
$digestSecret = self::digest(
$this->colon($this->_eid, $invNo, $this->_secret)
);
$paramList = array(
$this->_eid,
$invNo,
$digestSecret
);
self::printDebug('invoice_address', $paramList);
$result = $this->xmlrpc_call('invoice_address', $paramList);
$addr = new KlarnaAddr();
if (strlen($result[0]) > 0) {
$addr->isCompany = false;
$addr->setFirstName($result[0]);
$addr->setLastName($result[1]);
} else {
$addr->isCompany = true;
$addr->setCompanyName($result[1]);
}
$addr->setStreet($result[2]);
$addr->setZipCode($result[3]);
$addr->setCity($result[4]);
$addr->setCountry($result[5]);
return $addr;
}
/**
* Retrieves the amount of a specific goods from a purchase.
*
* Note:
* You need to call {@link Klarna::addArtNo()} first.
*
* @param string $invNo Invoice number.
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /invoicepartamount
* @see Klarna::addArtNo()
*
* @throws KlarnaException
* @return float The amount of the goods.
*/
public function invoicePartAmount($invNo)
{
$this->_checkInvNo($invNo);
$this->_checkArtNos($this->artNos);
//function activate_part_digest
$string = $this->_eid . ":" . $invNo . ":";
foreach ($this->artNos as $artNo) {
$string .= $artNo["artno"] . ":". $artNo["qty"] . ":";
}
$digestSecret = self::digest($string . $this->_secret);
//end activate_part_digest
$paramList = array(
$this->_eid,
$invNo,
$this->artNos,
$digestSecret
);
$this->artNos = array();
self::printDebug('invoice_part_amount', $paramList);
$result = $this->xmlrpc_call('invoice_part_amount', $paramList);
return ($result / 100);
}
/**
* Returns the current order status for a specific reservation or invoice.
* Use this when {@link Klarna::addTransaction()} or
* {@link Klarna::reserveAmount()} returns a {@link KlarnaFlags::PENDING}
* status.
*
* Order status can be:
* {@link KlarnaFlags::ACCEPTED}
* {@link KlarnaFlags::PENDING}
* {@link KlarnaFlags::DENIED}
*
* @param string $id Reservation number or invoice number.
* @param int $type 0 if $id is an invoice or reservation, 1 for order id
*
* @link http://integration.klarna.com/en/api/other-functions/functions
* /checkorderstatus
*
* @throws KlarnaException
* @return string The order status.
*/
public function checkOrderStatus($id, $type = 0)
{
$this->_checkArgument($id, "id");
$this->_checkInt($type, 'type');
if ($type !== 0 && $type !== 1) {
throw new Klarna_InvalidTypeException(
'type', "0 or 1"
);
}
$digestSecret = self::digest(
$this->colon($this->_eid, $id, $this->_secret)
);
$paramList = array(
$this->_eid,
$digestSecret,
$id,
$type
);
self::printDebug('check_order_status', $paramList);
return $this->xmlrpc_call('check_order_status', $paramList);
}
/**
* Retrieves a list of all the customer numbers associated with the
* specified pno.
*
* @param string $pno Social security number, Personal number, ...
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
*
* @throws KlarnaException
* @return array An array containing all customer numbers associated
* with that pno.
*/
public function getCustomerNo($pno, $encoding = null)
{
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
$this->_checkPNO($pno, $encoding);
$digestSecret = self::digest(
$this->colon($this->_eid, $pno, $this->_secret)
);
$paramList = array(
$pno,
$this->_eid,
$digestSecret,
$encoding
);
self::printDebug('get_customer_no', $paramList);
return $this->xmlrpc_call('get_customer_no', $paramList);
}
/**
* Associates a pno with a customer number when you want to make future
* purchases without a pno.
*
* @param string $pno Social security number, Personal number, ...
* @param string $custNo The customer number.
* @param int $encoding {@link KlarnaEncoding PNO Encoding} constant.
*
* @throws KlarnaException
* @return bool True, if the customer number was associated with the pno.
*/
public function setCustomerNo($pno, $custNo, $encoding = null)
{
//Get the PNO/SSN encoding constant.
if ($encoding === null) {
$encoding = $this->getPNOEncoding();
}
$this->_checkPNO($pno, $encoding);
$this->_checkArgument($custNo, 'custNo');
$digestSecret = self::digest(
$this->colon($this->_eid, $pno, $custNo, $this->_secret)
);
$paramList = array(
$pno,
$custNo,
$this->_eid,
$digestSecret,
$encoding
);
self::printDebug('set_customer_no', $paramList);
$result = $this->xmlrpc_call('set_customer_no', $paramList);
return ($result == 'ok');
}
/**
* Removes a customer number from association with a pno.
*
* @param string $custNo The customer number.
*
* @throws KlarnaException
* @return bool True, if the customer number association was removed.
*/
public function removeCustomerNo($custNo)
{
$this->_checkArgument($custNo, 'custNo');
$digestSecret = self::digest(
$this->colon($this->_eid, $custNo, $this->_secret)
);
$paramList = array(
$custNo,
$this->_eid,
$digestSecret
);
self::printDebug('remove_customer_no', $paramList);
$result = $this->xmlrpc_call('remove_customer_no', $paramList);
return ($result == 'ok');
}
/**
* Sets notes/log information for the specified invoice number.
*
* @param string $invNo Invoice number.
* @param string $notes Note(s) to be associated with the invoice.
*
* @throws KlarnaException
* @return string Invoice number.
*/
public function updateNotes($invNo, $notes)
{
$this->_checkInvNo($invNo);
if (!is_string($notes)) {
$notes = strval($notes);
}
$digestSecret = self::digest(
$this->colon($invNo, $notes, $this->_secret)
);
$paramList = array(
$this->_eid,
$digestSecret,
$invNo,
$notes
);
self::printDebug('update_notes', $paramList);
return $this->xmlrpc_call('update_notes', $paramList);
}
/**
* Returns the configured PCStorage object.
*
* @throws Exception|KlarnaException
* @return PCStorage
*/
public function getPCStorage()
{
if (isset($this->pclasses)) {
return $this->pclasses;
}
include_once 'pclasses/storage.intf.php';
$className = $this->pcStorage.'storage';
$pclassStorage = dirname(__FILE__) . "/pclasses/{$className}.class.php";
include_once $pclassStorage;
$storage = new $className;
if (!($storage instanceof PCStorage)) {
throw new Klarna_PCStorageInvalidException(
$className, $pclassStorage
);
}
return $storage;
}
/**
* Fetch pclasses
*
* @param PCStorage $storage PClass Storage
* @param int $country KlarnaCountry constant
* @param int $language KlarnaLanguage constant
* @param int $currency KlarnaCurrency constant
*
* @return void
*/
private function _fetchPClasses($storage, $country, $language, $currency)
{
$digestSecret = self::digest(
$this->_eid . ":" . $currency . ":" . $this->_secret
);
$paramList = array(
$this->_eid,
$currency,
$digestSecret,
$country,
$language
);
self::printDebug('get_pclasses array', $paramList);
$result = $this->xmlrpc_call('get_pclasses', $paramList);
self::printDebug('get_pclasses result', $result);
foreach ($result as &$pclass) {
//numeric htmlentities
$pclass[1] = Klarna::num_htmlentities($pclass[1]);
//Below values are in "cents", fix them.
$pclass[3] /= 100; //divide start fee with 100
$pclass[4] /= 100; //divide invoice fee with 100
$pclass[5] /= 100; //divide interest rate with 100
$pclass[6] /= 100; //divide min amount with 100
if ($pclass[9] != '-') {
//unix timestamp instead of yyyy-mm-dd
$pclass[9] = strtotime($pclass[9]);
}
//Associate the PClass with this estore.
array_unshift($pclass, $this->_eid);
$storage->addPClass(new KlarnaPClass($pclass));
}
}
/**
* Fetches the PClasses from Klarna Online.
* Removes the cached/stored pclasses and updates.
* You are only allowed to call this once, or once per update of PClasses
* in KO.
*
* Note:
* If language and/or currency is null, then they will be set to mirror
* the specified country.
* Short codes like DE, SV or EUR can also be used instead of the constants.
*
* @param string|int $country {@link KlarnaCountry Country} constant,
* or two letter code.
* @param mixed $language {@link KlarnaLanguage Language} constant,
* or two letter code.
* @param mixed $currency {@link KlarnaCurrency Currency} constant,
* or three letter code.
*
* @throws KlarnaException
* @return void
*/
public function fetchPClasses(
$country = null, $language = null, $currency = null
) {
extract(
$this->getLocale($country, $language, $currency),
EXTR_OVERWRITE
);
$this->_checkConfig();
$pclasses = $this->getPCStorage();
try {
//Attempt to load previously stored pclasses, so they aren't
// accidentially removed.
$pclasses->load($this->pcURI);
}
catch(Exception $e) {
self::printDebug('load pclasses', $e->getMessage());
}
$this->_fetchPClasses($pclasses, $country, $language, $currency);
$pclasses->save($this->pcURI);
$this->pclasses = $pclasses;
}
/**
* Removes the stored PClasses, if you need to update them.
*
* @throws KlarnaException
* @return void
*/
public function clearPClasses()
{
$this->_checkConfig();
$pclasses = $this->getPCStorage();
$pclasses->clear($this->pcURI);
}
/**
* Retrieves the specified PClasses.
*
* Type can be:
* {@link KlarnaPClass::CAMPAIGN}
* {@link KlarnaPClass::ACCOUNT}
* {@link KlarnaPClass::SPECIAL}
* {@link KlarnaPClass::FIXED}
* {@link KlarnaPClass::DELAY}
* {@link KlarnaPClass::MOBILE}
*
* @param int $type PClass type identifier.
*
* @throws KlarnaException
* @return array An array of PClasses. [KlarnaPClass]
*/
public function getPClasses($type = null)
{
$this->_checkConfig();
if (!$this->pclasses) {
$this->pclasses = $this->getPCStorage();
$this->pclasses->load($this->pcURI);
}
$tmp = $this->pclasses->getPClasses(
$this->_eid, $this->_country, $type
);
$this->sortPClasses($tmp[$this->_eid]);
return $tmp[$this->_eid];
}
/**
* Retrieve a flattened array of all pclasses stored in the configured
* pclass storage.
*
* @return array
*/
public function getAllPClasses()
{
if (!$this->pclasses) {
$this->pclasses = $this->getPCStorage();
$this->pclasses->load($this->pcURI);
}
return $this->pclasses->getAllPClasses();
}
/**
* Returns the specified PClass.
*
* @param int $id The PClass ID.
*
* @return KlarnaPClass
*/
public function getPClass($id)
{
if (!is_numeric($id)) {
throw new Klarna_InvalidTypeException('id', 'integer');
}
$this->_checkConfig();
if (!$this->pclasses || !($this->pclasses instanceof PCStorage)) {
$this->pclasses = $this->getPCStorage();
$this->pclasses->load($this->pcURI);
}
return $this->pclasses->getPClass(
intval($id), $this->_eid, $this->_country
);
}
/**
* Sorts the specified array of KlarnaPClasses.
*
* @param array &$array An array of {@link KlarnaPClass PClasses}.
*
* @return void
*/
public function sortPClasses(&$array)
{
if (!is_array($array)) {
//Input is not an array!
$array = array();
return;
}
//Sort pclasses array after natural sort (natcmp)
if (!function_exists('pcCmp')) {
/**
* Comparison function
*
* @param KlarnaPClass $a object 1
* @param KlarnaPClass $b object 2
*
* @return int
*/
function pcCmp($a, $b)
{
if ($a->getDescription() == null
&& $b->getDescription() == null
) {
return 0;
} else if ($a->getDescription() == null) {
return 1;
} else if ($b->getDescription() == null) {
return -1;
} else if ($b->getType() === 2 && $a->getType() !== 2) {
return 1;
} else if ($b->getType() !== 2 && $a->getType() === 2) {
return -1;
}
return strnatcmp($a->getDescription(), $b->getDescription())*-1;
}
}
usort($array, "pcCmp");
}
/**
* Returns the cheapest, per month, PClass related to the specified sum.
*
* Note: This choose the cheapest PClass for the current country.
* {@link Klarna::setCountry()}
*
* Flags can be:
* {@link KlarnaFlags::CHECKOUT_PAGE}
* {@link KlarnaFlags::PRODUCT_PAGE}
*
* @param float $sum The product cost, or total sum of the cart.
* @param int $flags Which type of page the info will be displayed on.
*
* @throws KlarnaException
* @return KlarnaPClass or false if none was found.
*/
public function getCheapestPClass($sum, $flags)
{
if (!is_numeric($sum)) {
throw new Klarna_InvalidPriceException($sum);
}
if (!is_numeric($flags)
|| !in_array(
$flags, array(
KlarnaFlags::CHECKOUT_PAGE, KlarnaFlags::PRODUCT_PAGE)
)
) {
throw new Klarna_InvalidTypeException(
'flags',
KlarnaFlags::CHECKOUT_PAGE . ' or ' . KlarnaFlags::PRODUCT_PAGE
);
}
$lowest_pp = $lowest = false;
foreach ($this->getPClasses() as $pclass) {
$lowest_payment = KlarnaCalc::get_lowest_payment_for_account(
$pclass->getCountry()
);
if ($pclass->getType() < 2 && $sum >= $pclass->getMinAmount()) {
$minpay = KlarnaCalc::calc_monthly_cost(
$sum, $pclass, $flags
);
if ($minpay < $lowest_pp || $lowest_pp === false) {
if ($pclass->getType() == KlarnaPClass::ACCOUNT
|| $minpay >= $lowest_payment
) {
$lowest_pp = $minpay;
$lowest = $pclass;
}
}
}
}
return $lowest;
}
/**
* Initializes the checkoutHTML objects.
*
* @see Klarna::checkoutHTML()
* @return void
*/
protected function initCheckout()
{
$dir = dirname(__FILE__);
//Require the CheckoutHTML interface/abstract class
include_once $dir.'/checkout/checkouthtml.intf.php';
//Iterate over all .class.php files in checkout/
foreach (glob($dir.'/checkout/*.class.php') as $checkout) {
if (!self::$debug) {
ob_start();
}
include_once $checkout;
$className = basename($checkout, '.class.php');
$cObj = new $className;
if ($cObj instanceof CheckoutHTML) {
$cObj->init($this, $this->_eid);
$this->coObjects[$className] = $cObj;
}
if (!self::$debug) {
ob_end_clean();
}
}
}
/**
* Returns the checkout page HTML from the checkout classes.
*
* Note:
* This method uses output buffering to silence unwanted echoes.
*
* @see CheckoutHTML
*
* @return string A HTML string.
*/
public function checkoutHTML()
{
if (empty($this->coObjects)) {
$this->initCheckout();
}
$dir = dirname(__FILE__);
//Require the CheckoutHTML interface/abstract class
include_once $dir.'/checkout/checkouthtml.intf.php';
//Iterate over all .class.php files in
$html = "\n";
foreach ($this->coObjects as $cObj) {
if (!self::$debug) {
ob_start();
}
if ($cObj instanceof CheckoutHTML) {
$html .= $cObj->toHTML() . "\n";
}
if (!self::$debug) {
ob_end_clean();
}
}
return $html;
}
/**
* Creates a XMLRPC call with specified XMLRPC method and parameters from array.
*
* @param string $method XMLRPC method.
* @param array $array XMLRPC parameters.
*
* @throws KlarnaException
* @return mixed
*/
protected function xmlrpc_call($method, $array)
{
$this->_checkConfig();
if (!isset($method) || !is_string($method)) {
throw new Klarna_InvalidTypeException('method', 'string');
}
if ($array === null || count($array) === 0) {
throw new KlarnaException("Parameterlist is empty or null!", 50067);
}
if (self::$disableXMLRPC) {
return true;
}
try {
/*
* Disable verifypeer for CURL, so below error is avoided.
* CURL error: SSL certificate problem, verify that the CA
* cert is OK.
* Details: error:14090086:SSL
* routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (#8)
*/
$this->xmlrpc->verifypeer = false;
$timestart = microtime(true);
//Create the XMLRPC message.
$msg = new xmlrpcmsg($method);
$params = array_merge(
array(
$this->PROTO, $this->VERSION
), $array
);
$msg = new xmlrpcmsg($method);
foreach ($params as $p) {
if (!$msg->addParam(
php_xmlrpc_encode($p, array('extension_api'))
)
) {
throw new KlarnaException(
"Failed to add parameters to XMLRPC message.",
50068
);
}
}
//Send the message.
$selectDateTime = microtime(true);
if (self::$xmlrpcDebug) {
$this->xmlrpc->setDebug(2);
}
$xmlrpcresp = $this->xmlrpc->send($msg);
//Calculate time and selectTime.
$timeend = microtime(true);
$time = (int) (($selectDateTime - $timestart) * 1000);
$selectTime = (int) (($timeend - $timestart) * 1000);
$status = $xmlrpcresp->faultCode();
//Send report to candice.
if (self::$_candice === true) {
$this->sendStat($method, $time, $selectTime, $status);
}
if ($status !== 0) {
throw new KlarnaException($xmlrpcresp->faultString(), $status);
}
return php_xmlrpc_decode($xmlrpcresp->value());
}
catch(KlarnaException $e) {
//Otherwise it is caught below, and rethrown.
throw $e;
}
catch(Exception $e) {
throw new KlarnaException($e->getMessage(), $e->getCode());
}
}
/**
* Removes all relevant order/customer data from the internal structure.
*
* @return void
*/
public function clear()
{
$this->goodsList = null;
$this->comment = "";
$this->billing = null;
$this->shipping = null;
$this->shipInfo = array();
$this->extraInfo = array();
$this->bankInfo = array();
$this->incomeInfo = array();
$this->activateInfo = array();
$this->reference = "";
$this->reference_code = "";
$this->orderid[0] = "";
$this->orderid[1] = "";
$this->artNos = array();
$this->coObjects = array();
}
/**
* Sends a report to Candice.
*
* @param string $method XMLRPC method.
* @param int $time Elapsed time of entire XMLRPC call.
* @param int $selectTime Time to create the XMLRPC parameters.
* @param int $status XMLRPC error code.
*
* @return void
*/
protected function sendStat($method, $time, $selectTime, $status)
{
$fp = @fsockopen('udp://'.self::$_c_addr, 80, $errno, $errstr, 1500);
if ($fp) {
$uri = "{$this->_url['scheme']}://{$this->_url['host']}" .
":{$this->_url['port']}";
$data = $this->pipe(
$this->_eid,
$method,
$time,
$selectTime,
$status,
$uri
);
$digest = self::digest($this->pipe($data, $this->_secret));
self::printDebug("candice report", $data);
@fwrite($fp, $this->pipe($data, $digest));
@fclose($fp);
}
}
/**
* Implodes parameters with delimiter ':'.
* Null and "" values are ignored by the colon function to
* ensure there is not several colons in succession.
*
* @return string Colon separated string.
*/
public static function colon(/* variable parameters */)
{
return implode(
':',
array_filter(
func_get_args(),
array('self', 'filterDigest')
)
);
}
/**
* Implodes parameters with delimiter '|'.
*
* @return string Pipe separated string.
*/
public static function pipe(/* variable parameters */)
{
$args = func_get_args();
return implode('|', $args);
}
/**
* Check if the value has a string length larger than 0
*
* @param mixed $value The value to check.
*
* @return boolean True if string length is larger than 0
*/
public static function filterDigest($value)
{
return strlen(strval($value)) > 0;
}
/**
* Creates a digest hash from the inputted string,
* and the specified or the preferred hash algorithm.
*
* @param string $data Data to be hashed.
* @param string $hash hash algoritm to use
*
* @throws KlarnaException
* @return string Base64 encoded hash.
*/
public static function digest($data, $hash = null)
{
if ($hash===null) {
$preferred = array(
'sha512',
'sha384',
'sha256',
'sha224',
'md5'
);
$hashes = array_intersect($preferred, hash_algos());
if (count($hashes) == 0) {
throw new KlarnaException(
"No available hash algorithm supported!"
);
}
$hash = array_shift($hashes);
}
self::printDebug('digest() using hash', $hash);
return base64_encode(pack("H*", hash($hash, $data)));
}
/**
* Converts special characters to numeric htmlentities.
*
* Note:
* If supplied string is encoded with UTF-8, o umlaut ("ö") will become two
* HTML entities instead of one.
*
* @param string $str String to be converted.
*
* @return string String converted to numeric HTML entities.
*/
public static function num_htmlentities($str)
{
if (!self::$htmlentities) {
self::$htmlentities = array();
$table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES);
foreach ($table as $char => $entity) {
self::$htmlentities[$entity] = '' . ord($char) . ';';
}
}
return str_replace(
array_keys(
self::$htmlentities
), self::$htmlentities, htmlentities($str)
);
}
/**
* Prints debug information if debug is set to true.
* $msg is used as header/footer in the output.
*
* if FirePHP is available it will be used instead of
* dumping the debug info into the document.
*
* It uses print_r and encapsulates it in HTML/XML comments.
* ()
*
* @param string $msg Debug identifier, e.g. "my array".
* @param mixed $mixed Object, type, etc, to be debugged.
*
* @return void
*/
public static function printDebug($msg, $mixed)
{
if (self::$debug) {
if (class_exists('FB', false)) {
FB::send($mixed, $msg);
} else {
echo "\n\n";
}
}
}
/**
* Checks/fixes so the invNo input is valid.
*
* @param string &$invNo Invoice number.
*
* @throws KlarnaException
* @return void
*/
private function _checkInvNo(&$invNo)
{
if (!isset($invNo)) {
throw new Klarna_ArgumentNotSetException("Invoice number");
}
if (!is_string($invNo)) {
$invNo = strval($invNo);
}
if (strlen($invNo) == 0) {
throw new Klarna_ArgumentNotSetException("Invoice number");
}
}
/**
* Checks/fixes so the quantity input is valid.
*
* @param int &$qty Quantity.
*
* @throws KlarnaException
* @return void
*/
private function _checkQty(&$qty)
{
if (!isset($qty)) {
throw new Klarna_ArgumentNotSetException("Quantity");
}
if (is_numeric($qty) && !is_int($qty)) {
$qty = intval($qty);
}
if (!is_int($qty)) {
throw new Klarna_InvalidTypeException("Quantity", "integer");
}
}
/**
* Checks/fixes so the artTitle input is valid.
*
* @param string &$artTitle Article title.
*
* @throws KlarnaException
* @return void
*/
private function _checkArtTitle(&$artTitle)
{
if (!is_string($artTitle)) {
$artTitle = strval($artTitle);
}
if (!isset($artTitle) || strlen($artTitle) == 0) {
throw new Klarna_ArgumentNotSetException("artTitle", 50059);
}
}
/**
* Checks/fixes so the artNo input is valid.
*
* @param int|string &$artNo Article number.
*
* @throws KlarnaException
* @return void
*/
private function _checkArtNo(&$artNo)
{
if (is_numeric($artNo) && !is_string($artNo)) {
//Convert artNo to string if integer.
$artNo = strval($artNo);
}
if (!isset($artNo) || strlen($artNo) == 0 || (!is_string($artNo))) {
throw new Klarna_ArgumentNotSetException("artNo");
}
}
/**
* Checks/fixes so the credNo input is valid.
*
* @param string &$credNo Credit number.
*
* @throws KlarnaException
* @return void
*/
private function _checkCredNo(&$credNo)
{
if (!isset($credNo)) {
throw new Klarna_ArgumentNotSetException("Credit number");
}
if ($credNo === false || $credNo === null) {
$credNo = "";
}
if (!is_string($credNo)) {
$credNo = strval($credNo);
if (!is_string($credNo)) {
throw new Klarna_InvalidTypeException("Credit number", "string");
}
}
}
/**
* Checks so that artNos is an array and is not empty.
*
* @param array &$artNos Array from {@link Klarna::addArtNo()}.
*
* @throws KlarnaException
* @return void
*/
private function _checkArtNos(&$artNos)
{
if (!is_array($artNos)) {
throw new Klarna_InvalidTypeException("artNos", "array");
}
if (empty($artNos)) {
throw new KlarnaException('ArtNo array is empty!', 50064);
}
}
/**
* Checks/fixes so the integer input is valid.
*
* @param int &$int {@link KlarnaFlags flags} constant.
* @param string $field Name of the field.
*
* @throws KlarnaException
* @return void
*/
private function _checkInt(&$int, $field)
{
if (!isset($int)) {
throw new Klarna_ArgumentNotSetException($field);
}
if (is_numeric($int) && !is_int($int)) {
$int = intval($int);
}
if (!is_numeric($int) || !is_int($int)) {
throw new Klarna_InvalidTypeException($field, "integer");
}
}
/**
* Checks/fixes so the VAT input is valid.
*
* @param float &$vat VAT.
*
* @throws KlarnaException
* @return void
*/
private function _checkVAT(&$vat)
{
if (!isset($vat)) {
throw new Klarna_ArgumentNotSetException("VAT");
}
if (is_numeric($vat) && (!is_int($vat) || !is_float($vat))) {
$vat = floatval($vat);
}
if (!is_numeric($vat) || (!is_int($vat) && !is_float($vat))) {
throw new Klarna_InvalidTypeException("VAT", "integer or float");
}
}
/**
* Checks/fixes so the amount input is valid.
*
* @param int &$amount Amount.
*
* @throws KlarnaException
* @return void
*/
private function _checkAmount(&$amount)
{
if (!isset($amount)) {
throw new Klarna_ArgumentNotSetException("Amount");
}
if (is_numeric($amount)) {
$this->_fixValue($amount);
}
if (is_numeric($amount) && !is_int($amount)) {
$amount = intval($amount);
}
if (!is_numeric($amount) || !is_int($amount)) {
throw new Klarna_InvalidTypeException("amount", "integer");
}
}
/**
* Checks/fixes so the price input is valid.
*
* @param int &$price Price.
*
* @throws KlarnaException
* @return void
*/
private function _checkPrice(&$price)
{
if (!isset($price)) {
throw new Klarna_ArgumentNotSetException("Price");
}
if (is_numeric($price)) {
$this->_fixValue($price);
}
if (is_numeric($price) && !is_int($price)) {
$price = intval($price);
}
if (!is_numeric($price) || !is_int($price)) {
throw new Klarna_InvalidTypeException("Price", "integer");
}
}
/**
* Multiplies value with 100 and rounds it.
* This fixes value/price/amount inputs so that KO can handle them.
*
* @param float &$value value
*
* @return void
*/
private function _fixValue(&$value)
{
$value = round($value * 100);
}
/**
* Checks/fixes so the discount input is valid.
*
* @param float &$discount Discount amount.
*
* @throws KlarnaException
* @return void
*/
private function _checkDiscount(&$discount)
{
if (!isset($discount)) {
throw new Klarna_ArgumentNotSetException("Discount");
}
if (is_numeric($discount)
&& (!is_int($discount) || !is_float($discount))
) {
$discount = floatval($discount);
}
if (!is_numeric($discount)
|| (!is_int($discount) && !is_float($discount))
) {
throw new Klarna_InvalidTypeException("Discount", "integer or float");
}
}
/**
* Checks/fixes so that the estoreOrderNo input is valid.
*
* @param string &$estoreOrderNo Estores order number.
*
* @throws KlarnaException
* @return void
*/
private function _checkEstoreOrderNo(&$estoreOrderNo)
{
if (!isset($estoreOrderNo)) {
throw new Klarna_ArgumentNotSetException("Order number");
}
if (!is_string($estoreOrderNo)) {
$estoreOrderNo = strval($estoreOrderNo);
if (!is_string($estoreOrderNo)) {
throw new Klarna_InvalidTypeException("Order number", "string");
}
}
}
/**
* Checks/fixes to the PNO/SSN input is valid.
*
* @param string &$pno Personal number, social security number, ...
* @param int $enc {@link KlarnaEncoding PNO Encoding} constant.
*
* @throws KlarnaException
* @return void
*/
private function _checkPNO(&$pno, $enc)
{
if (!$pno) {
throw new Klarna_ArgumentNotSetException("PNO/SSN");
}
if (!KlarnaEncoding::checkPNO($pno)) {
throw new Klarna_InvalidPNOException;
}
}
/**
* Checks/fixes to the country input is valid.
*
* @param int &$country {@link KlarnaCountry Country} constant.
*
* @throws KlarnaException
* @return void
*/
private function _checkCountry(&$country)
{
if (!isset($country)) {
throw new Klarna_ArgumentNotSetException("Country");
}
if (is_numeric($country) && !is_int($country)) {
$country = intval($country);
}
if (!is_numeric($country) || !is_int($country)) {
throw new Klarna_InvalidTypeException("Country", "integer");
}
}
/**
* Checks/fixes to the language input is valid.
*
* @param int &$language {@link KlarnaLanguage Language} constant.
*
* @throws KlarnaException
* @return void
*/
private function _checkLanguage(&$language)
{
if (!isset($language)) {
throw new Klarna_ArgumentNotSetException("Language");
}
if (is_numeric($language) && !is_int($language)) {
$language = intval($language);
}
if (!is_numeric($language) || !is_int($language)) {
throw new Klarna_InvalidTypeException("Language", "integer");
}
}
/**
* Checks/fixes to the currency input is valid.
*
* @param int &$currency {@link KlarnaCurrency Currency} constant.
*
* @throws KlarnaException
* @return void
*/
private function _checkCurrency(&$currency)
{
if (!isset($currency)) {
throw new Klarna_ArgumentNotSetException("Currency");
}
if (is_numeric($currency) && !is_int($currency)) {
$currency = intval($currency);
}
if (!is_numeric($currency) || !is_int($currency)) {
throw new Klarna_InvalidTypeException("Currency", "integer");
}
}
/**
* Checks/fixes so no/number is a valid input.
*
* @param int &$no Number.
*
* @throws KlarnaException
* @return void
*/
private function _checkNo(&$no)
{
if (!isset($no)) {
throw new Klarna_ArgumentNotSetException("no");
}
if (is_numeric($no) && !is_int($no)) {
$no = intval($no);
}
if (!is_numeric($no) || !is_int($no) || $no <= 0) {
throw new Klarna_InvalidTypeException('no', 'integer > 0');
}
}
/**
* Checks/fixes so reservation number is a valid input.
*
* @param string &$rno Reservation number.
*
* @throws KlarnaException
* @return void
*/
private function _checkRNO(&$rno)
{
if (!is_string($rno)) {
$rno = strval($rno);
}
if (strlen($rno) == 0) {
throw new Klarna_ArgumentNotSetException("RNO");
}
}
/**
* Checks/fixes so that reference/refCode are valid.
*
* @param string &$reference Reference string.
* @param string &$refCode Reference code.
*
* @throws KlarnaException
* @return void
*/
private function _checkRef(&$reference, &$refCode)
{
if (!is_string($reference)) {
$reference = strval($reference);
if (!is_string($reference)) {
throw new Klarna_InvalidTypeException("Reference", "string");
}
}
if (!is_string($refCode)) {
$refCode = strval($refCode);
if (!is_string($refCode)) {
throw new Klarna_InvalidTypeException("Reference code", "string");
}
}
}
/**
* Checks/fixes so that the OCR input is valid.
*
* @param string &$ocr OCR number.
*
* @throws KlarnaException
* @return void
*/
private function _checkOCR(&$ocr)
{
if (!is_string($ocr)) {
$ocr = strval($ocr);
if (!is_string($ocr)) {
throw new Klarna_InvalidTypeException("OCR", "string");
}
}
}
/**
* Check so required argument is supplied.
*
* @param string $argument argument to check
* @param string $name name of argument
*
* @throws Klarna_ArgumentNotSetException
* @return void
*/
private function _checkArgument($argument, $name)
{
if (!is_string($argument)) {
$argument = strval($argument);
}
if (strlen($argument) == 0) {
throw new Klarna_ArgumentNotSetException($name);
}
}
/**
* Check so Locale settings (country, currency, language) are set.
*
* @throws KlarnaException
* @return void
*/
private function _checkLocale()
{
if (!is_int($this->_country)
|| !is_int($this->_language)
|| !is_int($this->_currency)
) {
throw new Klarna_InvalidLocaleException;
}
}
/**
* Checks wether a goodslist is set.
*
* @throws Klarna_MissingGoodslistException
* @return void
*/
private function _checkGoodslist()
{
if (!is_array($this->goodsList) || empty($this->goodsList)) {
throw new Klarna_MissingGoodslistException;
}
}
/**
* Set the pcStorage method used for this instance
*
* @param PCStorage $pcStorage PCStorage implementation
*
* @return void
*/
public function setPCStorage($pcStorage)
{
if (!($pcStorage instanceof PCStorage)) {
throw new Klarna_InvalidTypeException('pcStorage', 'PCStorage');
}
$this->pcStorage = $pcStorage->getName();
$this->pclasses = $pcStorage;
}
/**
* Ensure the configuration is of the correct type.
*
* @param array|ArrayAccess|null $config an optional config to validate
*
* @return void
*/
private function _checkConfig($config = null)
{
if ($config === null) {
$config = $this->config;
}
if (!($config instanceof ArrayAccess)
&& !is_array($config)
) {
throw new Klarna_IncompleteConfigurationException;
}
}
} //End Klarna
/**
* Include the {@link KlarnaConfig} class.
*/
require_once 'klarnaconfig.php';
/**
* Include the {@link KlarnaPClass} class.
*/
require_once 'klarnapclass.php';
/**
* Include the {@link KlarnaCalc} class.
*/
require_once 'klarnacalc.php';
/**
* Include the {@link KlarnaAddr} class.
*/
require_once 'klarnaaddr.php';
/**
* Include the Exception classes.
*/
require_once 'Exceptions.php';
/**
* Include the KlarnaEncoding class.
*/
require_once 'Encoding.php';
/**
* Include the KlarnaFlags class.
*/
require_once 'Flags.php';
/**
* Include KlarnaCountry, KlarnaCurrency, KlarnaLanguage classes
*/
require_once 'Country.php';
require_once 'Currency.php';
require_once 'Language.php';