Initial import: Carteasy Shop (Dev-Stand)

This commit is contained in:
Thomas Bartelt
2026-04-20 01:03:43 +02:00
commit d504f8a05d
3845 changed files with 761050 additions and 0 deletions
+185
View File
@@ -0,0 +1,185 @@
=====================
Klarna PHP API
=====================
v2.3.0
---------------
Date: 2012-09-19
Rickard D. <support@klarna.com>
Klarna.php (activateReservation) :
Change to allow NULL to be sent in as PNO when activating a
reservation. Any other value than null will still trigger a
verification that a string longer than 0 characters is sent
as PNO.
Klarna.php (activate) : new function
New function to activate a reservation using minimal information.
Optional information for the activate call should be set using
setActivateInformation.
To partially activate a reservation, use Klarna::addArtNo() function
(replaces splitReservation).
Klarna.php (update) : new function
New function to update a reservation using minimal information.
Use setAddress to update address, addArticle to update an article in
the goodslist and setEstoreInfo to update order id:s.
Klarna.php (checkCountryCurrency) : removed function
As this function does not scale and does not belong in a library it has
been removed.
Country.php () :
Added all available country constants.
Language.php () :
Added all available language constants.
Klarna.php (getLanguageForCountry) : deprecated
(getCurrencyForCountry) : deprecated
Country.php (checkLanguage) : deprecated
(checkCurrency) : deprecated
(getLanguage) : deprecated
(getCurrency) : deprecated
Deprecated functions that will not scale and will not be compatible for
any potential future markets.
Klarna.php (init, setCountry) :
Removed the automatic setting of currency and language when setting
the country. This functionality does not scale and was not consistent
depending on how you set the country.
Majid G. <support@klarna.com>
Klarna.php (addTransaction) :
Removing the link comment for PRE_PAY flag
Flags.php (KlarnaFlags) :
Adding deprecated comment for Flag 8 (PRE_PAY)
v2.2.1
----------------
Date: 2012-05-18
David K. <support@klarna.com>
Klarna.php (summarizeGoodsList)
New method that can be used to get a aggregated price for the entire
goodslist
Klarna.php (reserveAmount)
Replace the simple goodslist summary that did not take taxes and
discounts into consideration with a call to summarizeGoodsList
v2.2.0
----------------
Date: 2012-05-14
Rickard D. <support@klarna.com>
Klarna.php (assembleAddress) :
Only validate that the proper object type is sent in to Klarna, no longer
performs any validation of the content of the fields.
klarnaaddr.php () :
Removed validation of field contets. Now possible to set all fields to
empty strings if you wan.
Klarna.php (addTransaction, reserveAmount, activateReservation) :
If $gender is sent in as an empty string, treat it as null.
klarnacalc.php (calc_apr) :
Removed the ability to send in a FIXED or SPECIAL pclass to
KlarnaCalc->calc_apr. If this function is called with a FIXED or SPECIAL
pclass it will now throw an exception instead of causing a fatal error.
Klarna.php (getAllPClasses) : added
storage.intf.php (getAllPClasses) : added
Added possibility to get all stored pclasses, regardless of eid or type.
Klarna.php (setPCStorage) :
Added possibility to set a PCStorage on the Klarna object.
Klarna.php (getPCStorage) : made public (was protected)
Added possibility to get the configured PCStorage object from the Klarna
object.
Country.php (getLanguageForCountry, getCurrencyForCountry) : added
Added possibility to get the language or currency for a specific country.
All Files () :
Updated code to follow the PEAR standard.
Refactored several classes into their own files.
All refactored classes were previosly declared inside the Klarna.php
file. The new files are now instead included in the Klarna.php file,
so no functionality has changed in that regard.
KlarnaCountry => Country.php
KlarnaCurrency => Currency.php
KlarnaEncoding => Encoding.php
KlarnaException => Exceptions.php
KlarnaFlags => Flags.php
KlarnaLanguage => Language.php
Made almost all exceptions thrown more specific and meaningful than just
KlarnaException, although they still extend KlarnaException so old
try-catch blocks will still work.
v2.1.3
----------------
Date: 2011-09-26
* Fixed a minor conversion issue.
v2.1.2
----------------
Date: 2011-09-12
* Improved the MySQL and SQL storage modules
Added so you can pass an associative array to pcURI with the database info
Added support for dashes in the normal regexp handling
Fixed a rounding bug which requires a DROP TABLE and re-update of all PClasses
* Fixed a minor issue regarding the debug and xmlrpcDebug settings
* Added support for the ISO 3166-1 alpha-3 country codes
v2.1.1
----------------
Date: 2011-09-06
* Corrected a few issues in the phpDoc comments
* Improved fetchPClasses, it is now possible to specify only country (as code or constant)
* Changed the MySQL PClass storage's clear functionality to use DELETE FROM instead of DROP TABLE,
this is to prevent possible permission issues in the database
* Various improvements and bug fixes
v2.1.0
----------------
Date: 2011-08-19
* Added support for stronger cryptographic hashes
The default is now SHA-512 instead of MD5
* Experimental generic database storage using PDO
* Added work arounds for issues with the XML-RPC library
* Bug fix and additional sanity checks in getCheapestPClass
* Debug mode uses FirePHP if available
v2.0.0
----------------
Date: 2011-07-01
* Initial release of 2.0 API
* A complete rewrite using object oriented practices
+760
View File
@@ -0,0 +1,760 @@
<?php
/**
* KlarnaCountry
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Country Constants class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaCountry
{
/**
* Country constant for Austria (AT).<br>
* ISO3166_AT
*
* @var int
*/
const AT = 15;
/**
* Country constant for Denmark (DK).<br>
* ISO3166_DK
*
* @var int
*/
const DK = 59;
/**
* Country constant for Finland (FI).<br>
* ISO3166_FI
*
* @var int
*/
const FI = 73;
/**
* Country constant for Germany (DE).<br>
* ISO3166_DE
*
* @var int
*/
const DE = 81;
/**
* Country constant for Netherlands (NL).<br>
* ISO3166_NL
*
* @var int
*/
const NL = 154;
/**
* Country constant for Norway (NO).<br>
* ISO3166_NO
*
* @var int
*/
const NO = 164;
/**
* Country constant for Sweden (SE).<br>
* ISO3166_SE
*
* @var int
*/
const SE = 209;
/**
* Converts a country code, e.g. 'de' or 'deu' to the KlarnaCountry constant.
*
* @param string $val country code iso-alpha-2 or iso-alpha-3
*
* @return int|null
*/
public static function fromCode($val)
{
$val = strtoupper($val);
if (strlen($val) === 3) {
if (self::$_tlcFlip === array()) {
self::$_tlcFlip = array_flip(self::$_tlcMap);
}
if (!array_key_exists($val, self::$_tlcFlip)) {
return null;
}
$val = self::$_tlcFlip[$val];
}
if (array_key_exists($val, self::$_countries)) {
return self::$_countries[$val];
}
return null;
}
/**
* Converts a KlarnaCountry constant to the respective country code.
*
* @param int $val KlarnaCountry constant
* @param bool $alpha3 Whether to return a ISO-3166-1 alpha-3 code
*
* @return string|null
*/
public static function getCode($val, $alpha3 = false)
{
if (self::$_countryFlip === array()) {
self::$_countryFlip = array_flip(self::$_countries);
}
if (!array_key_exists($val, self::$_countryFlip)) {
return null;
}
$result = self::$_countryFlip[$val];
if ($alpha3) {
return self::$_tlcMap[$result];
}
return $result;
}
/**
* Checks country against currency and returns true if they match.
*
* @param int $country {@link KlarnaCountry}
* @param int $language {@link KlarnaLanguage}
*
* @deprecated Do not use.
*
* @return bool
*/
public static function checkLanguage($country, $language)
{
switch($country) {
case KlarnaCountry::AT:
case KlarnaCountry::DE:
return ($language === KlarnaLanguage::DE);
case KlarnaCountry::NL:
return ($language === KlarnaLanguage::NL);
case KlarnaCountry::FI:
return ($language === KlarnaLanguage::FI);
case KlarnaCountry::DK:
return ($language === KlarnaLanguage::DA);
case KlarnaCountry::NO:
return ($language === KlarnaLanguage::NB);
case KlarnaCountry::SE:
return ($language === KlarnaLanguage::SV);
default:
//Country not yet supported by Klarna.
return false;
}
}
/**
* Checks country against language and returns true if they match.
*
* @param int $country {@link KlarnaCountry}
* @param int $currency {@link KlarnaCurrency}
*
* @deprecated Do not use.
*
* @return bool
*/
public static function checkCurrency($country, $currency)
{
switch($country) {
case KlarnaCountry::AT:
case KlarnaCountry::DE:
case KlarnaCountry::NL:
case KlarnaCountry::FI:
return ($currency === KlarnaCurrency::EUR);
case KlarnaCountry::DK:
return ($currency === KlarnaCurrency::DKK);
case KlarnaCountry::NO:
return ($currency === KlarnaCurrency::NOK);
case KlarnaCountry::SE:
return ($currency === KlarnaCurrency::SEK);
default:
//Country not yet supported by Klarna.
return false;
}
}
/**
* Get language for supplied country. Defaults to English.
*
* @param int $country KlarnaCountry constant
*
* @deprecated Do not use.
*
* @return int
*/
public static function getLanguage($country)
{
switch($country) {
case KlarnaCountry::AT:
case KlarnaCountry::DE:
return KlarnaLanguage::DE;
case KlarnaCountry::NL:
return KlarnaLanguage::NL;
case KlarnaCountry::FI:
return KlarnaLanguage::FI;
case KlarnaCountry::DK:
return KlarnaLanguage::DA;
case KlarnaCountry::NO:
return KlarnaLanguage::NB;
case KlarnaCountry::SE:
return KlarnaLanguage::SV;
default:
return KlarnaLanguage::EN;
}
}
/**
* Get currency for supplied country
*
* @param int $country KlarnaCountry constant
*
* @deprecated Do not use.
*
* @return int|false
*/
public static function getCurrency($country)
{
switch($country) {
case KlarnaCountry::AT:
case KlarnaCountry::DE:
case KlarnaCountry::NL:
case KlarnaCountry::FI:
return KlarnaCurrency::EUR;
case KlarnaCountry::DK:
return KlarnaCurrency::DKK;
case KlarnaCountry::NO:
return KlarnaCurrency::NOK;
case KlarnaCountry::SE:
return KlarnaCurrency::SEK;
default:
return false;
}
}
private static $_tlcFlip = array();
/**
* Cache for the flipped country array
*
* @var array
*/
private static $_countryFlip = array();
/**
* Array containing all countries and their KRED Code
*
* @var array
*/
private static $_countries = array(
'AF' => 1, // AFGHANISTAN
'AX' => 2, // ÅLAND ISLANDS
'AL' => 3, // ALBANIA
'DZ' => 4, // ALGERIA
'AS' => 5, // AMERICAN SAMOA
'AD' => 6, // ANDORRA
'AO' => 7, // ANGOLA
'AI' => 8, // ANGUILLA
'AQ' => 9, // ANTARCTICA
'AG' => 10, // ANTIGUA AND BARBUDA
'AR' => 11, // ARGENTINA
'AM' => 12, // ARMENIA
'AW' => 13, // ARUBA
'AU' => 14, // AUSTRALIA
'AT' => 15, // AUSTRIA
'AZ' => 16, // AZERBAIJAN
'BS' => 17, // BAHAMAS
'BH' => 18, // BAHRAIN
'BD' => 19, // BANGLADESH
'BB' => 20, // BARBADOS
'BY' => 21, // BELARUS
'BE' => 22, // BELGIUM
'BZ' => 23, // BELIZE
'BJ' => 24, // BENIN
'BM' => 25, // BERMUDA
'BT' => 26, // BHUTAN
'BO' => 27, // BOLIVIA
'BA' => 28, // BOSNIA AND HERZEGOVINA
'BW' => 29, // BOTSWANA
'BV' => 30, // BOUVET ISLAND
'BR' => 31, // BRAZIL
'IO' => 32, // BRITISH INDIAN OCEAN TERRITORY
'BN' => 33, // BRUNEI DARUSSALAM
'BG' => 34, // BULGARIA
'BF' => 35, // BURKINA FASO
'BI' => 36, // BURUNDI
'KH' => 37, // CAMBODIA
'CM' => 38, // CAMEROON
'CA' => 39, // CANADA
'CV' => 40, // CAPE VERDE
'KY' => 41, // CAYMAN ISLANDS
'CF' => 42, // CENTRAL AFRICAN REPUBLIC
'TD' => 43, // CHAD
'CL' => 44, // CHILE
'CN' => 45, // CHINA
'CX' => 46, // CHRISTMAS ISLAND
'CC' => 47, // COCOS (KEELING) ISLANDS
'CO' => 48, // COLOMBIA
'KM' => 49, // COMOROS
'CG' => 50, // CONGO
'CD' => 51, // CONGO, THE DEMOCRATIC REPUBLIC OF THE
'CK' => 52, // COOK ISLANDS
'CR' => 53, // COSTA RICA
'CI' => 54, // COTE D'IVOIRE
'HR' => 55, // CROATIA
'CU' => 56, // CUBA
'CY' => 57, // CYPRUS
'CZ' => 58, // CZECH REPUBLIC
'DK' => 59, // DENMARK
'DJ' => 60, // DJIBOUTI
'DM' => 61, // DOMINICA
'DO' => 62, // DOMINICAN REPUBLIC
'EC' => 63, // ECUADOR
'EG' => 64, // EGYPT
'SV' => 65, // EL SALVADOR
'GQ' => 66, // EQUATORIAL GUINEA
'ER' => 67, // ERITREA
'EE' => 68, // ESTONIA
'ET' => 69, // ETHIOPIA
'FK' => 70, // FALKLAND ISLANDS (MALVINAS)
'FO' => 71, // FAROE ISLANDS
'FJ' => 72, // FIJI
'FI' => 73, // FINLAND
'FR' => 74, // FRANCE
'GF' => 75, // FRENCH GUIANA
'PF' => 76, // FRENCH POLYNESIA
'TF' => 77, // FRENCH SOUTHERN TERRITORIES
'GA' => 78, // GABON
'GM' => 79, // GAMBIA
'GE' => 80, // GEORGIA
'DE' => 81, // GERMANY
'GH' => 82, // GHANA
'GI' => 83, // GIBRALTAR
'GR' => 84, // GREECE
'GL' => 85, // GREENLAND
'GD' => 86, // GRENADA
'GP' => 87, // GUADELOUPE
'GU' => 88, // GUAM
'GT' => 89, // GUATEMALA
'GG' => 90, // GUERNSEY
'GN' => 91, // GUINEA
'GW' => 92, // GUINEA-BISSAU
'GY' => 93, // GUYANA
'HT' => 94, // HAITI
'HM' => 95, // HEARD ISLAND AND MCDONALD ISLANDS
'VA' => 96, // HOLY SEE (VATICAN CITY STATE)
'HN' => 97, // HONDURAS
'HK' => 98, // HONG KONG
'HU' => 99, // HUNGARY
'IS' => 100, // ICELAND
'IN' => 101, // INDIA
'ID' => 102, // INDONESIA
'IR' => 103, // IRAN, ISLAMIC REPUBLIC OF
'IQ' => 104, // IRAQ
'IE' => 105, // IRELAND
'IM' => 106, // ISLE OF MAN
'IL' => 107, // ISRAEL
'IT' => 108, // ITALY
'JM' => 109, // JAMAICA
'JP' => 110, // JAPAN
'JE' => 111, // JERSEY
'JO' => 112, // JORDAN
'KZ' => 113, // KAZAKHSTAN
'KE' => 114, // KENYA
'KI' => 115, // KIRIBATI
'KP' => 116, // KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
'KR' => 117, // KOREA, REPUBLIC OF
'KW' => 118, // KUWAIT
'KG' => 119, // KYRGYZSTAN
'LA' => 120, // LAO PEOPLE'S DEMOCRATIC REPUBLIC
'LV' => 121, // LATVIA
'LB' => 122, // LEBANON
'LS' => 123, // LESOTHO
'LR' => 124, // LIBERIA
'LY' => 125, // LIBYAN ARAB JAMAHIRIYA
'LI' => 126, // LIECHTENSTEIN
'LT' => 127, // LITHUANIA
'LU' => 128, // LUXEMBOURG
'MO' => 129, // MACAO
'MK' => 130, // MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
'MG' => 131, // MADAGASCAR
'MW' => 132, // MALAWI
'MY' => 133, // MALAYSIA
'MV' => 134, // MALDIVES
'ML' => 135, // MALI
'MT' => 136, // MALTA
'MH' => 137, // MARSHALL ISLANDS
'MQ' => 138, // MARTINIQUE
'MR' => 139, // MAURITANIA
'MU' => 140, // MAURITIUS
'YT' => 141, // MAYOTTE
'MX' => 142, // MEXICO
'FM' => 143, // MICRONESIA FEDERATED STATES OF
'MD' => 144, // MOLDOVA, REPUBLIC OF
'MC' => 145, // MONACO
'MN' => 146, // MONGOLIA
'MS' => 147, // MONTSERRAT
'MA' => 148, // MOROCCO
'MZ' => 149, // MOZAMBIQUE
'MM' => 150, // MYANMAR
'NA' => 151, // NAMIBIA
'NR' => 152, // NAURU
'NP' => 153, // NEPAL
'NL' => 154, // NETHERLANDS
'AN' => 155, // NETHERLANDS ANTILLES
'NC' => 156, // NEW CALEDONIA
'NZ' => 157, // NEW ZEALAND
'NI' => 158, // NICARAGUA
'NE' => 159, // NIGER
'NG' => 160, // NIGERIA
'NU' => 161, // NIUE
'NF' => 162, // NORFOLK ISLAND
'MP' => 163, // NORTHERN MARIANA ISLANDS
'NO' => 164, // NORWAY
'OM' => 165, // OMAN
'PK' => 166, // PAKISTAN
'PW' => 167, // PALAU
'PS' => 168, // PALESTINIAN TERRITORY OCCUPIED
'PA' => 169, // PANAMA
'PG' => 170, // PAPUA NEW GUINEA
'PY' => 171, // PARAGUAY
'PE' => 172, // PERU
'PH' => 173, // PHILIPPINES
'PN' => 174, // PITCAIRN
'PL' => 175, // POLAND
'PT' => 176, // PORTUGAL
'PR' => 177, // PUERTO RICO
'QA' => 178, // QATAR
'RE' => 179, // REUNION
'RO' => 180, // ROMANIA
'RU' => 181, // RUSSIAN FEDERATION
'RW' => 182, // RWANDA
'SH' => 183, // SAINT HELENA
'KN' => 184, // SAINT KITTS AND NEVIS
'LC' => 185, // SAINT LUCIA
'PM' => 186, // SAINT PIERRE AND MIQUELON
'VC' => 187, // SAINT VINCENT AND THE GRENADINES
'WS' => 188, // SAMOA
'SM' => 189, // SAN MARINO
'ST' => 190, // SAO TOME AND PRINCIPE
'SA' => 191, // SAUDI ARABIA
'SN' => 192, // SENEGAL
'CS' => 193, // SERBIA AND MONTENEGRO
'SC' => 194, // SEYCHELLES
'SL' => 195, // SIERRA LEONE
'SG' => 196, // SINGAPORE
'SK' => 197, // SLOVAKIA
'SI' => 198, // SLOVENIA
'SB' => 199, // SOLOMON ISLANDS
'SO' => 200, // SOMALIA
'ZA' => 201, // SOUTH AFRICA
'GS' => 202, // SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS
'ES' => 203, // SPAIN
'LK' => 204, // SRI LANKA
'SD' => 205, // SUDAN
'SR' => 206, // SURINAME
'SJ' => 207, // SVALBARD AND JAN MAYEN
'SZ' => 208, // SWAZILAND
'SE' => 209, // SWEDEN
'CH' => 210, // SWITZERLAND
'SY' => 211, // SYRIAN ARAB REPUBLIC
'TW' => 212, // TAIWAN PROVINCE OF CHINA
'TJ' => 213, // TAJIKISTAN
'TZ' => 214, // TANZANIA, UNITED REPUBLIC OF
'TH' => 215, // THAILAND
'TL' => 216, // TIMOR-LESTE
'TG' => 217, // TOGO
'TK' => 218, // TOKELAU
'TO' => 219, // TONGA
'TT' => 220, // TRINIDAD AND TOBAGO
'TN' => 221, // TUNISIA
'TR' => 222, // TURKEY
'TM' => 223, // TURKMENISTAN
'TC' => 224, // TURKS AND CAICOS ISLANDS
'TV' => 225, // TUVALU
'UG' => 226, // UGANDA
'UA' => 227, // UKRAINE
'AE' => 228, // UNITED ARAB EMIRATES
'GB' => 229, // UNITED KINGDOM
'US' => 230, // UNITED STATES
'UM' => 231, // UNITED STATES MINOR OUTLYING ISLANDS
'UY' => 232, // URUGUAY
'UZ' => 233, // UZBEKISTAN
'VU' => 234, // VANUATU
'VE' => 235, // VENEZUELA
'VN' => 236, // VIET NAM
'VG' => 237, // VIRGIN ISLANDS, BRITISH
'VI' => 238, // VIRGIN ISLANDS, US
'WF' => 239, // WALLIS AND FUTUNA
'EH' => 240, // WESTERN SAHARA
'YE' => 241, // YEMEN
'ZM' => 242, // ZAMBIA
'ZW' => 243 // ZIMBABWE
);
private static $_tlcMap = array(
'AF' => 'AFG',
'AX' => 'ALA',
'AL' => 'ALB',
'DZ' => 'DZA',
'AS' => 'ASM',
'AD' => 'AND',
'AO' => 'AGO',
'AI' => 'AIA',
'AQ' => 'ATA',
'AG' => 'ATG',
'AR' => 'ARG',
'AM' => 'ARM',
'AW' => 'ABW',
'AU' => 'AUS',
'AT' => 'AUT',
'AZ' => 'AZE',
'BS' => 'BHS',
'BH' => 'BHR',
'BD' => 'BGD',
'BB' => 'BRB',
'BY' => 'BLR',
'BE' => 'BEL',
'BZ' => 'BLZ',
'BJ' => 'BEN',
'BM' => 'BMU',
'BT' => 'BTN',
'BO' => 'BOL',
'BQ' => 'BES',
'BA' => 'BIH',
'BW' => 'BWA',
'BV' => 'BVT',
'BR' => 'BRA',
'IO' => 'IOT',
'BN' => 'BRN',
'BG' => 'BGR',
'BF' => 'BFA',
'BI' => 'BDI',
'KH' => 'KHM',
'CM' => 'CMR',
'CA' => 'CAN',
'CV' => 'CPV',
'KY' => 'CYM',
'CF' => 'CAF',
'TD' => 'TCD',
'CL' => 'CHL',
'CN' => 'CHN',
'CX' => 'CXR',
'CC' => 'CCK',
'CO' => 'COL',
'KM' => 'COM',
'CG' => 'COG',
'CD' => 'COD',
'CK' => 'COK',
'CR' => 'CRI',
'CI' => 'CIV',
'HR' => 'HRV',
'CU' => 'CUB',
'CW' => 'CUW',
'CY' => 'CYP',
'CZ' => 'CZE',
'DK' => 'DNK',
'DJ' => 'DJI',
'DM' => 'DMA',
'DO' => 'DOM',
'EC' => 'ECU',
'EG' => 'EGY',
'SV' => 'SLV',
'GQ' => 'GNQ',
'ER' => 'ERI',
'EE' => 'EST',
'ET' => 'ETH',
'FK' => 'FLK',
'FO' => 'FRO',
'FJ' => 'FJI',
'FI' => 'FIN',
'FR' => 'FRA',
'GF' => 'GUF',
'PF' => 'PYF',
'TF' => 'ATF',
'GA' => 'GAB',
'GM' => 'GMB',
'GE' => 'GEO',
'DE' => 'DEU',
'GH' => 'GHA',
'GI' => 'GIB',
'GR' => 'GRC',
'GL' => 'GRL',
'GD' => 'GRD',
'GP' => 'GLP',
'GU' => 'GUM',
'GT' => 'GTM',
'GG' => 'GGY',
'GN' => 'GIN',
'GW' => 'GNB',
'GY' => 'GUY',
'HT' => 'HTI',
'HM' => 'HMD',
'VA' => 'VAT',
'HN' => 'HND',
'HK' => 'HKG',
'HU' => 'HUN',
'IS' => 'ISL',
'IN' => 'IND',
'ID' => 'IDN',
'IR' => 'IRN',
'IQ' => 'IRQ',
'IE' => 'IRL',
'IM' => 'IMN',
'IL' => 'ISR',
'IT' => 'ITA',
'JM' => 'JAM',
'JP' => 'JPN',
'JE' => 'JEY',
'JO' => 'JOR',
'KZ' => 'KAZ',
'KE' => 'KEN',
'KI' => 'KIR',
'KP' => 'PRK',
'KR' => 'KOR',
'KW' => 'KWT',
'KG' => 'KGZ',
'LA' => 'LAO',
'LV' => 'LVA',
'LB' => 'LBN',
'LS' => 'LSO',
'LR' => 'LBR',
'LY' => 'LBY',
'LI' => 'LIE',
'LT' => 'LTU',
'LU' => 'LUX',
'MO' => 'MAC',
'MK' => 'MKD',
'MG' => 'MDG',
'MW' => 'MWI',
'MY' => 'MYS',
'MV' => 'MDV',
'ML' => 'MLI',
'MT' => 'MLT',
'MH' => 'MHL',
'MQ' => 'MTQ',
'MR' => 'MRT',
'MU' => 'MUS',
'YT' => 'MYT',
'MX' => 'MEX',
'FM' => 'FSM',
'MD' => 'MDA',
'MC' => 'MCO',
'MN' => 'MNG',
'ME' => 'MNE',
'MS' => 'MSR',
'MA' => 'MAR',
'MZ' => 'MOZ',
'MM' => 'MMR',
'NA' => 'NAM',
'NR' => 'NRU',
'NP' => 'NPL',
'NL' => 'NLD',
'NC' => 'NCL',
'NZ' => 'NZL',
'NI' => 'NIC',
'NE' => 'NER',
'NG' => 'NGA',
'NU' => 'NIU',
'NF' => 'NFK',
'MP' => 'MNP',
'NO' => 'NOR',
'OM' => 'OMN',
'PK' => 'PAK',
'PW' => 'PLW',
'PS' => 'PSE',
'PA' => 'PAN',
'PG' => 'PNG',
'PY' => 'PRY',
'PE' => 'PER',
'PH' => 'PHL',
'PN' => 'PCN',
'PL' => 'POL',
'PT' => 'PRT',
'PR' => 'PRI',
'QA' => 'QAT',
'RE' => 'REU',
'RO' => 'ROU',
'RU' => 'RUS',
'RW' => 'RWA',
'BL' => 'BLM',
'SH' => 'SHN',
'KN' => 'KNA',
'LC' => 'LCA',
'MF' => 'MAF',
'PM' => 'SPM',
'VC' => 'VCT',
'WS' => 'WSM',
'SM' => 'SMR',
'ST' => 'STP',
'SA' => 'SAU',
'SN' => 'SEN',
'RS' => 'SRB',
'SC' => 'SYC',
'SL' => 'SLE',
'SG' => 'SGP',
'SX' => 'SXM',
'SK' => 'SVK',
'SI' => 'SVN',
'SB' => 'SLB',
'SO' => 'SOM',
'ZA' => 'ZAF',
'GS' => 'SGS',
'SS' => 'SSD',
'ES' => 'ESP',
'LK' => 'LKA',
'SD' => 'SDN',
'SR' => 'SUR',
'SJ' => 'SJM',
'SZ' => 'SWZ',
'SE' => 'SWE',
'CH' => 'CHE',
'SY' => 'SYR',
'TW' => 'TWN',
'TJ' => 'TJK',
'TZ' => 'TZA',
'TH' => 'THA',
'TL' => 'TLS',
'TG' => 'TGO',
'TK' => 'TKL',
'TO' => 'TON',
'TT' => 'TTO',
'TN' => 'TUN',
'TR' => 'TUR',
'TM' => 'TKM',
'TC' => 'TCA',
'TV' => 'TUV',
'UG' => 'UGA',
'UA' => 'UKR',
'AE' => 'ARE',
'GB' => 'GBR',
'US' => 'USA',
'UM' => 'UMI',
'UY' => 'URY',
'UZ' => 'UZB',
'VU' => 'VUT',
'VE' => 'VEN',
'VN' => 'VNM',
'VG' => 'VGB',
'VI' => 'VIR',
'WF' => 'WLF',
'EH' => 'ESH',
'YE' => 'YEM',
'ZM' => 'ZMB',
'ZW' => 'ZWE'
);
}
+104
View File
@@ -0,0 +1,104 @@
<?php
/**
* KlarnaCurrency
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Currency Constants class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaCurrency
{
/**
* Currency constant for Swedish Crowns (SEK).
*
* @var int
*/
const SEK = 0;
/**
* Currency constant for Norwegian Crowns (NOK).
*
* @var int
*/
const NOK = 1;
/**
* Currency constant for Euro.
*
* @var int
*/
const EUR = 2;
/**
* Currency constant for Danish Crowns (DKK).
*
* @var int
*/
const DKK = 3;
/**
* Converts a currency code, e.g. 'eur' to the KlarnaCurrency constant.
*
* @param string $val currency code
*
* @return int|null
*/
public static function fromCode($val)
{
switch(strtolower($val)) {
case 'dkk':
return self::DKK;
case 'eur':
case 'euro':
return self::EUR;
case 'nok':
return self::NOK;
case 'sek':
return self::SEK;
default:
return null;
}
}
/**
* Converts a KlarnaCurrency constant to the respective language code.
*
* @param int $val KlarnaCurrency constant
*
* @return string|null
*/
public static function getCode($val)
{
switch($val) {
case self::DKK:
return 'dkk';
case self::EUR:
return 'eur';
case self::NOK:
return 'nok';
case self::SEK:
return 'sek';
default:
return null;
}
}
}
+250
View File
@@ -0,0 +1,250 @@
<?php
/**
* KlarnaEncoding
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
require_once 'Exceptions.php';
/**
* Encoding class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaEncoding
{
/**
* PNO/SSN encoding for Sweden.
*
* @var int
*/
const PNO_SE = 2;
/**
* PNO/SSN encoding for Norway.
*
* @var int
*/
const PNO_NO = 3;
/**
* PNO/SSN encoding for Finland.
*
* @var int
*/
const PNO_FI = 4;
/**
* PNO/SSN encoding for Denmark.
*
* @var int
*/
const PNO_DK = 5;
/**
* PNO/SSN encoding for Germany.
*
* @var int
*/
const PNO_DE = 6;
/**
* PNO/SSN encoding for Netherlands.
*
* @var int
*/
const PNO_NL = 7;
/**
* PNO/SSN encoding for Austria.
*
* @var int
*/
const PNO_AT = 8;
/**
* Encoding constant for customer numbers.
*
* @see Klarna::setCustomerNo()
* @var int
*/
const CUSTNO = 1000;
/**
* Encoding constant for email address.
*
* @var int
*/
const EMAIL = 1001;
/**
* Encoding constant for cell numbers.
*
* @var int
*/
const CELLNO = 1002;
/**
* Encoding constant for bank bic + account number.
*
* @var int
*/
const BANK_BIC_ACC_NO = 1003;
/**
* Returns the constant for the wanted country.
*
* @param string $country country
*
* @return int
*/
public static function get($country)
{
switch (strtoupper($country)) {
case "DE":
return KlarnaEncoding::PNO_DE;
case "DK":
return KlarnaEncoding::PNO_DK;
case "FI":
return KlarnaEncoding::PNO_FI;
case "NL":
return KlarnaEncoding::PNO_NL;
case "NO":
return KlarnaEncoding::PNO_NO;
case "SE":
return KlarnaEncoding::PNO_SE;
case "AT":
return KlarnaEncoding::PNO_AT;
default:
return -1;
}
}
/**
* Returns a regexp string for the specified encoding constant.
*
* @param int $enc PNO/SSN encoding constant.
*
* @return string The regular expression.
* @throws Klarna_UnknownEncodingException
*/
public static function getRegexp($enc)
{
switch($enc) {
case self::PNO_SE:
/*
* All positions except C contain numbers 0-9.
*
* PNO:
* YYYYMMDDCNNNN, C = -|+ length 13
* YYYYMMDDNNNN 12
* YYMMDDCNNNN 11
* YYMMDDNNNN 10
*
* ORGNO:
* XXXXXXNNNN
* XXXXXX-NNNN
* 16XXXXXXNNNN
* 16XXXXXX-NNNN
*
*/
return '/^[0-9]{6,6}(([0-9]{2,2}[-\+]{1,1}[0-9]{4,4})|([-\+]'.
'{1,1}[0-9]{4,4})|([0-9]{4,6}))$/';
case self::PNO_NO:
/*
* All positions contain numbers 0-9.
*
* Pno
* DDMMYYIIIKK ("fodelsenummer" or "D-nummer") length = 11
* DDMMYY-IIIKK ("fodelsenummer" or "D-nummer") length = 12
* DDMMYYYYIIIKK ("fodelsenummer" or "D-nummer") length = 13
* DDMMYYYY-IIIKK ("fodelsenummer" or "D-nummer") length = 14
*
* Orgno
* Starts with 8 or 9.
*
* NNNNNNNNK (orgno) length = 9
*/
return '/^[0-9]{6,6}((-[0-9]{5,5})|([0-9]{2,2}((-[0-9]'.
'{5,5})|([0-9]{1,1})|([0-9]{3,3})|([0-9]{5,5))))$/';
case self::PNO_FI:
/*
* Pno
* DDMMYYCIIIT
* DDMMYYIIIT
* C = century, '+' = 1800, '-' = 1900 och 'A' = 2000.
* I = 0-9
* T = 0-9, A-F, H, J, K-N, P, R-Y
*
* Orgno
* NNNNNNN-T
* NNNNNNNT
* T = 0-9, A-F, H, J, K-N, P, R-Y
*/
return '/^[0-9]{6,6}(([A\+-]{1,1}[0-9]{3,3}[0-9A-FHJK-NPR-Y]'.
'{1,1})|([0-9]{3,3}[0-9A-FHJK-NPR-Y]{1,1})|([0-9]{1,1}-{0,1}'.
'[0-9A-FHJK-NPR-Y]{1,1}))$/i';
case self::PNO_DK:
/*
* Pno
* DDMMYYNNNG length 10
* G = gender, odd/even for men/women.
*
* Orgno
* XXXXXXXX length 8
*/
return '/^[0-9]{8,8}([0-9]{2,2})?$/';
case self::PNO_NL:
case self::PNO_DE:
/**
* Pno
* DDMMYYYYG length 9
* DDMMYYYY 8
*
* Orgno
* XXXXXXX 7 company org nr
*/
return '/^[0-9]{7,9}$/';
case self::EMAIL:
/**
* Validates an email.
*/
return '/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]'.
'+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z0-9-][a-zA-Z0-9-]+)+$/';
case self::CELLNO:
/**
* Validates a cellno.
*
*/
return '/^07[\ \-0-9]{8,13}$/';
default:
throw new Klarna_UnknownEncodingException($enc);
}
}
/**
* Checks if the specified PNO is correct according to specified encoding constant.
*
* @param string $pno PNO/SSN string.
* @param int $enc {@link KlarnaEncoding PNO/SSN encoding} constant.
*
* @return bool True if correct.
*/
public static function checkPNO($pno, $enc = null)
{
return strlen($pno) > 0;
}
}
+735
View File
@@ -0,0 +1,735 @@
<?php
/**
* Klarna Exceptions
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
require_once 'Country.php';
/**
* KlarnaException class, only used so it says "KlarnaException" instead of
* Exception.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaException extends Exception
{
/**
* Returns an error message readable by end customers.
*
* @return string
*/
public function __toString()
{
return $this->getMessage() . " (#".$this->code.")";
}
}
/**
* Exception for invalid Configuration object
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidConfigurationException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
"Supplied config is not a KlarnaConfig/ArrayAccess object!",
50001
);
}
}
/**
* Exception for incomplete Configuration object
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_IncompleteConfigurationException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct('Klarna instance not fully configured!', 50002);
}
}
/**
* Exception for invalid KlarnaAddr object
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidKlarnaAddrException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
"Supplied address is not a KlarnaAddr object!",
50011
);
}
}
/**
* Exception for no KlarnaAddr set
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_MissingAddressException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct("No address set!", 50035);
}
}
/**
* Exception for missing Configuration field
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_ConfigFieldMissingException extends KlarnaException
{
/**
* Constructor
*
* @param string $field config field
*/
public function __construct($field)
{
parent::__construct("Config field '{$field}' is not valid!", 50003);
}
}
/**
* Exception for Unknown Encoding
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnknownEncodingException extends KlarnaException
{
/**
* Constructor
*
* @param int $encoding encoding
*/
public function __construct($encoding)
{
parent::__construct(
"Unknown PNO/SSN encoding constant! ({$encoding})", 50091
);
}
}
/**
* Exception for Unknown Address Type
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnknownAddressTypeException extends KlarnaException
{
/**
* Constructor
*
* @param int $type type
*/
public function __construct($type)
{
parent::__construct("Unknown address type: {$type}", 50012);
}
}
/**
* Exception for Missing Country
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_MissingCountryException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct('You must set country first!', 50046);
}
}
/**
* Exception for Unknown Country
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnknownCountryException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $country country
*/
public function __construct($country)
{
parent::__construct("Unknown country! ({$country})", 50006);
}
}
/**
* Exception for Unknown Language
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnknownLanguageException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $language language
*/
public function __construct($language)
{
parent::__construct("Unknown language! ({$language})", 50007);
}
}
/**
* Exception for Unknown Currency
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnknownCurrencyException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $currency currency
*/
public function __construct($currency)
{
parent::__construct("Unknown currency! ({$currency})", 50008);
}
}
/**
* Exception for Missing Arguments
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_ArgumentNotSetException extends KlarnaException
{
/**
* Constructor
*
* @param string $argument argument
*/
public function __construct($argument)
{
parent::__construct("Argument '{$argument}' not set!", 50005);
}
}
/**
* Exception for Country and Currency mismatch
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_CountryCurrencyMismatchException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $country country
* @param mixed $currency currency
*/
public function __construct($country, $currency)
{
$countryCode = KlarnaCountry::getCode($country);
parent::__construct(
"Mismatching country/currency for '{$countryCode}'! ".
"[country: $country currency: $currency]",
50011
);
}
}
/**
* Exception for Country and Currency mismatch
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_CountryLanguageMismatchException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $country country
* @param mixed $language language
*/
public function __construct($country, $language)
{
$countryCode = KlarnaCountry::getCode($country);
parent::__construct(
"Mismatching country/language for '{$countryCode}'! ".
"[country: $country language: $language]",
50024
);
}
}
/**
* Exception for Shipping country being different from set country
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_ShippingCountryException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
'Shipping address country must match the country set!', 50041
);
}
}
/**
* Exception for Missing Goodslist
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_MissingGoodslistException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct("No articles in goodslist!", 50034);
}
}
/**
* Exception for invalid price
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidPriceException extends KlarnaException
{
/**
* Constructor
*
* @param mixed $price price
*/
public function __construct($price)
{
parent::__construct(
"price/amount must be an integer and greater than 0! ($price)",
50039
);
}
}
/**
* Exception for invalid pcstorage class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_PCStorageInvalidException extends KlarnaException
{
/**
* Constructor
*
* @param string $className classname
* @param string $pclassStorage pcstorage class file
*/
public function __construct($className, $pclassStorage)
{
parent::__construct(
"$className located in $pclassStorage is not a PCStorage instance.",
50052
);
}
}
/**
* Exception for invalid type
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidTypeException extends KlarnaException
{
/**
* Constructor
*
* @param string $param parameter
* @param string $type type
*/
public function __construct($param, $type)
{
parent::__construct(
"$param is not of the expected type. Expected: $type.",
50062
);
}
}
/**
* Exception for invalid PNO
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidPNOException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct("PNO/SSN is not valid!", 50078);
}
}
/**
* Exception for invalid Email
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidEmailException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct("Email is not valid!", 50017);
}
}
/**
* Exception for invalid Email
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_UnsupportedMarketException extends KlarnaException
{
/**
* Constructor
*
* @param string|array $countries allowed countries
*/
public function __construct($countries)
{
if (is_array($countries)) {
$countries = implode(", ", $countries);
}
parent::__construct(
"This method is only available for customers from: {$countries}",
50025
);
}
}
/**
* Exception for invalid Locale
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_InvalidLocaleException extends KlarnaException
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
"You must set country, language and currency!",
50023
);
}
}
/**
* Exception for Missing Address Fields
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_AddressFieldMissingException extends KlarnaException
{
/**
* Constructor
*
* @param string $argument argument
*/
public function __construct($argument)
{
parent::__construct("'{$argument}' not set!", 50015);
}
}
/**
* Exception for File Not Writable
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_FileNotWritableException extends KlarnaException
{
/**
* Constructor
*
* @param string $file filename
*/
public function __construct($file)
{
parent::__construct("Unable to write to {$file}!");
}
}
/**
* Exception for File Not Readable
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_FileNotReadableException extends KlarnaException
{
/**
* Constructor
*
* @param string $file filename
*/
public function __construct($file)
{
parent::__construct("Unable to read from {$file}!");
}
}
/**
* Exception for File Not Readable
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_FileNotFoundException extends KlarnaException
{
/**
* Constructor
*
* @param string $file filename
*/
public function __construct($file)
{
parent::__construct("Unable to find file: {$file}!");
}
}
/**
* Exception for Database Errors
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_DatabaseException extends KlarnaException
{
}
/**
* Exception for PClass Errors
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_PClassException extends KlarnaException
{
}
/**
* Exception for XML Parse errors
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class Klarna_XMLParseException extends KlarnaException
{
/**
* Constructor
*
* @param string $file filename
*/
public function __construct($file)
{
parent::__construct("Unable to parse XML file: {$file}!");
}
}
+319
View File
@@ -0,0 +1,319 @@
<?php
/**
* KlarnaFlags
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Flag Constants class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaFlags
{
/**
* Specifies that no flag is to be used.
*
* @var int
*/
const NO_FLAG = 0;
//Gender flags
/**
* Indicates that the person is a female.<br>
* Use "" or null when unspecified.<br>
*
* @var int
*/
const FEMALE = 0;
/**
* Indicates that the person is a male.<br>
* Use "" or null when unspecified.<br>
*
* @var int
*/
const MALE = 1;
//Order status constants
/**
* This signifies that the invoice or reservation is accepted.
*
* @var int
*/
const ACCEPTED = 1;
/**
* This signifies that the invoice or reservation is pending, will be set
* to accepted or denied.
*
* @var int
*/
const PENDING = 2;
/**
* This signifies that the invoice or reservation is <b>denied</b>.
*
* @var int
*/
const DENIED = 3;
//Get_address constants
/**
* A code which indicates that all first names should be returned with the
* address.
*
* Formerly refered to as GA_OLD.
*
* @var int
*/
const GA_ALL = 1;
/**
* A code which indicates that only the last name should be returned with
* the address.
*
* Formerly referd to as GA_NEW.
*
* @var int
*/
const GA_LAST = 2;
/**
* A code which indicates that the given name should be returned with
* the address. If no given name is registered, this will behave as
* {@link KlarnaFlags::GA_ALL GA_ALL}.
*
*/
const GA_GIVEN = 5;
//Article/goods constants
/**
* Quantity measured in 1/1000s.
*
* @var int
*/
const PRINT_1000 = 1;
/**
* Quantity measured in 1/100s.
*
* @var int
*/
const PRINT_100 = 2;
/**
* Quantity measured in 1/10s.
*
* @var int
*/
const PRINT_10 = 4;
/**
* Indicates that the item is a shipment fee.
*
* Update_charge_amount (1)
*
* @var int
*/
const IS_SHIPMENT = 8;
/**
* Indicates that the item is a handling fee.
*
* Update_charge_amount (2)
*
* @var int
*/
const IS_HANDLING = 16;
/**
* Article price including VAT.
*
* @var int
*/
const INC_VAT = 32;
//Miscellaneous
/**
* Signifies that this is to be displayed in the checkout.<br>
* Used for part payment.<br>
*
* @var int
*/
const CHECKOUT_PAGE = 0;
/**
* Signifies that this is to be displayed in the product page.<br>
* Used for part payment.<br>
*
* @var int
*/
const PRODUCT_PAGE = 1;
/**
* Signifies that the specified address is billing address.
*
* @var int
*/
const IS_BILLING = 100;
/**
* Signifies that the specified address is shipping address.
*
* @var int
*/
const IS_SHIPPING = 101;
//Invoice and Reservation
/**
* Indicates that the purchase is a test invoice/part payment.
*
* @var int
*/
const TEST_MODE = 2;
/**
* PClass id/value for invoices.
*
* @see KlarnaPClass::INVOICE.
* @var int
*/
const PCLASS_INVOICE = -1;
//Invoice
/**
* Activates an invoices automatically, requires setting in Klarna Online.
*
* If you designate this flag an invoice is created directly in the active
* state, i.e. Klarna will buy the invoice immediately.
*
* @var int
*/
const AUTO_ACTIVATE = 1;
/**
* Creates a pre-pay invoice.
*
* @var int
*
* @deprecated Do not use.
*/
const PRE_PAY = 8;
/**
* Used to flag a purchase as sensitive order.
*
* @var int
*/
const SENSITIVE_ORDER = 1024;
/**
* Used to return an array with long and short ocr number.
*
* @see Klarna::addTransaction()
* @var int
*/
const RETURN_OCR = 8192;
/**
* Specifies the shipment type as normal.
*
* @var int
*/
const NORMAL_SHIPMENT = 1;
/**
* Specifies the shipment type as express.
*
* @var int
*/
const EXPRESS_SHIPMENT = 2;
//Mobile (Invoice) flags
/**
* Marks the transaction as Klarna mobile.
*
* @var int
*/
const M_PHONE_TRANSACTION = 262144;
/**
* Sends a pin code to the phone sent in pno.
*
* @var int
*/
const M_SEND_PHONE_PIN = 524288;
//Reservation flags
/**
* Signifies that the amount specified is the new amount.
*
* @var int
*/
const NEW_AMOUNT = 0;
/**
* Signifies that the amount specified is to be added.
*
* @var int
*/
const ADD_AMOUNT = 1;
/**
* Sends the invoice by mail when activating a reservation.
*
* @var int
*/
const RSRV_SEND_BY_MAIL = 4;
/**
* Sends the invoice by e-mail when activating a reservation.
*
* @var int
*/
const RSRV_SEND_BY_EMAIL = 8;
/**
* Used for partial deliveries, this flag saves the reservation number so
* it can be used again.
*
* @var int
*/
const RSRV_PRESERVE_RESERVATION = 16;
/**
* Used to flag a purchase as sensitive order.
*
* @var int
*/
const RSRV_SENSITIVE_ORDER = 32;
/**
* Marks the transaction as Klarna mobile.
*
* @var int
*/
const RSRV_PHONE_TRANSACTION = 512;
/**
* Sends a pin code to the mobile number.
*
* @var int
*/
const RSRV_SEND_PHONE_PIN = 1024;
}
File diff suppressed because it is too large Load Diff
+300
View File
@@ -0,0 +1,300 @@
<?php
/**
* KlarnaLanguage
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Language Constants class
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaLanguage
{
/**
* Language constant for Danish (DA).<br>
* ISO639_DA
*
* @var int
*/
const DA = 27;
/**
* Language constant for German (DE).<br>
* ISO639_DE
*
* @var int
*/
const DE = 28;
/**
* Language constant for English (EN).<br>
* ISO639_EN
*
* @var int
*/
const EN = 31;
/**
* Language constant for Finnish (FI).<br>
* ISO639_FI
*
* @var int
*/
const FI = 37;
/**
* Language constant for Norwegian (NB).<br>
* ISO639_NB
*
* @var int
*/
const NB = 97;
/**
* Language constant for Dutch (NL).<br>
* ISO639_NL
*
* @var int
*/
const NL = 101;
/**
* Language constant for Swedish (SV).<br>
* ISO639_SV
*
* @var int
*/
const SV = 138;
/**
* Converts a language code, e.g. 'de' to the KlarnaLanguage constant.
*
* @param string $val language code
*
* @return int|null
*/
public static function fromCode($val)
{
$val = strtoupper($val);
if (array_key_exists($val, self::$_languages)) {
return self::$_languages[$val];
}
return null;
}
/**
* Converts a KlarnaLanguage constant to the respective language code.
*
* @param int $val KlarnaLanguage constant
*
* @return lowercase string|null
*/
public static function getCode($val)
{
if (self::$_languageFlip === array()) {
self::$_languageFlip = array_flip(self::$_languages);
}
if (array_key_exists($val, self::$_languageFlip)) {
return strtolower(self::$_languageFlip[$val]);
}
return null;
}
/**
* Cache for the flipped language array
*
* @var array
*/
private static $_languageFlip = array();
/**
* Array containing all languages and their KRED Code
*
* @var array
*/
private static $_languages = array(
'AA' => 1, // Afar
'AB' => 2, // Abkhazian
'AE' => 3, // Avestan
'AF' => 4, // Afrikaans
'AM' => 5, // Amharic
'AR' => 6, // Arabic
'AS' => 7, // Assamese
'AY' => 8, // Aymara
'AZ' => 9, // Azerbaijani
'BA' => 10, // Bashkir
'BE' => 11, // Byelorussian; Belarusian
'BG' => 12, // Bulgarian
'BH' => 13, // Bihari
'BI' => 14, // Bislama
'BN' => 15, // Bengali; Bangla
'BO' => 16, // Tibetan
'BR' => 17, // Breton
'BS' => 18, // Bosnian
'CA' => 19, // Catalan
'CE' => 20, // Chechen
'CH' => 21, // Chamorro
'CO' => 22, // Corsican
'CS' => 23, // Czech
'CU' => 24, // Church Slavic
'CV' => 25, // Chuvash
'CY' => 26, // Welsh
'DA' => 27, // Danish
'DE' => 28, // German
'DZ' => 29, // Dzongkha; Bhutani
'EL' => 30, // Greek
'EN' => 31, // English
'EO' => 32, // Esperanto
'ES' => 33, // Spanish
'ET' => 34, // Estonian
'EU' => 35, // Basque
'FA' => 36, // Persian
'FI' => 37, // Finnish
'FJ' => 38, // Fijian; Fiji
'FO' => 39, // Faroese
'FR' => 40, // French
'FY' => 41, // Frisian
'GA' => 42, // Irish
'GD' => 43, // Scots; Gaelic
'GL' => 44, // Gallegan; Galician
'GN' => 45, // Guarani
'GU' => 46, // Gujarati
'GV' => 47, // Manx
'HA' => 48, // Hausa
'HE' => 49, // Hebrew (formerly iw)
'HI' => 50, // Hindi
'HO' => 51, // Hiri Motu
'HR' => 52, // Croatian
'HU' => 53, // Hungarian
'HY' => 54, // Armenian
'HZ' => 55, // Herero
'IA' => 56, // Interlingua
'ID' => 57, // Indonesian (formerly in)
'IE' => 58, // Interlingue
'IK' => 59, // Inupiak
'IO' => 60, // Ido
'IS' => 61, // Icelandic
'IT' => 62, // Italian
'IU' => 63, // Inuktitut
'JA' => 64, // Japanese
'JV' => 65, // Javanese
'KA' => 66, // Georgian
'KI' => 67, // Kikuyu
'KJ' => 68, // Kuanyama
'KK' => 69, // Kazakh
'KL' => 70, // Kalaallisut; Greenlandic
'KM' => 71, // Khmer; Cambodian
'KN' => 72, // Kannada
'KO' => 73, // Korean
'KS' => 74, // Kashmiri
'KU' => 75, // Kurdish
'KV' => 76, // Komi
'KW' => 77, // Cornish
'KY' => 78, // Kirghiz
'LA' => 79, // Latin
'LB' => 80, // Letzeburgesch
'LN' => 81, // Lingala
'LO' => 82, // Lao; Laotian
'LT' => 83, // Lithuanian
'LV' => 84, // Latvian; Lettish
'MG' => 85, // Malagasy
'MH' => 86, // Marshall
'MI' => 87, // Maori
'MK' => 88, // Macedonian
'ML' => 89, // Malayalam
'MN' => 90, // Mongolian
'MO' => 91, // Moldavian
'MR' => 92, // Marathi
'MS' => 93, // Malay
'MT' => 94, // Maltese
'MY' => 95, // Burmese
'NA' => 96, // Nauru
'NB' => 97, // Norwegian Bokmål
'ND' => 98, // Ndebele, North
'NE' => 99, // Nepali
'NG' => 100, // Ndonga
'NL' => 101, // Dutch
'NN' => 102, // Norwegian Nynorsk
'NO' => 103, // Norwegian
'NR' => 104, // Ndebele, South
'NV' => 105, // Navajo
'NY' => 106, // Chichewa; Nyanja
'OC' => 107, // Occitan; Provençal
'OM' => 108, // (Afan) Oromo
'OR' => 109, // Oriya
'OS' => 110, // Ossetian; Ossetic
'PA' => 111, // Panjabi; Punjabi
'PI' => 112, // Pali
'PL' => 113, // Polish
'PS' => 114, // Pashto, Pushto
'PT' => 115, // Portuguese
'QU' => 116, // Quechua
'RM' => 117, // Rhaeto-Romance
'RN' => 118, // Rundi; Kirundi
'RO' => 119, // Romanian
'RU' => 120, // Russian
'RW' => 121, // Kinyarwanda
'SA' => 122, // Sanskrit
'SC' => 123, // Sardinian
'SD' => 124, // Sindhi
'SE' => 125, // Northern Sami
'SG' => 126, // Sango; Sangro
'SI' => 127, // Sinhalese
'SK' => 128, // Slovak
'SL' => 129, // Slovenian
'SM' => 130, // Samoan
'SN' => 131, // Shona
'SO' => 132, // Somali
'SQ' => 133, // Albanian
'SR' => 134, // Serbian
'SS' => 135, // Swati; Siswati
'ST' => 136, // Sesotho; Sotho, Southern
'SU' => 137, // Sundanese
'SV' => 138, // Swedish
'SW' => 139, // Swahili
'TA' => 140, // Tamil
'TE' => 141, // Telugu
'TG' => 142, // Tajik
'TH' => 143, // Thai
'TI' => 144, // Tigrinya
'TK' => 145, // Turkmen
'TL' => 146, // Tagalog
'TN' => 147, // Tswana; Setswana
'TO' => 148, // Tongan
'TR' => 149, // Turkish
'TS' => 150, // Tsonga
'TT' => 151, // Tatar
'TW' => 152, // Twi
'TY' => 153, // Tahitian
'UG' => 154, // Uighur
'UK' => 155, // Ukrainian
'UR' => 156, // Urdu
'UZ' => 157, // Uzbek
'VI' => 158, // Vietnamese
'VO' => 159, // Volapuk
'WA' => 160, // Walloon
'WO' => 161, // Wolof
'XH' => 162, // Xhosa
'YI' => 163, // Yiddish (formerly ji)
'YO' => 164, // Yoruba
'ZA' => 165, // Zhuang
'ZH' => 166, // Chinese
'ZU' => 167 // Zulu
);
}
@@ -0,0 +1,97 @@
<?php
/**
* CheckoutHTML interface for threatmetrix
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* This interface provides methods to supply checkout page specific HTML.<br>
* Can be used to insert device identification, fraud prevention,<br>
* client side validation code into the checkout page.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
abstract class CheckoutHTML
{
/**
* Creates a session ID used for e.g. client identification and fraud
* prevention.
*
* This method creates a 40 character long integer.
* The first 30 numbers is microtime + random numbers.
* The last 10 numbers is the eid zero-padded.
*
* All random functions are automatically seeded as of PHP 4.2.0.
*
* E.g. for eid 1004 output could be:
* 1624100001298454658880354228080000001004
*
* @param int $eid merchant id
*
* @return string A integer with a string length of 40.
*/
public static function getSessionID($eid)
{
$eid = strval($eid);
while (strlen($eid) < 10) {
$eid = "0" . $eid; //Zero-pad the eid.
}
$sid = str_replace(array(' ', ',', '.'), '', microtime());
$sid[0] = rand(1, 9); //Make sure we always have a non-zero first.
//microtime + rand = 30 numbers in length
while (strlen($sid) < 30) {
//rand is automatically seeded as of PHP 4.2.0
$sid .= rand(0, 9999);
}
$sid = substr($sid, 0, 30);
$sid .= $eid;
return $sid;
}
/**
* Initializes this object, this method is always called
* before {@link CheckoutHTML::toHTML()}.
* This method is used in {@link Klarna::addTransaction()},
* {@link Klarna::reserveAmount()} and in {@link Klarna::checkoutHTML()}
*
* @param Klarna $klarna The API instance
* @param int $eid merchant id
*
* @return void
*/
abstract public function init($klarna, $eid);
/**
* This returns the HTML code for this object,
* which will be used in the checkout page.
*
* @return string HTML
*/
abstract public function toHTML();
/**
* This function is used to clear any stored values
* (in SESSION, COOKIE or similar)
* which are required to be unique between purchases.
*
* @return void
*/
abstract public function clear();
}
+136
View File
@@ -0,0 +1,136 @@
<?php
/**
* threatmetrix implementation of checckouthtml
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* ThreatMetrix is a fraud prevention and device identification software.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class ThreatMetrix extends CheckoutHTML
{
/**
* The ID used in conjunction with the Klarna API.
*
* @var int
*/
const ID = 'dev_id_1';
/**
* ThreatMetrix organizational ID.
*
* @var string
*/
protected $orgID = 'qicrzsu4';
/**
* Session ID for the client.
*
* @var string
*/
protected $sessionID;
/**
* Hostname used to access ThreatMetrix.
*
* @var string
*/
protected $host = 'h.online-metrix.net';
/**
* Protocol used to access ThreatMetrix.
*
* @var string
*/
protected $proto = 'https';
/**
* Initializes this object, this method is always called
* before {@link CheckoutHTML::toHTML()}.
* This method is used in {@link Klarna::addTransaction()},
* {@link Klarna::reserveAmount()} and in {@link Klarna::checkoutHTML()}
*
* @param Klarna $klarna The API instance
* @param int $eid Merchant ID
*
* @return void
*/
public function init($klarna, $eid)
{
if (!is_int($eid)) {
throw new Klarna_ConfigFieldMissingException('eid');
}
if (isset($_SESSION)) {
if (!isset($_SESSION[self::ID])
|| (strlen($_SESSION[self::ID]) < 40)
) {
$_SESSION[self::ID] = parent::getSessionID($eid);
$this->sessionID = $_SESSION[self::ID];
} else {
$this->sessionID = $_SESSION[self::ID];
}
} else {
$this->sessionID = parent::getSessionID($eid);
}
$klarna->setSessionID(self::ID, $this->sessionID);
}
/**
* This function is used to clear any stored values
* (in SESSION, COOKIE or similar)
* which are required to be unique between purchases.
*
* @return void
*/
public function clear()
{
if (isset($_SESSION) && isset($_SESSION[self::ID])) {
$_SESSION[self::ID] = null;
unset($_SESSION[self::ID]);
}
}
/**
* This returns the HTML code for this object,
* which will be used in the checkout page.
*
* @return string
*/
public function toHTML()
{
$html
= "<p style='display: none; ".
"background:url($this->proto://$this->host/fp/clear.png?org_id=".
"$this->orgID&session_id=$this->sessionID&m=1)'></p>".
"<script src='$this->proto://$this->host/fp/check.js?org_id=".
"$this->orgID&session_id=$this->sessionID' ".
"type='text/javascript'></script>".
"<img src='$this->proto://$this->host/fp/clear.png?org_id=".
"$this->orgID&session_id=$this->sessionID&m=2' alt='' >".
"<object type='application/x-shockwave-flash' style='display: none' ".
"data='$this->proto://$this->host/fp/fp.swf?org_id=$this->orgID&".
"session_id=$this->sessionID' width='1' height='1' id='obj_id'>".
"<param name='movie' value='$this->proto://$this->host/fp/fp.swf?".
"org_id=$this->orgID&session_id=$this->sessionID' />".
"<div></div>".
"</object>";
return $html;
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
/**
* 2. Activate the reservation
*/
$rno = '123456';
// Optional fields should be set using
// $k->setActivateInfo()
try {
$result = $k->activate($rno);
$risk = $result[0]; // ok or no_risk
$invno = $result[1];
echo "risk: {$risk}\ninvno: {$invno}\n";
// Reservation is activated, proceed accordingly.
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+53
View File
@@ -0,0 +1,53 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Activate the invoice
*/
// Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
// You can specify a new pclass ID if the customer wanted to change it
// before you activate.
$url = $k->activateInvoice($invNo, $pclass = KlarnaPClass::INVOICE);
echo "{$url}\n";
// The url points to a PDF file for the invoice.
// Invoice activated, proceed accordingly.
} catch(Exception $e) {
// Something went wrong or the invoice doesn't exist.
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+67
View File
@@ -0,0 +1,67 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Partially activate the invoice
*/
// Here you specify the quantity of an article you wish to partially activate.
// artNo must be the same as the one you used in addArticle() when you made the
// addTransaction() call.
$k->addArtNo(
1, // Quantity
'MG200MMS' // Article number
);
// Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
$result = $k->activatePart(
$invNo, // Invoice number
KlarnaPClass::INVOICE // Or the PClass ID used to make the order.
);
$url = $result['url'];
echo "url: ${url}\n";
if (isset($result['invno'])) {
$invno = $result['invno'];
echo "invno: ${invno}\n";
}
// The url points to a PDF file for the invoice.
// The invno field is only present if the invoice was not entirely activated,
// and in that case it contains the new invoice number.
// Invoice activated, proceed accordingly.
} catch(Exception $e) {
// Something went wrong or the invoice doesn't exist.
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
@@ -0,0 +1,158 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Add the article(s), shipping and/or handling fee.
*/
// Here we add a normal product to our goods list.
$k->addArticle(
4, // Quantity
"MG200MMS", // Article number
"Matrox G200 MMS", // Article name/title
299.99, // Price
25, // 25% VAT
0, // Discount
KlarnaFlags::INC_VAT // Price is including VAT.
);
// Next we might want to add a shipment fee for the product
$k->addArticle(
1,
"",
"Shipping fee",
14.5,
25,
0,
// Price is including VAT and is shipment fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_SHIPMENT
);
// Lastly, we want to use an invoice/handling fee as well
$k->addArticle(
1,
"",
"Handling fee",
11.5,
25,
0,
// Price is including VAT and is handling/invoice fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_HANDLING
);
/**
* 3. Create and set the address(es).
*/
// Create the address object and specify the values.
$addr = new KlarnaAddr(
'always_approved@klarna.com', // email
'', // Telno, only one phone number is needed.
'0762560000', // Cellno
'Testperson-se', // Firstname
'Approved', // Lastname
'', // No care of, C/O.
'Stårgatan 1', // Street
'12345', // Zip Code
'Ankeborg', // City
KlarnaCountry::SE, // Country
null, // HouseNo for German and Dutch customers.
null // House Extension. Dutch customers only.
);
// Next we tell the Klarna instance to use the address in the next order.
$k->setAddress(KlarnaFlags::IS_BILLING, $addr); // Billing / invoice address
$k->setAddress(KlarnaFlags::IS_SHIPPING, $addr); // Shipping / delivery address
/**
* 4. Specify relevant information from your store. (OPTIONAL)
*/
// Set store specific information so you can e.g. search and associate invoices
// with order numbers.
$k->setEstoreInfo(
'175012', // Order ID 1
'1999110234', // Order ID 2
'' // Optional username, email or identifier
);
// If you don't have the order id available at this stage, you can later use the
// method updateOrderNo().
/**
* 5. Set additional information. (OPTIONAL)
*/
/** Comment **/
$k->setComment('A text string stored in the invoice commentary area.');
/** Shipment type **/
// Normal shipment is defaulted, delays the start of invoice
// expiration/due-date.
$k->setShipmentInfo('delay_adjust', KlarnaFlags::EXPRESS_SHIPMENT);
/**
* 6. Invoke activateReservation and transmit the data.
*/
/* Make sure the order status is ACCEPTED, before activation.
You can do this by using checkOrderStatus(). */
// Here you enter the reservation number you got from reserveAmount():
$rno = '123456';
try {
// Transmit all the specified data, from the steps above, to Klarna.
$result = $k->activateReservation(
'4103219202', // PNO (Date of birth for DE and NL).
$rno, // Reservation to activate
null, // Gender.
'', // OCR number to use if you have reserved one.
KlarnaFlags::NO_FLAG, // Flags to affect behavior.
// -1, notes that this is an invoice purchase, for part payment purchase
// you will have a pclass object which you use getId() from.
KlarnaPClass::INVOICE
);
$risk = $result[0]; // ok or no_risk
$invno = $result[1];
echo "risk: {$risk}\ninvno: {$invno}\n";
// Reservation is activated, proceed accordingly.
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+159
View File
@@ -0,0 +1,159 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Add the article(s), shipping and/or handling fee.
*/
// Here we add a normal product to our goods list.
$k->addArticle(
4, // Quantity
"MG200MMS", // Article number
"Matrox G200 MMS", // Article name/title
299.99, // Price
25, // 25% VAT
0, // Discount
KlarnaFlags::INC_VAT // Price is including VAT.
);
// Next we might want to add a shipment fee for the product
$k->addArticle(
1,
"",
"Shipping fee",
14.5,
25,
0,
// Price is including VAT and is shipment fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_SHIPMENT
);
// Lastly, we want to use an invoice/handling fee as well
$k->addArticle(
1,
"",
"Handling fee",
11.5,
25,
0,
// Price is including VAT and is handling/invoice fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_HANDLING
);
/**
* 3. Create and set the address(es).
*/
// Create the address object and specify the values.
$addr = new KlarnaAddr(
'always_approved@klarna.com', // email
'', // Telno, only one phone number is needed.
'0762560000', // Cellno
'Testperson-se', // Firstname
'Approved', // Lastname
'', // No care of, C/O.
'Stårgatan 1', // Street
'12345', // Zip Code
'Ankeborg', // City
KlarnaCountry::SE, // Country
null, // HouseNo for German and Dutch customers.
null // House Extension. Dutch customers only.
);
// Next we tell the Klarna instance to use the address in the next order.
$k->setAddress(KlarnaFlags::IS_BILLING, $addr); // Billing / invoice address
$k->setAddress(KlarnaFlags::IS_SHIPPING, $addr); // Shipping / delivery address
/**
* 4. Specify relevant information from your store. (OPTIONAL)
*/
// Set store specific information so you can e.g. search and associate invoices
// with order numbers.
$k->setEstoreInfo(
'175012', // Order ID 1
'1999110234', // Order ID 2
'' // Optional username, email or identifier
);
// If you don't have the order id available at this stage, you can later use the
// method updateOrderNo().
/**
* 5. Set additional information. (OPTIONAL)
*/
/** Comment **/
$k->setComment('A text string stored in the invoice commentary area.');
/** Shipment type **/
// Normal shipment is defaulted, delays the start of invoice expiration/due-date.
$k->setShipmentInfo('delay_adjust', KlarnaFlags::EXPRESS_SHIPMENT);
/**
* 6. Invoke addTransaction and transmit the data.
*/
try {
// Transmit all the specified data, from the steps above, to Klarna.
$result = $k->addTransaction(
'4103219202', // PNO (Date of birth for DE and NL).
null, // Gender.
KlarnaFlags::NO_FLAG, // Flags to affect behavior.
// -1, notes that this is an invoice purchase, for part payment purchase
// you will have a pclass object on which you use getId().
KlarnaPClass::INVOICE
);
// Check the order status
if ($result[1] == KlarnaFlags::PENDING) {
/* 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.
*/
}
// Here we get the invoice number
$invno = $result[0];
// Order is complete, store it in a database.
echo "Status: {$result[1]}\nInvno: {$result[0]}\n";
} catch(Exception $e) {
// The purchase was denied or something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
echo $e->getTraceAsString();
}
@@ -0,0 +1,56 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Calculate the monthly cost for the product page.
*/
$sum = 149.99; // Let's assume this is the product cost.
$flag = KlarnaFlags::PRODUCT_PAGE; // or KlarnaFlags::CHECKOUT_PAGE, if you want
// to do it for the whole order.
$pclass = $k->getCheapestPClass($sum, $flag);
// Did we get a PClass? (it is false if we didn't)
if ($pclass) {
// Here we reuse the same values as above:
$value = KlarnaCalc::calc_monthly_cost(
$sum,
$pclass,
$flag
);
echo "Value: {$value}\n";
/*
$value is now a rounded monthly cost amount to be displayed to the
customer.
*/
}
@@ -0,0 +1,48 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Cancelling a reservation
*/
// Here you enter the reservation number you got from reserveAmount():
$rno = '123456';
try {
$result = $k->cancelReservation($rno);
echo "Result: {$result}\n";
// Reservation cancelled, proceed accordingly.
} catch(Exception $e) {
// Something went wrong or the reservation doesn't exist.
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
@@ -0,0 +1,54 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Change the reservation.
*/
// Here you enter the reservation number you got from reserveAmount():
$rno = '123456';
try {
$result = $k->changeReservation(
$rno, // Reservation number
49.99, // Amount
KlarnaFlags::NEW_AMOUNT // Flag deciding if the amount is the new amount
// to reserve, or if it is to be added to the
// existing amount. (KlarnaFlags::ADD_AMOUNT)
);
// Reservation changed, proceed accordingly.
echo "Result: {$result}\n";
} catch (Exception $e) {
// Something went wrong or the reservation doesn't exist.
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+58
View File
@@ -0,0 +1,58 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Check the status on your order (invoice or reservation)
*/
$id = '123456'; // Your reservation or invoice number.
try {
$result = $k->checkOrderStatus(
$id, // Reservation, invoice number or order id.
0 // Flag specifying number type. 0 = rno or invno. 1 = order id.
);
if ($result == KlarnaFlags::ACCEPTED) {
// Status changed, you can now activate your invoice/reservation.
echo "Accepted\n";
} else if ($result == KlarnaFlags::DENIED) {
echo "Denied\n";
// Status changed, it is now denied, proceed accordingly.
} else {
echo "Pending\n";
//Order is still pending, try again later.
}
} catch (Exception $e) {
//Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+53
View File
@@ -0,0 +1,53 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Completely refund a invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
$result = $k->creditInvoice(
$invNo, // Invoice Number
'' // Credit number. (Optional).
);
echo "Result: {$result}\n";
/* Invoice fully refunded, proceed accordingly.
$result contains the invoice number of the refunded invoice. */
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+60
View File
@@ -0,0 +1,60 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Partially refund a invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
// Specify for which article(s) you want to refund.
$k->addArtNo(
1, // Quantity
'MG200MMS' // Article Number. Must be the same as the one you used
); // in addArticle() when you made the addTransaction() call.
try {
$result = $k->creditPart(
$invNo, // Invoice Number
'' // Credit Number. (Optional).
);
echo "Result: {$result}\n";
/* Invoice partially refunded, proceed accordingly.
$result contains the invoice number of the refunded invoice.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+49
View File
@@ -0,0 +1,49 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Remove the invoice
*/
//Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
$result = $k->deleteInvoice($invNo);
echo "Result: {$result}\n";
//Invoice removed, proceed accordingly.
} catch(Exception $e) {
//Something went wrong or the invoice doesn't exist.
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+50
View File
@@ -0,0 +1,50 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Send an (activated) invoice to the customer via email.
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
$result = $k->emailInvoice($invNo);
echo "Result: {$result}\n";
/* 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:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+50
View File
@@ -0,0 +1,50 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Retrieve the PClasses from Klarna.
*/
try {
$k->fetchPClasses(); // You can specify country (and language, currency if
// you wish) if you don't want to use the configured
// country.
/* PClasses successfully fetched, now you can use getPClasses() to load them
locally or getPClass to load a specific PClass locally.
*/
echo "Fetched " . count($k->getAllPClasses()) . " pclasses.\n";
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+66
View File
@@ -0,0 +1,66 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Get the address(es) from Klarna. (Sweden only!)
*/
$k->setCountry('se');
try {
//Attempt to get the address(es) associated with the SSN/PNO.
$addrs = $k->getAddresses('410321-9202');
/* If there exists several addresses you would want to output a list in
which the customer could choose the address which suits him/her.
*/
// Print them if available:
foreach ($addrs as $key => $addr) {
echo "<table>\n";
// This only works if the right getAddresses type is used.
if ($addr->isCompany) {
echo "\t<tr><td>Company</td><td>{$addr->getCompanyName()}</td></tr>\n";
} else {
echo "\t<tr><td>First name</td><td>{$addr->getFirstName()}</td></tr>\n";
echo "\t<tr><td>Last name</td><td>{$addr->getLastName()}</td></tr>\n";
}
echo "\t<tr><td>Street</td><td>{$addr->getStreet()}</td></tr>\n";
echo "\t<tr><td>Zip code</td><td>{$addr->getZipCode()}</td></tr>\n";
echo "\t<tr><td>City</td><td>{$addr->getCity()}</td></tr>\n";
echo "\t<tr><td>Country</td><td>{$addr->getCountryCode()}</td></tr>\n";
echo "</table>\n";
}
} catch(Exception $e) {
//Something went wrong
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+119
View File
@@ -0,0 +1,119 @@
<?php
require_once('../Klarna.php');
//Dependencies from http://phpxmlrpc.sourceforge.net/
require_once(dirname(dirname(__FILE__)).'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc');
require_once(dirname(dirname(__FILE__)).'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc');
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
/** Configure the Klarna object using the setConfig() method. (Alternative 1) **/
//Later we define the settings in code, thus we don't save the config to a file in JSON format.
/*
KlarnaConfig::$store = false;
//Create the config object, since we aren't storing the file, we don't need to specify a URI.
$config = new KlarnaConfig($file = null);
//Define the values:
$config['eid'] = 0; //Merchant ID or Estore ID, an integer above 0.
$config['secret'] = "sharedSecret"; //The shared secret which accompanied your eid.
$config['country'] = KlarnaCountry::DE;
$config['language'] = KlarnaLanguage::DE;
$config['currency'] = KlarnaCurrency::EUR;
$config['mode'] = Klarna::BETA; //or Klarna::BETA, depending on which server your eid is associated with.
//Define pclass settings:
$config['pcStorage'] = 'json'; //Which storage module? can be json, xml or mysql.
$config['pcURI'] = '/srv/pclasses.json'; //Where the json file for the pclasses are stored.
//Should we use HTTPS?
$config['ssl'] = false;
//Should we error report/status report to Klarna?
$config['candice'] = true; //(set to false if your server doesn't support UDP)
//Do we want to see xmlrpc debugging information?
$config['xmlrpcDebug'] = null; //If this is defined to anything, it will debug.
//Do we want to see normal debug information?
$config['debug'] = null; //If this is defined to anything, it will debug.
//Set the config object.
$k->setConfig($config);
*/
/** Configure the Klarna object using the config() method. (Alternative 2) **/
//Specify the values:
/*
$k->config(
$eid = 0,
$secret = 'sharedSecret',
$country = KlarnaCountry::DE,
$language = KlarnaLanguage::DE,
$currency = KlarnaCurrency::EUR,
$mode = Klarna::BETA,
$pcStorage = 'json',
$pcURI = '/srv/pclasses.json',
$ssl = true,
$candice = true
);
Klarna::$xmlrpcDebug = false;
Klarna::$debug = false;
*/
/** Configure the Klarna object using the setConfig() method. (Alternative 3) **/
//KlarnaConfig::$store = true; //This is default to true, so this is just to be more detailed.
//Set the config which loads from file /srv/klarna.json:
$k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/* The file would contain the following data to set the same information as the above alternatives:
{
"eid": 0,
"secret":"sharedSecret",
"country": 81,
"language": 28,
"currency": 2,
"mode":0,
"pcStorage":"json",
"pcURI":"\/srv\/pclasses.json",
"ssl": 1,
"candice": 1,
"xmlrpcDebug":0,
"debug":0
}
*/
/**
* 2. Load the PClasses from the local file or MySQL table.
*/
/* PClasses are loaded from the local storage, as defined by "pcStorage" and "pcURI". */
//Load all PClasses available.
$pclasses = $k->getPClasses(
$type = null //Here we can define a specific type of PClass we want to load (KlarnaPClass::CAMPAIGN, for instance).
);
//Next we might want to display the description in a drop down menu:
echo "<select name='pclass'>";
foreach($pclasses as $pclass) {
echo "<option value='".$pclass->getId()."'>".$pclass->getDescription()."</option>";
}
echo "</select>";
//When the customer has confirmed the purchase and chosen a pclass, you can easily grab just that one by doing:
$pclassId = $pclasses[0]->getId(); //Let's say the customer picked the first one
$pclass = $k->getPClass($pclassId);
// Next we can use $pclassId in the addTransaction call or in the reserveAmount call.
+61
View File
@@ -0,0 +1,61 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Get the address associated with the purchase/invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
// Attempt to get the address
$addr = $k->invoiceAddress($invNo);
// Display the retrieved address:
echo "<table>\n";
if ($addr->isCompany) {
echo "\t<tr><td>Company</td><td>{$addr->getCompanyName()}</td></tr>\n";
} else {
echo "\t<tr><td>First name</td><td>{$addr->getFirstName()}</td></tr>\n";
echo "\t<tr><td>Last name</td><td>{$addr->getLastName()}</td></tr>\n";
}
echo "\t<tr><td>Street</td><td>{$addr->getStreet()}</td></tr>\n";
echo "\t<tr><td>Zip code</td><td>{$addr->getZipCode()}</td></tr>\n";
echo "\t<tr><td>City</td><td>{$addr->getCity()}</td></tr>\n";
echo "\t<tr><td>Country</td><td>{$addr->getCountryCode()}</td></tr>\n";
echo "</table>\n";
} catch(Exception $e) {
//Something went wrong
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+50
View File
@@ -0,0 +1,50 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Retrieve the total amount of a invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
$result = $k->invoiceAmount($invNo);
echo "Result: {$result}\n";
/* Invoice amount successfully retrieved, proceed accordingly.
$result contains the total sum of the invoice.
*/
} catch(Exception $e) {
//Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
@@ -0,0 +1,58 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Retrieve the amount for specific article(s) from an invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
// Specify for which article(s) you want the amount.
// artNo must be the same as the one you used in addArticle() when you made the
// addTransaction() call.
$k->addArtNo(
1, // Quantity
'MG200MMS' // Article number
);
try {
$result = $k->invoicePartAmount($invNo);
echo "Result: {$result}\n";
/* Partial invoice amount successfully retrieved, proceed accordingly.
$result contains the sum of specified article(s).
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+160
View File
@@ -0,0 +1,160 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Add the article(s), shipping and/or handling fee.
*/
// Here we add a normal product to our goods list.
$k->addArticle(
4, // Quantity
"MG200MMS", // Article number
"Matrox G200 MMS", // Article name/title
299.99, // Price
25, // 25% VAT
0, // Discount
KlarnaFlags::INC_VAT // Price is including VAT.
);
// Next we might want to add a shipment fee for the product
$k->addArticle(
1,
"",
"Shipping fee",
14.5,
25,
0,
// Price is including VAT and is shipment fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_SHIPMENT
);
// Lastly, we want to use an invoice/handling fee as well
$k->addArticle(
1,
"",
"Handling fee",
11.5,
25,
0,
// Price is including VAT and is handling/invoice fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_HANDLING
);
/**
* 3. Create and set the address(es).
*/
// Create the address object and specify the values.
$addr = new KlarnaAddr(
'always_approved@klarna.com', // email
'', // Telno, only one phone number is needed.
'0762560000', // Cellno
'Testperson-se', // Firstname
'Approved', // Lastname
'', // No care of, C/O.
'Stårgatan 1', // Street
'12345', // Zip Code
'Ankeborg', // City
KlarnaCountry::SE, // Country
null, // HouseNo for German and Dutch customers.
null // House Extension. Dutch customers only.
);
// Next we tell the Klarna instance to use the address in the next order.
$k->setAddress(KlarnaFlags::IS_BILLING, $addr); // Billing / invoice address
$k->setAddress(KlarnaFlags::IS_SHIPPING, $addr); // Shipping / delivery address
/**
* 4. Specify relevant information from your store. (OPTIONAL)
*/
// Set store specific information so you can e.g. search and associate invoices
// with order numbers.
$k->setEstoreInfo(
'175012', // Order ID 1
'1999110234', // Order ID 2
'' // Optional username, email or identifier
);
// If you don't have the order id available at this stage, you can later use the
// method updateOrderNo().
/**
* 5. Set additional information. (OPTIONAL)
*/
/** Comment **/
$k->setComment('A text string stored in the invoice commentary area.');
/** Shipment type **/
// Normal shipment is defaulted, delays the start of invoice expiration/due-date.
$k->setShipmentInfo('delay_adjust', KlarnaFlags::EXPRESS_SHIPMENT);
/**
* 6. Invoke reserveAmount and transmit the data.
*/
try {
// Transmit all the specified data, from the steps above, to Klarna.
$result = $k->reserveAmount(
'4103219202', // PNO (Date of birth for DE and NL).
null, // Gender.
// Amount. -1 specifies that calculation should calculate the amount
// using the goods list
-1,
KlarnaFlags::NO_FLAG, // Flags to affect behavior.
// -1 notes that this is an invoice purchase, for part payment purchase
// you will have a pclass object on which you use getId().
KlarnaPClass::INVOICE
);
//Check the order status
if ($result[1] == KlarnaFlags::PENDING) {
/* 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.
*/
}
// Here we get the reservation number
$rno = $result[0];
echo "status: {$result[1]}\nrno: {$result[0]}\n";
// Order is complete, store it in a database.
} catch(Exception $e) {
// The purchase was denied or something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+51
View File
@@ -0,0 +1,51 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Reserve the OCR numbers.
*/
try {
// Reserve the OCR number(s):
$result = $k->reserveOCR(
1 // Number of OCR numbers you wish to reserve.
);
echo "Result: \n";
foreach ($result as $r) {
echo "{$r}\n";
}
/* $result now contains an array of OCR numbers, proceed accordingly. */
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+57
View File
@@ -0,0 +1,57 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Give a discount on the invoice.
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
$result = $k->returnAmount(
$invNo, // Invoice number
19.99, // Amount given as a discount.
25, // 25% VAT
KlarnaFlags::INC_VAT, // Amount including VAT.
"Family discount" // Description
);
echo "Result: {$result}\n";
/* Discount given, proceed accordingly.
$result contains the invoice number of the discounted invoice.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+52
View File
@@ -0,0 +1,52 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Send an (activated) invoice to the customer.
* (Postal service / normal mail)
*/
// Here you enter the invoice number:
$invNo = '123456';
try {
$result = $k->sendInvoice($invNo);
echo "Result: {$result}\n";
/* Invoice sent to customer, proceed accordingly.
$result contains the invoice number of the sent invoice.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+56
View File
@@ -0,0 +1,56 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Split the reservation.
*/
// Here you enter the reservation number you got from reserveAmount():
$rno = '123456';
try {
// Transmit all the specified data, from the steps above, to Klarna.
$result = $k->splitReservation(
$rno, // Reservation number
99.5, // Amount to be subtracted from the reservation.
KlarnaFlags::NO_FLAG // No specific behaviour.
);
// Split successful, proceed accordingly.
$newRno = $result[0]; // New reservation number
$status = $result[1]; // Status of the new reservation (1 or 2)
echo "New RNO: {$result[0]}\nStatus: {$result[1]}\n";
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+123
View File
@@ -0,0 +1,123 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Add the article(s), shipping and/or handling fee. (OPTIONAL)
*/
// Here we add a normal product to our goods list.
$k->addArticle(
4, // Quantity
"MG200MMS", // Article number
"Matrox G200 MMS", // Article name/title
299.99, // Price
25, // 25% VAT
0, // Discount
KlarnaFlags::INC_VAT // Price is including VAT.
);
// Next we might want to add a shipment fee for the product
$k->addArticle(
1,
"",
"Shipping fee",
14.5,
25,
0,
// Price is including VAT and is shipment fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_SHIPMENT
);
// Lastly, we want to use an invoice/handling fee as well
$k->addArticle(
1,
"",
"Handling fee",
11.5,
25,
0,
// Price is including VAT and is handling/invoice fee
KlarnaFlags::INC_VAT | KlarnaFlags::IS_HANDLING
);
/**
* 3. Create and set the address(es). (OPTIONAL)
*/
// Create the address object and specify the values.
$addr = new KlarnaAddr(
'always_approved@klarna.com', // email
'', // Telno, only one phone number is needed.
'0762560000', // Cellno
'Testperson-se', // Firstname
'Approved', // Lastname
'', // No care of, C/O.
'Stårgatan 1', // Street
'12345', // Zip Code
'Ankeborg', // City
KlarnaCountry::SE, // Country
null, // HouseNo for German and Dutch customers.
null // House Extension. Dutch customers only.
);
// Next we tell the Klarna instance to use the address in the next order.
$k->setAddress(KlarnaFlags::IS_BILLING, $addr); // Billing / invoice address
$k->setAddress(KlarnaFlags::IS_SHIPPING, $addr); // Shipping / delivery address
/**
* 4. Specify relevant information from your store. (OPTIONAL)
*/
// Set store specific information so you can e.g. search and associate invoices
// with order numbers.
$k->setEstoreInfo(
'175012', // Order ID 1
'1999110234', // Order ID 2
'' // Optional username, email or identifier
);
/**
* 5. Make the call to Klarna
*/
// Reservation number
$rno = '123456';
try {
$result = $k->update('1402740');
if ($result) {
echo "Update successful\n";
}
} catch(KlarnaException $e) {
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
@@ -0,0 +1,54 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Update charge amount (shipping fee or handling fee).
*/
// Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
$result = $k->updateChargeAmount(
$invNo, // Invoice number
KlarnaFlags::IS_SHIPMENT, // IS_SHIPMENT or IS_HANDLING
16.7 // Set the shipping fee to 16.7
);
echo "Result: {$result}\n";
/* Charge type updated successfully, proceed accordingly.
$result contains the same invoice number.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+55
View File
@@ -0,0 +1,55 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Update goods quantity.
*/
// Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
$result = $k->updateGoodsQty(
$invNo, // Invoice number
'MG200MMS', // ArtNo must be the same as the one you used in
// addArticle() when you made the addTransaction() call.
2 // New Quantity
);
echo "Result: {$result}\n";
/* Article quantity updated successfully, proceed accordingly.
$result contains the same invoice number.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+53
View File
@@ -0,0 +1,53 @@
<?php
require_once '../Klarna.php';
// Dependencies from http://phpxmlrpc.sourceforge.net/
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc.inc';
require_once dirname(dirname(__FILE__)) .
'/transport/xmlrpc-3.0.0.beta/lib/xmlrpc_wrappers.inc';
/**
* 1. Initialize and setup the Klarna instance.
*/
$k = new Klarna();
$k->config(
123456, // Merchant ID
'sharedSecret', // Shared Secret
KlarnaCountry::SE, // Country
KlarnaLanguage::SV, // Language
KlarnaCurrency::SEK, // Currency
Klarna::BETA, // Server
'json', // PClass Storage
'/srv/pclasses.json', // PClass Storage URI path
true, // SSL
true // Remote logging of response times of xmlrpc calls
);
// OR you can set the config to loads from a file, for example /srv/klarna.json:
// $k->setConfig(new KlarnaConfig('/srv/klarna.json'));
/**
* 2. Update order number / id.
*/
// Here you enter the invoice number you got from addTransaction():
$invNo = '123456';
try {
$result = $k->updateOrderNo(
$invNo, // Invoice Number
'1234' // The order id/number you wish to associated.
);
echo "Result: {$result}\n";
/* Order id is now assicated with the invoice, proceed accordingly.
$result contains the same invoice number.
*/
} catch(Exception $e) {
// Something went wrong, print the message:
echo "{$e->getMessage()} (#{$e->getCode()})\n";
}
+609
View File
@@ -0,0 +1,609 @@
<?php
/**
* KlarnaAddr
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* KlarnaAddr is an object of convenience, to parse and create addresses.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaAddr
{
/**
* Email address.
*
* @var string
*/
protected $email;
/**
* Phone number.
*
* @var string
*/
protected $telno;
/**
* Cellphone number.
*
* @var string
*/
protected $cellno;
/**
* First name.
*
* @var string
*/
protected $fname;
/**
* Last name.
*
* @var string
*/
protected $lname;
/**
* Company name.
*
* @var string
*/
protected $company;
/**
* Care of, C/O.
*
* @var string
*/
protected $careof;
/**
* Street address.
*
* @var string
*/
protected $street;
/**
* Zip code.
*
* @var string
*/
protected $zip;
/**
* City.
*
* @var string
*/
protected $city;
/**
* KlarnaCountry constant
*
* @var int
*/
protected $country;
/**
* House number.
* Only for NL and DE!
*
* @var string
*/
protected $houseNo;
/**
* House extension.
* Only for NL!
*
* @var string
*/
protected $houseExt;
/**
* When using {@link Klarna::getAddresses()} this might be guessed
* depending on type used.
*
* Signifies if address is for a company or a private person.
* If isCompany is null, then it is unknown and will be assumed to
* be a private person.
*
* <b>Note</b>:<br>
* This has no effect on transmitted data.
*
* @var bool|null
*/
public $isCompany = null;
/**
* Class constructor.
*
* Calls the set methods for all arguments.
*
* @param string $email Email address.
* @param string $telno Phone number.
* @param string $cellno Cellphone number.
* @param string $fname First name.
* @param string $lname Last name.
* @param string $careof Care of, C/O.
* @param string $street Street address.
* @param string $zip Zip code.
* @param string $city City.
* @param string|int $country KlarnaCountry constant or two letter code.
* @param string $houseNo House number, only used in DE and NL.
* @param string $houseExt House extension, only used in NL.
*
* @throws KlarnaException
*/
public function __construct(
$email = null, $telno = null, $cellno = null, $fname = null,
$lname = null, $careof = "", $street = null, $zip = null,
$city = null, $country = null, $houseNo = "", $houseExt = ""
) {
//Set all string values to ""
$this->company = "";
$this->telno = "";
$this->careof = "";
$this->cellno = "";
$this->city = "";
$this->email = "";
$this->fname = "";
$this->lname = "";
$this->zip = "";
if ($email !== null) {
$this->setEmail($email);
}
if ($telno !== null) {
$this->setTelno($telno);
}
if ($cellno !== null) {
$this->setCellno($cellno);
}
if ($fname !== null) {
$this->setFirstName($fname);
}
if ($lname !== null) {
$this->setLastName($lname);
}
$this->setCareof($careof);
if ($street !== null) {
$this->setStreet($street);
}
if ($zip !== null) {
$this->setZipCode($zip);
}
if ($city !== null) {
$this->setCity($city);
}
if ($country !== null) {
$this->setCountry($country);
}
$this->setHouseNumber($houseNo);
$this->setHouseExt($houseExt);
}
/**
* Returns the email address.
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Sets the email address.
*
* @param string $email email address
*
* @return void
*/
public function setEmail($email)
{
if (!is_string($email)) {
$email = strval($email);
}
$this->email = $email;
}
/**
* Returns the phone number.
*
* @return string
*/
public function getTelno()
{
return $this->telno;
}
/**
* Sets the phone number.
*
* @param string $telno telno
*
* @return void
*/
public function setTelno($telno)
{
if (!is_string($telno)) {
$telno = strval($telno);
}
$this->telno = $telno;
}
/**
* Returns the cellphone number.
*
* @return string
*/
public function getCellno()
{
return $this->cellno;
}
/**
* Sets the cellphone number.
*
* @param string $cellno mobile number
*
* @return void
*/
public function setCellno($cellno)
{
if (!is_string($cellno)) {
$cellno = strval($cellno);
}
$this->cellno = $cellno;
}
/**
* Returns the first name.
*
* @return string
*/
public function getFirstName()
{
return $this->fname;
}
/**
* Sets the first name.
*
* @param string $fname firstname
*
* @return void
*/
public function setFirstName($fname)
{
if (!is_string($fname)) {
$fname = strval($fname);
}
$this->fname = $fname;
}
/**
* Returns the last name.
*
* @return string
*/
public function getLastName()
{
return $this->lname;
}
/**
* Sets the last name.
*
* @param string $lname lastname
*
* @return void
*/
public function setLastName($lname)
{
if (!is_string($lname)) {
$lname = strval($lname);
}
$this->lname = $lname;
}
/**
* Returns the company name.
*
* @return string
*/
public function getCompanyName()
{
return $this->company;
}
/**
* Sets the company name.
* If the purchase results in a company purchase,
* reference person will be used from first and last name,
* or the value set with {@link Klarna::setReference()}.
*
* @param string $company company name
*
* @see Klarna::setReference
* @return void
*/
public function setCompanyName($company)
{
if (!is_string($company)) {
$company = strval($company);
}
$this->company = $company;
}
/**
* Returns the care of, C/O.
*
* @return string
*/
public function getCareof()
{
return $this->careof;
}
/**
* Sets the care of, C/O.
*
* @param string $careof care of address
*
* @return void
*/
public function setCareof($careof)
{
if (!is_string($careof)) {
$careof = strval($careof);
}
$this->careof = $careof;
}
/**
* Returns the street address.
*
* @return string
*/
public function getStreet()
{
return $this->street;
}
/**
* Sets the street address.
*
* @param string $street street address
*
* @return void
*/
public function setStreet($street)
{
if (!is_string($street)) {
$street = strval($street);
}
$this->street = $street;
}
/**
* Returns the zip code.
*
* @return string
*/
public function getZipCode()
{
return $this->zip;
}
/**
* Sets the zip code.
*
* @param string $zip zip code
*
* @return void
*/
public function setZipCode($zip)
{
if (!is_string($zip)) {
$zip = strval($zip);
}
$zip = str_replace(' ', '', $zip); //remove spaces
$this->zip = $zip;
}
/**
* Returns the city.
*
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* Sets the city.
*
* @param string $city city
*
* @return void
*/
public function setCity($city)
{
if (!is_string($city)) {
$city = strval($city);
}
$this->city = $city;
}
/**
* Returns the country as a integer constant.
*
* @return int {@link KlarnaCountry}
*/
public function getCountry()
{
return $this->country;
}
/**
* Returns the country as a two letter representation.
*
* @throws KlarnaException
* @return string E.g. 'de', 'dk', ...
*/
public function getCountryCode()
{
return KlarnaCountry::getCode($this->country);
}
/**
* Sets the country, use either a two letter representation or the integer
* constant.
*
* @param int $country {@link KlarnaCountry}
*
* @throws KlarnaException
* @return void
*/
public function setCountry($country)
{
if ($country === null) {
throw new Klarna_ArgumentNotSetException('Country');
}
if (is_numeric($country)) {
if (!is_int($country)) {
$country = intval($country);
}
$this->country = $country;
return;
}
if (strlen($country) == 2 || strlen($country) == 3) {
$this->setCountry(KlarnaCountry::fromCode($country));
return;
}
throw new KlarnaException("Failed to set country! ($country)");
}
/**
* Returns the house number.<br>
* Only used in Germany and Netherlands.<br>
*
* @return string
*/
public function getHouseNumber()
{
return $this->houseNo;
}
/**
* Sets the house number.<br>
* Only used in Germany and Netherlands.<br>
*
* @param string $houseNo house number
*
* @return void
*/
public function setHouseNumber($houseNo)
{
if (!is_string($houseNo)) {
$houseNo = strval($houseNo);
}
$this->houseNo = $houseNo;
}
/**
* Returns the house extension.<br>
* Only used in Netherlands.<br>
*
* @return string
*/
public function getHouseExt()
{
return $this->houseExt;
}
/**
* Sets the house extension.<br>
* Only used in Netherlands.<br>
*
* @param string $houseExt house extension
*
* @return void
*/
public function setHouseExt($houseExt)
{
if (!is_string($houseExt)) {
$houseExt = strval($houseExt);
}
$this->houseExt = $houseExt;
}
/**
* Returns an associative array representing this object.
*
* @return array
*/
public function toArray()
{
return array(
'email' => $this->getEmail(),
'telno' => $this->getTelno(),
'cellno' => $this->getCellno(),
'fname' => $this->getFirstName(),
'lname' => $this->getLastName(),
'company' => $this->getCompanyName(),
'careof' => $this->getCareof(),
'street' => $this->getStreet(),
'house_number' => $this->getHouseNumber(),
'house_extension' => $this->getHouseExt(),
'zip' => $this->getZipCode(),
'city' => $this->getCity(),
'country' => $this->getCountry(),
);
}
}
+654
View File
@@ -0,0 +1,654 @@
<?php
/**
* KlarnaCalc
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* KlarnaCalc provides methods to calculate part payment functions.
*
* All rates are yearly rates, but they are calculated monthly. So
* a rate of 9 % is used 0.75% monthly. The first is the one we specify
* to the customers, and the second one is the one added each month to
* the account. The IRR uses the same notation.
*
* The APR is however calculated by taking the monthly rate and raising
* it to the 12 power. This is according to the EU law, and will give
* very large numbers if the $pval is small compared to the $fee and
* the amount of months you repay is small as well.
*
* All functions work in discrete mode, and the time interval is the
* mythical evenly divided month. There is no way to calculate APR in
* days without using integrals and other hairy math. So don't try.
* The amount of days between actual purchase and the first bill can
* of course vary between 28 and 61 days, but all calculations in this
* class assume this time is exactly and that is ok since this will only
* overestimate the APR and all examples in EU law uses whole months as well.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaCalc
{
/**
* This constant tells the irr function when to stop.
* If the calculation error is lower than this the calculation is done.
*
* @var float
*/
protected static $accuracy = 0.01;
/**
* Calculates the midpoint between two points. Used by divide and conquer.
*
* @param float $a point a
* @param float $b point b
*
* @return float
*/
private static function _midpoint($a, $b)
{
return (($a+$b)/2);
}
/**
* npv - Net Present Value
* Calculates the difference between the initial loan to the customer
* and the individual payments adjusted for the inverse of the interest
* rate. The variable we are searching for is $rate and if $pval,
* $payarray and $rate is perfectly balanced this function returns 0.0.
*
* @param float $pval initial loan to customer (in any currency)
* @param array $payarray array of monthly payments from the customer
* @param float $rate interest rate per year in %
* @param int $fromdayone count interest from the first day? yes(1)/no(0)
*
* @return float
*/
private static function _npv($pval, $payarray, $rate, $fromdayone)
{
$month = $fromdayone;
foreach ($payarray as $payment) {
$pval -= $payment / pow(1 + $rate/(12*100.0), $month++);
}
return ($pval);
}
/**
* This function uses divide and conquer to numerically find the IRR,
* Internal Rate of Return. It starts of by trying a low of 0% and a
* high of 100%. If this isn't enough it will double the interval up
* to 1000000%. Note that this is insanely high, and if you try to convert
* an IRR that high to an APR you will get even more insane values,
* so feed this function good data.
*
* Return values: float irr if it was possible to find a rate that gets
* npv closer to 0 than $accuracy.
* int -1 The sum of the payarray is less than the lent
* amount, $pval. Hellooooooo. Impossible.
* int -2 the IRR is way to high, giving up.
*
* This algorithm works in logarithmic time no matter what inputs you give
* and it will come to a good answer within ~30 steps.
*
* @param float $pval initial loan to customer (in any currency)
* @param array $payarray array of monthly payments from the customer
* @param int $fromdayone count interest from the first day? yes(1)/no(0)
*
* @return float
*/
private static function _irr($pval, $payarray, $fromdayone)
{
$low = 0.0;
$high = 100.0;
$lowval = self::_npv($pval, $payarray, $low, $fromdayone);
$highval = self::_npv($pval, $payarray, $high, $fromdayone);
// The sum of $payarray is smaller than $pval, impossible!
if ($lowval > 0.0) {
return (-1);
}
// Standard divide and conquer.
do {
$mid = self::_midpoint($low, $high);
$midval = self::_npv($pval, $payarray, $mid, $fromdayone);
if (abs($midval) < self::$accuracy) {
//we are close enough
return ($mid);
}
if ($highval < 0.0) {
// we are not in range, so double it
$low = $high;
$lowval = $highval;
$high *= 2;
$highval = self::_npv($pval, $payarray, $high, $fromdayone);
} else if ($midval >= 0.0) {
// irr is between low and mid
$high = $mid;
$highval = $midval;
} else {
// irr is between mid and high
$low = $mid;
$lowval = $midval;
}
} while ($high < 1000000);
// bad input, insanely high interest. APR will be INSANER!
return (-2);
}
/**
* IRR is not the same thing as APR, Annual Percentage Rate. The
* IRR is per time period, i.e. 1 month, and the APR is per year,
* and note that that you need to raise to the power of 12, not
* mutliply by 12.
*
* This function turns an IRR into an APR.
*
* If you feed it a value of 100%, yes the APR will be millions!
* If you feed it a value of 9%, it will be 9.3806%.
* That is the nature of this math and you can check the wiki
* page for APR for more info.
*
* @param float $irr Internal Rate of Return, expressed yearly, in %
*
* @return float Annual Percentage Rate, in %
*/
private static function _irr2apr($irr)
{
return (100 * (pow(1 + $irr / (12 * 100.0), 12) - 1));
}
/**
* This is a simplified model of how our paccengine works if
* a client always pays their bills. It adds interest and fees
* and checks minimum payments. It will run until the value
* of the account reaches 0, and return an array of all the
* individual payments. Months is the amount of months to run
* the simulation. Important! Don't feed it too few months or
* the whole loan won't be paid off, but the other functions
* should handle this correctly.
*
* Giving it too many months has no bad effects, or negative
* amount of months which means run forever, but it will stop
* as soon as the account is paid in full.
*
* Depending if the account is a base account or not, the
* payment has to be 1/24 of the capital amount.
*
* The payment has to be at least $minpay, unless the capital
* amount + interest + fee is less than $minpay; in that case
* that amount is paid and the function returns since the client
* no longer owes any money.
*
* @param float $pval initial loan to customer (in any currency)
* @param float $rate interest rate per year in %
* @param float $fee monthly invoice fee
* @param float $minpay minimum monthly payment allowed for this country.
* @param float $payment payment the client to pay each month
* @param int $months amount of months to run (-1 => infinity)
* @param boolean $base is it a base account?
*
* @return array An array of monthly payments for the customer.
*/
private static function _fulpacc(
$pval, $rate, $fee, $minpay, $payment, $months, $base
) {
$bal = $pval;
$payarray = array();
while (($months != 0) && ($bal > self::$accuracy)) {
$interest = $bal * $rate / (100.0 * 12);
$newbal = $bal + $interest + $fee;
if ($minpay >= $newbal || $payment >= $newbal) {
$payarray[] = $newbal;
return $payarray;
}
$newpay = max($payment, $minpay);
if ($base) {
$newpay = max($newpay, $bal/24.0 + $fee + $interest);
}
$bal = $newbal - $newpay;
$payarray[] = $newpay;
$months -= 1;
}
return $payarray;
}
/**
* Calculates how much you have to pay each month if you want to
* pay exactly the same amount each month. The interesting input
* is the amount of $months.
*
* It does not include the fee so add that later.
*
* Return value: monthly payment.
*
* @param float $pval principal value
* @param int $months months to pay of in
* @param float $rate interest rate in % as before
*
* @return float monthly payment
*/
private static function _annuity($pval, $months, $rate)
{
if ($months == 0) {
return $pval;
}
if ($rate == 0) {
return $pval/$months;
}
$p = $rate / (100.0*12);
return $pval * $p / (1 - pow((1+$p), -$months));
}
/**
* Calculate the APR for an annuity given the following inputs.
*
* If you give it bad inputs, it will return negative values.
*
* @param float $pval principal value
* @param int $months months to pay off in
* @param float $rate interest rate in % as before
* @param float $fee monthly fee
* @param float $minpay minimum payment per month
*
* @return float APR in %
*/
private static function _aprAnnuity($pval, $months, $rate, $fee, $minpay)
{
$payment = self::_annuity($pval, $months, $rate) + $fee;
if ($payment < 0) {
return $payment;
}
$payarray = self::_fulpacc(
$pval, $rate, $fee, $minpay, $payment, $months, false
);
$apr = self::_irr2apr(self::_irr($pval, $payarray, 1));
return $apr;
}
/**
* Grabs the array of all monthly payments for specified PClass.
*
* <b>Flags can be either</b>:<br>
* {@link KlarnaFlags::CHECKOUT_PAGE}<br>
* {@link KlarnaFlags::PRODUCT_PAGE}<br>
*
* @param float $sum The sum for the order/product.
* @param KlarnaPClass $pclass KlarnaPClass used to calculate the APR.
* @param int $flags Checkout or Product page.
*
* @throws KlarnaException
* @return array An array of monthly payments.
*/
private static function _getPayArray($sum, $pclass, $flags)
{
$monthsfee = 0;
if ($flags === KlarnaFlags::CHECKOUT_PAGE) {
$monthsfee = $pclass->getInvoiceFee();
}
$startfee = 0;
if ($flags === KlarnaFlags::CHECKOUT_PAGE) {
$startfee = $pclass->getStartFee();
}
//Include start fee in sum
$sum += $startfee;
$base = ($pclass->getType() === KlarnaPClass::ACCOUNT);
$lowest = self::get_lowest_payment_for_account($pclass->getCountry());
if ($flags == KlarnaFlags::CHECKOUT_PAGE) {
$minpay = ($pclass->getType() === KlarnaPClass::ACCOUNT) ? $lowest : 0;
} else {
$minpay = 0;
}
$payment = self::_annuity(
$sum,
$pclass->getMonths(),
$pclass->getInterestRate()
);
//Add monthly fee
$payment += $monthsfee;
return self::_fulpacc(
$sum,
$pclass->getInterestRate(),
$monthsfee,
$minpay,
$payment,
$pclass->getMonths(),
$base
);
}
/**
* Calculates APR for the specified values.<br>
* Result is rounded with two decimals.<br>
*
* <b>Flags can be either</b>:<br>
* {@link KlarnaFlags::CHECKOUT_PAGE}<br>
* {@link KlarnaFlags::PRODUCT_PAGE}<br>
*
* @param float $sum The sum for the order/product.
* @param KlarnaPClass $pclass KlarnaPClass used to calculate the APR.
* @param int $flags Checkout or Product page.
* @param int $free Number of free months.
*
* @throws KlarnaException
* @return float APR in %
*/
public static function calc_apr($sum, $pclass, $flags, $free = 0)
{
if (!is_numeric($sum)) {
throw new Klarna_InvalidTypeException('sum', 'numeric');
}
if (is_numeric($sum) && (!is_int($sum) || !is_float($sum))) {
$sum = floatval($sum);
}
if (!($pclass instanceof KlarnaPClass)) {
throw new Klarna_InvalidTypeException('pclass', 'KlarnaPClass');
}
if (!is_numeric($free)) {
throw new Klarna_InvalidTypeException('free', 'integer');
}
if (is_numeric($free) && !is_int($free)) {
$free = intval($free);
}
if ($free < 0) {
throw new KlarnaException(
'Error in ' . __METHOD__ .
': Number of free months must be positive or zero!'
);
}
if (is_numeric($flags) && !is_int($flags)) {
$flags = intval($flags);
}
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
);
}
$monthsfee = 0;
if ($flags === KlarnaFlags::CHECKOUT_PAGE) {
$monthsfee = $pclass->getInvoiceFee();
}
$startfee = 0;
if ($flags === KlarnaFlags::CHECKOUT_PAGE) {
$startfee = $pclass->getStartFee();
}
//Include start fee in sum
$sum += $startfee;
$lowest = self::get_lowest_payment_for_account($pclass->getCountry());
if ($flags == KlarnaFlags::CHECKOUT_PAGE) {
$minpay = ($pclass->getType() === KlarnaPClass::ACCOUNT) ? $lowest : 0;
} else {
$minpay = 0;
}
//add monthly fee
$payment = self::_annuity(
$sum,
$pclass->getMonths(),
$pclass->getInterestRate()
) + $monthsfee;
$type = $pclass->getType();
switch($type) {
case KlarnaPClass::CAMPAIGN:
case KlarnaPClass::ACCOUNT:
return round(
self::_aprAnnuity(
$sum, $pclass->getMonths(),
$pclass->getInterestRate(),
$pclass->getInvoiceFee(),
$minpay
),
2
);
case KlarnaPClass::SPECIAL:
throw new Klarna_PClassException(
'Method is not available for SPECIAL pclasses'
);
case KlarnaPClass::FIXED:
throw new Klarna_PClassException(
'Method is not available for FIXED pclasses'
);
default:
throw new Klarna_PClassException(
'Unknown PClass type! ('.$type.')'
);
}
}
/**
* Calculates the total credit purchase cost.<br>
* The result is rounded up, depending on the pclass country.<br>
*
* <b>Flags can be either</b>:<br>
* {@link KlarnaFlags::CHECKOUT_PAGE}<br>
* {@link KlarnaFlags::PRODUCT_PAGE}<br>
*
* @param float $sum The sum for the order/product.
* @param KlarnaPClass $pclass PClass used to calculate total credit cost.
* @param int $flags Checkout or Product page.
*
* @throws KlarnaException
* @return float Total credit purchase cost.
*/
public static function total_credit_purchase_cost($sum, $pclass, $flags)
{
if (!is_numeric($sum)) {
throw new Klarna_InvalidTypeException('sum', 'numeric');
}
if (is_numeric($sum) && (!is_int($sum) || !is_float($sum))) {
$sum = floatval($sum);
}
if (!($pclass instanceof KlarnaPClass)) {
throw new Klarna_InvalidTypeException('pclass', 'KlarnaPClass');
}
if (is_numeric($flags) && !is_int($flags)) {
$flags = intval($flags);
}
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
);
}
$payarr = self::_getPayArray($sum, $pclass, $flags);
$credit_cost = 0;
foreach ($payarr as $pay) {
$credit_cost += $pay;
}
return self::pRound($credit_cost, $pclass->getCountry());
}
/**
* Calculates the monthly cost for the specified pclass.
* The result is rounded up to the correct value depending on the
* pclass country.<br>
*
* Example:<br>
* <ul>
* <li>In product view, round monthly cost with max 0.5 or 0.1
* depending on currency.<br>
* <ul>
* <li>10.50 SEK rounds to 11 SEK</li>
* <li>10.49 SEK rounds to 10 SEK</li>
* <li> 8.55 EUR rounds to 8.6 EUR</li>
* <li> 8.54 EUR rounds to 8.5 EUR</li>
* </ul></li>
* <li>
* In checkout, round the monthly cost to have 2 decimals.<br>
* For example 10.57 SEK/per månad
* </li>
* </ul>
*
* <b>Flags can be either</b>:<br>
* {@link KlarnaFlags::CHECKOUT_PAGE}<br>
* {@link KlarnaFlags::PRODUCT_PAGE}<br>
*
* @param int $sum The sum for the order/product.
* @param KlarnaPClass $pclass PClass used to calculate monthly cost.
* @param int $flags Checkout or product page.
*
* @throws KlarnaException
* @return float The monthly cost.
*/
public static function calc_monthly_cost($sum, $pclass, $flags)
{
if (!is_numeric($sum)) {
throw new Klarna_InvalidTypeException('sum', 'numeric');
}
if (is_numeric($sum) && (!is_int($sum) || !is_float($sum))) {
$sum = floatval($sum);
}
if (!($pclass instanceof KlarnaPClass)) {
throw new Klarna_InvalidTypeException('pclass', 'KlarnaPClass');
}
if (is_numeric($flags) && !is_int($flags)) {
$flags = intval($flags);
}
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
);
}
$payarr = self::_getPayArray($sum, $pclass, $flags);
$value = 0;
if (isset($payarr[0])) {
$value = $payarr[0];
}
if (KlarnaFlags::CHECKOUT_PAGE == $flags) {
return round($value, 2);
}
return self::pRound($value, $pclass->getCountry());
}
/**
* Returns the lowest monthly payment for Klarna Account.
*
* @param int $country KlarnaCountry constant.
*
* @throws KlarnaException
* @return int|float Lowest monthly payment.
*/
public static function get_lowest_payment_for_account($country)
{
$country = KlarnaCountry::getCode($country);
switch (strtoupper($country)) {
case "SE":
return 50.0;
case "NO":
return 95.0;
case "FI":
return 8.95;
case "DK":
return 89.0;
case "DE":
case "NL":
case "AT":
return 6.95;
default:
throw new KlarnaException("Invalid country {$country}");
}
}
/**
* Rounds a value depending on the specified country.
*
* @param int|float $value The value to be rounded.
* @param int $country KlarnaCountry constant.
*
* @return float|int
*/
public static function pRound($value, $country)
{
$multiply = 1; //Round to closest integer
$country = KlarnaCountry::getCode($country);
switch($country) {
case "FI":
case "DE":
case "NL":
case "AT":
$multiply = 10; //Round to closest decimal
break;
}
return floor(($value*$multiply)+0.5)/$multiply;
}
}
+176
View File
@@ -0,0 +1,176 @@
<?php
/**
* KlarnaConfig
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Configuration class for the Klarna instance.
*
* KlarnaConfig stores added fields in JSON, it also prepends.<br>
* Loads/saves specified file, or default file, if {@link KlarnaConfig::$store}
* is set to true.<br>
*
* You add settings using the ArrayAccess:<br>
* $arr['field'] = $val or $arr->offsetSet('field', $val);<br>
*
* Available settings are:<br>
* eid - Merchant ID (int)
* secret - Shared secret (string)
* country - Country constant or code (int|string)
* language - Language constant or code (int|string)
* currency - Currency constant or code (int|string)
* mode - Klarna::BETA or Klarna::LIVE
* ssl - Use HTTPS or HTTP. (bool)
* candice - Status reporting to Klarna, to detect erroneous
* integrations, etc. (bool)
* pcStorage - Storage module, e.g. 'json'
* pcURI - URI to where the PClasses are stored, e.g.
* '/srv/shop/pclasses.json'
* xmlrpcDebug - XMLRPC debugging (bool)
* debug - Normal debugging (bool)
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaConfig implements ArrayAccess
{
/**
* An array containing all the options for this config.
*
* @ignore Do not show in PHPDoc.
* @var array
*/
protected $options;
/**
* If set to true, saves the config.
*
* @var bool
*/
public static $store = true;
/**
* URI to the config file.
*
* @ignore Do not show in PHPDoc.
* @var string
*/
protected $file;
/**
* Class constructor
*
* Loads specified file, or default file,
* if {@link KlarnaConfig::$store} is set to true.
*
* @param string $file URI to config file, e.g. ./config.json
*/
public function __construct($file = null)
{
$this->options = array();
if ($file) {
$this->file = $file;
if (is_readable($this->file)) {
$this->options = json_decode(
file_get_contents(
$this->file
), true
);
}
}
}
/**
* Clears the config.
*
* @return void
*/
public function clear()
{
$this->options = array();
}
/**
* Class destructor
*
* Saves specified file, or default file,
* if {@link KlarnaConfig::$store} is set to true.
*/
public function __destruct()
{
if (self::$store && $this->file) {
if ((!file_exists($this->file)
&& is_writable(dirname($this->file)))
|| is_writable($this->file)
) {
file_put_contents($this->file, json_encode($this->options));
}
}
}
/**
* Returns true whether the field exists.
*
* @param mixed $offset field
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->options[$offset]);
}
/**
* Used to get the value of a field.
*
* @param mixed $offset field
*
* @return mixed
*/
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
return null;
}
return $this->options[$offset];
}
/**
* Used to set a value to a field.
*
* @param mixed $offset field
* @param mixed $value value
*
* @return void
*/
public function offsetSet($offset, $value)
{
$this->options[$offset] = $value;
}
/**
* Removes the specified field.
*
* @param mixed $offset field
*
* @return void
*/
public function offsetUnset($offset)
{
unset($this->options[$offset]);
}
}
+573
View File
@@ -0,0 +1,573 @@
<?php
/**
* KlarnaPClass
*
* PHP Version 5.3
*
* @ignore Do not show in PHPDoc.
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* PClass object used for part payment.
*
* PClasses are used in conjunction with KlarnaCalc to determine part payment costs.
*
* @ignore Do not show in PHPDoc.
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class KlarnaPClass
{
/**
* Invoice type/identifier, used for invoice purchases.
*
* @var int
*/
const INVOICE = -1;
/**
* Campaign type pclass.
*
* @var int
*/
const CAMPAIGN = 0;
/**
* Account type pclass.
*
* @var int
*/
const ACCOUNT = 1;
/**
* Special campaign type pclass.<br>
* "Buy now, pay in x month"<br>
*
* @var int
*/
const SPECIAL = 2;
/**
* Fixed campaign type pclass
*
* @var int
*/
const FIXED = 3;
/**
* Delayed campaign type pclass.<br>
* "Pay in X months"<br>
*
* @var int
*/
const DELAY = 4;
/**
* Klarna Mobile type pclass
*
* @var int
*/
const MOBILE = 5;
/**
* The description for this PClass.
* HTML entities for special characters.
*
* @ignore Do not show in PHPDoc.
* @var string
*/
protected $description;
/**
* Number of months for this PClass.
*
* @ignore Do not show in PHPDoc.
* @var int
*/
protected $months;
/**
* PClass starting fee.
*
* @ignore Do not show in PHPDoc.
* @var float
*/
protected $startFee;
/**
* PClass invoice/handling fee.
*
* @ignore Do not show in PHPDoc.
* @var float
*/
protected $invoiceFee;
/**
* PClass interest rate.
*
* @ignore Do not show in PHPDoc.
* @var float
*/
protected $interestRate;
/**
* PClass minimum amount for purchase/product.
*
* @ignore Do not show in PHPDoc.
* @var float
*/
protected $minAmount;
/**
* PClass country.
*
* @ignore Do not show in PHPDoc.
* @see KlarnaCountry
* @var int
*/
protected $country;
/**
* PClass ID.
*
* @ignore Do not show in PHPDoc.
* @var int
*/
protected $id;
/**
* PClass type.
*
* @see self::CAMPAIGN
* @see self::ACCOUNT
* @see self::SPECIAL
* @see self::FIXED
* @see self::DELAY
* @see self::MOBILE
*
* @ignore Do not show in PHPDoc.
* @var int
*/
protected $type;
/**
* Expire date / valid until date as unix timestamp.<br>
* Compare it with e.g. $_SERVER['REQUEST_TIME'].<br>
*
* @ignore Do not show in PHPDoc.
* @var int
*/
protected $expire;
/**
* Merchant ID / Estore ID.
*
* @ignore Do not show in PHPDoc.
* @var int
*/
protected $eid;
/**
* Class constructor
*
* The optional array argument can be:
* array (
* 0 = eid (this is created in the API)
* 1 = id number
* 2 = description
* 3 = amount of months for part payment
* 4 = start fee
* 5 = invoice fee
* 6 = interest rate
* 7 = minimum purchase amount for pclass
* 8 = country
* 9 = type
* (This is used to determine which pclass-id is an account and
* a campaign, 0 = campaign, 1 = account, 2 = special campaign
* i.e. x-mas campaign)
* 10 = expire date
*
* @param null|array $arr Associative or numeric array of PClass data.
*/
public function __construct($arr = null)
{
if (!is_array($arr) || count($arr) < 11) {
return;
}
foreach ($arr as $key => $val) {
switch($key) {
case "0":
case "eid":
$this->setEid($val);
break;
case "1":
case "id":
$this->setId($val);
break;
case "2":
case "desc":
case "description":
$this->setDescription($val);
break;
case "3":
case "months":
$this->setMonths($val);
break;
case "4":
case "startfee":
$this->setStartFee($val);
break;
case "5":
case "invoicefee":
$this->setInvoiceFee($val);
break;
case "6":
case "interestrate":
$this->setInterestRate($val);
break;
case "7":
case "minamount":
$this->setMinAmount($val);
break;
case "8":
case "country":
$this->setCountry($val);
break;
case "9":
case "type":
$this->setType($val);
break;
case "10":
case "expire":
$this->setExpire($val);
break;
default:
//Array index not supported.
break;
}
}
}
/**
* Returns an associative array mirroring this PClass.
*
* @return array
*/
public function toArray()
{
return array(
'eid' => $this->eid,
'id' => $this->id,
'description' => $this->description,
'months' => $this->months,
'startfee' => $this->startFee,
'invoicefee' => $this->invoiceFee,
'interestrate' => $this->interestRate,
'minamount' => $this->minAmount,
'country' => $this->country,
'type' => $this->type,
'expire' => $this->expire
);
}
/**
* Sets the descriptiton, converts to HTML entities.
*
* @param string $description PClass description.
*
* @return void
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Sets the number of months.
*
* @param int $months Number of months.
*
* @return void
*/
public function setMonths($months)
{
$this->months = intval($months);
}
/**
* Sets the starting fee.
*
* @param float $startFee Starting fee.
*
* @return void
*/
public function setStartFee($startFee)
{
$this->startFee = floatval($startFee);
}
/**
* Sets the invoicing/handling fee.
*
* @param float $invoiceFee Invoicing fee.
*
* @return void
*/
public function setInvoiceFee($invoiceFee)
{
$this->invoiceFee = floatval($invoiceFee);
}
/**
* Sets the interest rate.
*
* @param float $interestRate Interest rate.
*
* @return void
*/
public function setInterestRate($interestRate)
{
$this->interestRate = floatval($interestRate);
}
/**
* Sets the Minimum amount to use this PClass.
*
* @param float $minAmount Minimum amount.
*
* @return void
*/
public function setMinAmount($minAmount)
{
$this->minAmount = floatval($minAmount);
}
/**
* Sets the country for this PClass.
*
* @param int $country {@link KlarnaCountry} constant.
*
* @see KlarnaCountry
*
* @return void
*/
public function setCountry($country)
{
$this->country = intval($country);
}
/**
* Sets the ID for this pclass.
*
* @param int $id PClass identifier.
*
* @return void
*/
public function setId($id)
{
$this->id = intval($id);
}
/**
* Sets the type for this pclass.
*
* @param int $type PClass type identifier.
*
* @see self::CAMPAIGN
* @see self::ACCOUNT
* @see self::SPECIAL
* @see self::FIXED
* @see self::DELAY
* @see self::MOBILE
*
* @return void
*/
public function setType($type)
{
$this->type = intval($type);
}
/**
* Returns the ID for this PClass.
*
* @return int PClass identifier.
*/
public function getId()
{
return $this->id;
}
/**
* Returns this PClass's type.
*
* @see self::CAMPAIGN
* @see self::ACCOUNT
* @see self::SPECIAL
* @see self::FIXED
* @see self::DELAY
* @see self::MOBILE
*
* @return int PClass type identifier.
*/
public function getType()
{
return $this->type;
}
/**
* Returns the Merchant ID or Estore ID connected to this PClass.
*
* @return int
*/
public function getEid()
{
return $this->eid;
}
/**
* Merchant ID or Estore ID connected to this PClass.
*
* @param int $eid Merchant ID.
*
* @return void
*/
public function setEid($eid)
{
$this->eid = intval($eid);
}
/**
* Checks whether this PClass is valid.
*
* @param int $now Unix timestamp
*
* @return bool
*/
public function isValid($now = null)
{
if ($this->expire == null
|| $this->expire == '-'
|| $this->expire <= 0
) {
//No expire, or unset? assume valid.
return true;
}
if ($now === null || !is_numeric($now)) {
$now = time();
}
//If now is before expire, it is still valid.
return ($now > $this->expire) ? false : true;
}
/**
* Returns the valid until/expire date unix timestamp.
*
* @return int
*/
public function getExpire()
{
return $this->expire;
}
/**
* Sets the valid until/expire date unix timestamp.
*
* @param int $expire unix timestamp for expire
*
* @return void
*/
public function setExpire($expire)
{
$this->expire = $expire;
}
/**
* Returns the description for this PClass.
*
* <b>Note</b>:<br>
* Encoded with HTML entities.
*
* @return string PClass description.
*/
public function getDescription()
{
return $this->description;
}
/**
* Returns the number of months for this PClass.
*
* @return int Number of months.
*/
public function getMonths()
{
return $this->months;
}
/**
* Returns the starting fee for this PClass.
*
* @return float Starting fee.
*/
public function getStartFee()
{
return $this->startFee;
}
/**
* Returns the invoicing/handling fee for this PClass.
*
* @return float Invoicing fee.
*/
public function getInvoiceFee()
{
return $this->invoiceFee;
}
/**
* Returns the interest rate for this PClass.
*
* @return float Interest rate.
*/
public function getInterestRate()
{
return $this->interestRate;
}
/**
* Returns the minimum order/product amount for which this PClass is allowed.
*
* @return float Minimum amount to use this PClass.
*/
public function getMinAmount()
{
return $this->minAmount;
}
/**
* Returns the country related to this PClass.
*
* @see KlarnaCountry
* @return int {@link KlarnaCountry} constant.
*/
public function getCountry()
{
return $this->country;
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
/**
* JsonStorage
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Include the {@link PCStorage} interface.
*/
require_once 'storage.intf.php';
/**
* JSON storage class for KlarnaPClass
*
* This class is an JSON implementation of the PCStorage interface.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class JSONStorage extends PCStorage
{
/**
* return the name of the storage type
*
* @return string
*/
public function getName()
{
return "json";
}
/**
* Checks if the file is writeable, readable or if the directory is.
*
* @param string $jsonFile json file that holds the pclasses
*
* @throws error
* @return void
*/
protected function checkURI($jsonFile)
{
//If file doesn't exist, check the directory.
if (!file_exists($jsonFile)) {
$jsonFile = dirname($jsonFile);
}
if (!is_writable($jsonFile)) {
throw new Klarna_FileNotWritableException($jsonFile);
}
if (!is_readable($jsonFile)) {
throw new Klarna_FileNotReadableException($jsonFile);
}
}
/**
* Clear the pclasses
*
* @param string $uri uri to file to clear
*
* @throws KlarnaException
* @return void
*/
public function clear($uri)
{
$this->checkURI($uri);
unset($this->pclasses);
if (file_exists($uri)) {
unlink($uri);
}
}
/**
* Load pclasses from file
*
* @param string $uri uri to file to load
*
* @throws KlarnaException
* @return void
*/
public function load($uri)
{
$this->checkURI($uri);
if (!file_exists($uri)) {
//Do not fail, if file doesn't exist.
return;
}
$arr = json_decode(file_get_contents($uri), true);
if (count($arr) == 0) {
return;
}
foreach ($arr as $pclasses) {
if (count($pclasses) == 0) {
continue;
}
foreach ($pclasses as $pclass) {
$this->addPClass(new KlarnaPClass($pclass));
}
}
}
/**
* Save pclasses to file
*
* @param string $uri uri to file to save
*
* @throws KlarnaException
* @return void
*/
public function save($uri)
{
try {
$this->checkURI($uri);
$output = array();
foreach ($this->pclasses as $eid => $pclasses) {
foreach ($pclasses as $pclass) {
if (!isset($output[$eid])) {
$output[$eid] = array();
}
$output[$eid][] = $pclass->toArray();
}
}
if (count($this->pclasses) > 0) {
file_put_contents($uri, json_encode($output));
} else {
file_put_contents($uri, "");
}
} catch(Exception $e) {
throw new KlarnaException($e->getMessage());
}
}
}
+335
View File
@@ -0,0 +1,335 @@
<?php
/**
* MySQL Storage
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Include the {@link PCStorage} interface.
*/
require_once 'storage.intf.php';
/**
* MySQL storage class for KlarnaPClass
*
* This class is an MySQL implementation of the PCStorage interface.<br>
* Config field pcURI needs to match format:
* user:passwd@addr:port/dbName.dbTable<br>
* Port can be omitted.<br>
*
* <b>Acceptable characters</b>:<br>
* Username: [A-Za-z0-9_]<br>
* Password: [A-Za-z0-9_]<br>
* Address: [A-Za-z0-9_.]<br>
* Port: [0-9]<br>
* DB name: [A-Za-z0-9_]<br>
* DB table: [A-Za-z0-9_]<br>
*
* To allow for more special characters, and to avoid having<br>
* a regular expression that is too hard to understand, you can<br>
* use an associative array:<br>
* <code>
* array(
* "user" => "myuser",
* "passwd" => "mypass",
* "dsn" => "localhost",
* "db" => "mydatabase",
* "table" => "mytable"
* );
* </code>
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class MySQLStorage extends PCStorage
{
/**
* Database name.
*
* @var string
*/
protected $dbName;
/**
* Database table.
*
* @var string
*/
protected $dbTable;
/**
* Database address.
*
* @var string
*/
protected $addr;
/**
* Database username.
*
* @var string
*/
protected $user;
/**
* Database password.
*
* @var string
*/
protected $passwd;
/**
* MySQL DB link resource.
*
* @var resource
*/
protected $link;
/**
* return the name of the storage type
*
* @return string
*/
public function getName()
{
return "mysql";
}
/**
* Connects to the DB and checks if DB and table exists.
*
* @throws KlarnaException
* @return void
*/
protected function connect()
{
$this->link = mysql_connect($this->addr, $this->user, $this->passwd);
if ($this->link === false) {
throw new Klarna_DatabaseException(
'Failed to connect to database! ('.mysql_error().')'
);
}
if (!mysql_query(
"CREATE DATABASE IF NOT EXISTS `{$this->dbName}`",
$this->link
)
) {
throw new Klarna_DatabaseException(
'Failed to create! ('.mysql_error().')'
);
}
$create = mysql_query(
"CREATE TABLE IF NOT EXISTS `{$this->dbName}`.`{$this->dbTable}` (
`eid` int(10) unsigned NOT NULL,
`id` int(10) unsigned NOT NULL,
`type` tinyint(4) NOT NULL,
`description` varchar(255) NOT NULL,
`months` int(11) NOT NULL,
`interestrate` decimal(11,2) NOT NULL,
`invoicefee` decimal(11,2) NOT NULL,
`startfee` decimal(11,2) NOT NULL,
`minamount` decimal(11,2) NOT NULL,
`country` int(11) NOT NULL,
`expire` int(11) NOT NULL,
KEY `id` (`id`)
)", $this->link
);
if (!$create) {
throw new Klarna_DatabaseException(
'Table not existing, failed to create! ('.mysql_error().')'
);
}
}
/**
* Splits the URI in format: user:passwd@addr/dbName.dbTable<br>
*
* To allow for more special characters, and to avoid having<br>
* a regular expression that is too hard to understand, you can<br>
* use an associative array:<br>
* <code>
* array(
* "user" => "myuser",
* "passwd" => "mypass",
* "dsn" => "localhost",
* "db" => "mydatabase",
* "table" => "mytable"
* );
* </code>
*
* @param string|array $uri Specified URI to database and table.
*
* @throws KlarnaException
* @return void
*/
protected function splitURI($uri)
{
if (is_array($uri)) {
$this->user = $uri['user'];
$this->passwd = $uri['passwd'];
$this->addr = $uri['dsn'];
$this->dbName = $uri['db'];
$this->dbTable = $uri['table'];
} else if (preg_match(
'/^([\w-]+):([\w-]+)@([\w\.-]+|[\w\.-]+:[\d]+)\/([\w-]+).([\w-]+)$/',
$uri,
$arr
) === 1
) {
/*
[0] => user:passwd@addr/dbName.dbTable
[1] => user
[2] => passwd
[3] => addr
[4] => dbName
[5] => dbTable
*/
if (count($arr) != 6) {
throw new Klarna_DatabaseException(
'URI is invalid! Missing field or invalid characters used!'
);
}
$this->user = $arr[1];
$this->passwd = $arr[2];
$this->addr = $arr[3];
$this->dbName = $arr[4];
$this->dbTable = $arr[5];
} else {
throw new Klarna_DatabaseException(
'URI to MySQL is not valid! ( user:passwd@addr/dbName.dbTable )'
);
}
}
/**
* Load pclasses
*
* @param string $uri pclass uri
*
* @throws KlarnaException
* @return void
*/
public function load($uri)
{
$this->splitURI($uri);
$this->connect();
$result = mysql_query(
"SELECT * FROM `{$this->dbName}`.`{$this->dbTable}`",
$this->link
);
if ($result === false) {
throw new Klarna_DatabaseException(
'SELECT query failed! ('.mysql_error().')'
);
}
while ($row = mysql_fetch_assoc($result)) {
$this->addPClass(new KlarnaPClass($row));
}
}
/**
* Save pclasses to database
*
* @param string $uri pclass uri
*
* @throws KlarnaException
* @return void
*/
public function save($uri)
{
$this->splitURI($uri);
$this->connect();
if (!is_array($this->pclasses) || count($this->pclasses) == 0) {
return;
}
foreach ($this->pclasses as $pclasses) {
foreach ($pclasses as $pclass) {
//Remove the pclass if it exists.
mysql_query(
"DELETE FROM `{$this->dbName}`.`{$this->dbTable}`
WHERE `id` = '{$pclass->getId()}'
AND `eid` = '{$pclass->getEid()}'"
);
//Insert it again.
$result = mysql_query(
"INSERT INTO `{$this->dbName}`.`{$this->dbTable}`
(`eid`,
`id`,
`type`,
`description`,
`months`,
`interestrate`,
`invoicefee`,
`startfee`,
`minamount`,
`country`,
`expire`
)
VALUES
('{$pclass->getEid()}',
'{$pclass->getId()}',
'{$pclass->getType()}',
'{$pclass->getDescription()}',
'{$pclass->getMonths()}',
'{$pclass->getInterestRate()}',
'{$pclass->getInvoiceFee()}',
'{$pclass->getStartFee()}',
'{$pclass->getMinAmount()}',
'{$pclass->getCountry()}',
'{$pclass->getExpire()}')", $this->link
);
if ($result === false) {
throw new Klarna_DatabaseException(
'INSERT INTO query failed! ('.mysql_error().')'
);
}
}
}
}
/**
* Clear the pclasses
*
* @param string $uri pclass uri
*
* @throws KlarnaException
* @return void
*/
public function clear($uri)
{
try {
$this->splitURI($uri);
unset($this->pclasses);
$this->connect();
mysql_query(
"DELETE FROM `{$this->dbName}`.`{$this->dbTable}`",
$this->link
);
} catch(Exception $e) {
throw new Klarna_DatabaseException(
$e->getMessage(), $e->getCode()
);
}
}
}
+473
View File
@@ -0,0 +1,473 @@
<?php
/**
* SQL Storage
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Include the {@link PCStorage} interface.
*/
require_once 'storage.intf.php';
/**
* SQL storage class for KlarnaPClass
*
* This class is an MySQL implementation of the PCStorage interface.<br>
* Config field pcURI needs to match format:
* user:passwd@addr:port/dbName.dbTable<br>
* Port can be omitted.<br>
*
* <b>Acceptable characters</b>:<br>
* Username: [A-Za-z0-9_]<br>
* Password: [A-Za-z0-9_]<br>
* Address: [A-Za-z0-9_.]<br>
* Port: [0-9]<br>
* DB name: [A-Za-z0-9_]<br>
* DB table: [A-Za-z0-9_]<br>
*
* To allow for more special characters, and to avoid having<br>
* a regular expression that is too hard to understand, you can<br>
* use an associative array:<br>
* <code>
* array(
* "user" => "myuser",
* "passwd" => "mypass",
* "dsn" => "localhost",
* "db" => "mydatabase",
* "table" => "mytable"
* );
* </code>
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class SQLStorage extends PCStorage
{
/**
* Database name.
*
* @var string
*/
protected $dbName;
/**
* Database table.
*
* @var string
*/
protected $dbTable;
/**
* Database address.
*
* @var string
*/
protected $addr;
/**
* PDO DSN notation.
*
* @var string
*/
protected $dsn;
/**
* Database username.
*
* @var string
*/
protected $user;
/**
* Database password.
*
* @var string
*/
protected $passwd;
/**
* PDO DB link resource.
*
* @var PDO
*/
protected $pdo;
/**
* return the name of the storage type
*
* @return string
*/
public function getName()
{
return "sql";
}
/**
* Splits the URI for the following formats:<br>
* user:passwd@addr/dbName.dbTable (assumes MySQL)<br>
* user:password@pdo:dsn/dbName.dbTable<br>
*
* To allow for more special characters, and to avoid having<br>
* a regular expression that is too hard to understand, you can<br>
* use an associative array:<br>
* <code>
* array(
* "user" => "myuser",
* "passwd" => "mypass",
* "dsn" => "localhost",
* "db" => "mydatabase",
* "table" => "mytable"
* );
* </code>
*
* @param string|array $uri Specified URI to database and table.
*
* @throws KlarnaException
* @return void
*/
protected function splitURI($uri)
{
/* If you want to have some characters that would make the
regexp too complex, you can use an array as input instead. */
if (is_array($uri)) {
$this->user = $uri['user'];
$this->passwd = $uri['passwd'];
$this->dsn = $uri['dsn'];
$this->dbName = $uri['db'];
$this->dbTable = $uri['table'];
return array(
$uri,
$this->user,
$this->passwd,
$this->dsn,
$this->dbName,
$this->dbTable
);
}
$pdo_rex
= '/^([\w-]+):([\w-]+)@pdo:([\w.,:;\/ \\\t=\(\){}\*-]+)\/([\w-]+)'.
'.([\w-]+)$/';
$pcuri_rex
= '/^([\w-]+):([\w-]+)@([\w\.-]+|[\w\.-]+:[\d]+|[\w\.-]+:'.
'[\w\.\/-]+|:[\w\.\/-]+)\/([\w-]+).([\w-]+)$/';
$arr = null;
if (preg_match($pdo_rex, $uri, $arr) === 1) {
/*
* [0] => user:password@pdo:dsn/dbName.dbTable
* [1] => user
* [2] => passwd
* [3] => dsn
* [4] => dbName
* [5] => dbTable
*/
if (count($arr) != 6) {
throw new Klarna_DatabaseException(
'URI is invalid! Missing field or invalid characters used!'
);
}
$this->user = $arr[1];
$this->passwd = $arr[2];
$this->dsn = $arr[3];
$this->dbName = $arr[4];
$this->dbTable = $arr[5];
} else if (preg_match($pcuri_rex, $uri, $arr) === 1) {
//user:pass@127.0.0.1:3306/dbName.dbTable
//user:pass@localhost:/tmp/mysql.sock/dbName.dbTable
/*
* [0] => user:passwd@addr/dbName.dbTable
* [1] => user
* [2] => passwd
* [3] => addr
* [4] => dbName
* [5] => dbTable
*/
if (count($arr) != 6) {
throw new Klarna_DatabaseException(
'URI is invalid! Missing field or invalid characters used!'
);
}
$this->user = $arr[1];
$this->passwd = $arr[2];
$this->addr = $arr[3];
$this->port = 3306;
if (preg_match(
'/^([0-9.]+(:([0-9]+))?)$/', $this->addr, $tmp
) === 1
) {
if (isset($tmp[3])) {
$this->port = $tmp[3];
}
}
$this->dbName = $arr[4];
$this->dbTable = $arr[5];
$this->dsn = "mysql:host={$this->addr};port={$this->port};";
} else {
throw new Klarna_DatabaseException(
'URI to SQL is not valid! ( user:passwd@addr/dbName.dbTable )'
);
}
return $arr;
}
/**
* Grabs the PDO connection to the database, specified by the URI.
*
* @param string $uri pclass uri
*
* @return void
* @throws KlarnaException
*/
protected function getConnection($uri)
{
if ($this->pdo) {
return; //Already have a connection
}
$this->splitURI($uri);
try {
$this->pdo = new PDO($this->dsn, $this->user, $this->passwd);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
throw new Klarna_DatabaseException('Failed to connect to database!');
}
}
/**
* Initializes the DB, if the database or table is missing.
*
* @return void
* @throws KlarnaException
*/
protected function initDB()
{
try {
$this->pdo->exec("CREATE DATABASE `{$this->dbName}`");
} catch (PDOException $e) {
//SQLite does not support this...
//throw new KlarnaException(
// 'Database non-existant, failed to create it!'
//);
}
$sql = <<<SQL
CREATE TABLE IF NOT EXISTS `{$this->dbName}`.`{$this->dbTable}` (
`eid` int(10) NOT NULL,
`id` int(10) NOT NULL,
`type` int(4) NOT NULL,
`description` varchar(255) NOT NULL,
`months` int(11) NOT NULL,
`interestrate` decimal(11,2) NOT NULL,
`invoicefee` decimal(11,2) NOT NULL,
`startfee` decimal(11,2) NOT NULL,
`minamount` decimal(11,2) NOT NULL,
`country` int(11) NOT NULL,
`expire` int(11) NOT NULL
);
SQL;
try {
$this->pdo->exec($sql);
} catch (PDOException $e) {
throw new Klarna_DatabaseException(
'Table non-existant, failed to create it!'
);
}
}
/**
* Connects to the DB and checks if DB and table exists.
*
* @param string|array $uri pclass uri
*
* @throws KlarnaException
* @return void
*/
protected function connect($uri)
{
$this->getConnection($uri);
$this->initDB();
}
/**
* Loads the PClasses.
*
* @param string|array $uri pclass uri
*
* @return void
* @throws KlarnaException
*/
public function load($uri)
{
$this->connect($uri);
$this->loadPClasses();
}
/**
* Loads the PClasses.
*
* @return void
* @throws KlarnaException
*/
protected function loadPClasses()
{
try {
$sth = $this->pdo->prepare(
"SELECT * FROM `{$this->dbName}`.`{$this->dbTable}`",
array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)
);
$sth->execute();
while ($row = $sth->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
$this->addPClass(new KlarnaPClass($row));
}
$sth->closeCursor();
$sth = null;
} catch (PDOException $e) {
throw new Klarna_DatabaseException(
'Could not fetch PClasses from database!'
);
}
}
/**
* Saves the PClasses.
*
* @param string|array $uri pclass uri
*
* @return void
* @throws KlarnaException
*/
public function save($uri)
{
$this->connect($uri);
//Only attempt to savePClasses if there are any.
if (!is_array($this->pclasses)) {
return;
}
if (count($this->pclasses) == 0) {
return;
}
$this->savePClasses();
}
/**
* Saves the PClasses.
*
* @return void
* @throws KlarnaException
*/
protected function savePClasses()
{
//Insert PClass SQL statement.
$sql = <<<SQL
INSERT INTO `{$this->dbName}`.`{$this->dbTable}`
(`eid`, `id`, `type`, `description`, `months`, `interestrate`,
`invoicefee`, `startfee`, `minamount`, `country`, `expire`)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
SQL;
foreach ($this->pclasses as $pclasses) {
foreach ($pclasses as $pclass) {
try {
//Remove the pclass if it exists.
$sth = $this->pdo->prepare(
"DELETE FROM `{$this->dbName}`.`{$this->dbTable}`
WHERE `id` = ? AND `eid` = ?"
);
$sth->execute(
array(
$pclass->getId(), $pclass->getEid()
)
);
$sth->closeCursor();
$sth = null;
} catch(PDOException $e) {
//Fail silently, we don't care if the removal failed.
}
try {
//Attempt to insert the PClass into the DB.
$sth = $this->pdo->prepare($sql);
$sth->execute(
array(
$pclass->getEid(),
$pclass->getId(),
$pclass->getType(),
$pclass->getDescription(),
$pclass->getMonths(),
$pclass->getInterestRate(),
$pclass->getInvoiceFee(),
$pclass->getStartFee(),
$pclass->getMinAmount(),
$pclass->getCountry(),
$pclass->getExpire()
)
);
$sth->closeCursor();
$sth = null;
} catch(PDOException $e) {
throw new Klarna_DatabaseException(
'Failed to insert PClass into database!'
);
}
}
}
}
/**
* Drops the database table, to clear the PClasses.
*
* @param string|array $uri pclass uri
*
* @return void
* @throws KlarnaException
*/
public function clear($uri)
{
try {
$this->connect($uri);
unset($this->pclasses);
$this->clearTable();
} catch(Exception $e) {
throw new Klarna_DatabaseException(
$e->getMessage(), $e->getCode()
);
}
}
/**
* Drops the database table, to clear the PClasses.
*
* @return void
* @throws KlarnaException
*/
protected function clearTable()
{
try {
$this->pdo->exec("DELETE FROM `{$this->dbName}`.`{$this->dbTable}`");
} catch (PDOException $e) {
throw new Klarna_DatabaseException('Could not clear the database!');
}
}
}
+229
View File
@@ -0,0 +1,229 @@
<?php
/**
* PClass Storage Interface
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* KlarnaPClass Storage interface
*
* This class provides an interface with which to save the PClasses easily.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
abstract class PCStorage
{
/**
* An array of KlarnaPClasses.
*
* @var array
*/
protected $pclasses;
/**
* Thhe name of the implementation.
* The file should be <name>storage.class.php
*
* @return string
*/
abstract public function getName();
/**
* Adds a PClass to the storage.
*
* @param KlarnaPClass $pclass PClass object.
*
* @throws KlarnaException
* @return void
*/
public function addPClass($pclass)
{
if (! $pclass instanceof KlarnaPClass) {
throw new Klarna_InvalidTypeException('pclass', 'KlarnaPClass');
}
if (!isset($this->pclasses) || !is_array($this->pclasses)) {
$this->pclasses = array();
}
if ($pclass->getDescription() === null || $pclass->getType() === null) {
//Something went wrong, do not save these!
return;
}
if (!isset($this->pclasses[$pclass->getEid()])) {
$this->pclasses[$pclass->getEid()] = array();
}
$this->pclasses[$pclass->getEid()][$pclass->getId()] = $pclass;
}
/**
* Gets the PClass by ID.
*
* @param int $id PClass ID.
* @param int $eid Merchant ID.
* @param int $country {@link KlarnaCountry Country} constant.
*
* @throws KlarnaException
* @return KlarnaPClass
*/
public function getPClass($id, $eid, $country)
{
if (!is_int($id)) {
throw new InvalidArgumentException('Supplied ID is not an integer!');
}
if (!is_array($this->pclasses)) {
throw new Klarna_PClassException('No match for that eid!');
}
if (!isset($this->pclasses[$eid]) || !is_array($this->pclasses[$eid])) {
throw new Klarna_PClassException('No match for that eid!');
}
if (!isset($this->pclasses[$eid][$id])
|| !$this->pclasses[$eid][$id]->isValid()
) {
throw new Klarna_PClassException('No such pclass available!');
}
if ($this->pclasses[$eid][$id]->getCountry() !== $country) {
throw new Klarna_PClassException(
'You cannot use this pclass with set country!'
);
}
return $this->pclasses[$eid][$id];
}
/**
* Returns an array of KlarnaPClasses, keyed with pclass ID.
* If type is specified, only that type will be returned.
*
* <b>Types available</b>:<br>
* {@link KlarnaPClass::ACCOUNT}<br>
* {@link KlarnaPClass::CAMPAIGN}<br>
* {@link KlarnaPClass::SPECIAL}<br>
* {@link KlarnaPClass::DELAY}<br>
* {@link KlarnaPClass::MOBILE}<br>
*
* @param int $eid Merchant ID.
* @param int $country {@link KlarnaCountry Country} constant.
* @param int $type PClass type identifier.
*
* @throws KlarnaException
* @return array An array of {@link KlarnaPClass PClasses}.
*/
public function getPClasses($eid, $country, $type = null)
{
if (!is_int($country)) {
throw new Klarna_ArgumentNotSetException('country');
}
$tmp = false;
if (!is_array($this->pclasses)) {
return;
}
$tmp = array();
foreach ($this->pclasses as $eid => $pclasses) {
$tmp[$eid] = array();
foreach ($pclasses as $pclass) {
if (!$pclass->isValid()) {
continue; //Pclass invalid, skip it.
}
if ($pclass->getEid() === $eid
&& $pclass->getCountry() === $country
&& ($pclass->getType() === $type || $type === null)
) {
$tmp[$eid][$pclass->getId()] = $pclass;
}
}
}
return $tmp;
}
/**
* Returns a flattened array of all pclasses
*
* @return array
*/
public function getAllPClasses()
{
if (!is_array($this->pclasses)) {
return array();
}
return $this->_flatten(array_values($this->pclasses));
}
/**
* Flatten an array
*
* @param array $array array to flatten
*
* @return array
*/
private function _flatten($array)
{
if (!is_array($array)) {
// nothing to do if it's not an array
return array($array);
}
$result = array();
foreach ($array as $value) {
// explode the sub-array, and add the parts
$result = array_merge($result, $this->_flatten($value));
}
return $result;
}
/**
* Loads the PClasses and calls {@link self::addPClass()} to store them
* in runtime.
* URI can be location to a file, or a db prefixed table.
*
* @param string $uri URI to stored PClasses.
*
* @throws KlarnaException|Exception
* @return void
*/
abstract public function load($uri);
/**
* Takes the internal PClass array and stores it.
* URI can be location to a file, or a db prefixed table.
*
* @param string $uri URI to stored PClasses.
*
* @throws KlarnaException|Exception
* @return void
*/
abstract public function save($uri);
/**
* Removes the internally stored pclasses.
*
* @param string $uri URI to stored PClasses.
*
* @throws KlarnaException|Exception
* @return void
*/
abstract public function clear($uri);
}
+280
View File
@@ -0,0 +1,280 @@
<?php
/**
* XMLStorage
*
* PHP Version 5.3
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
/**
* Include the {@link PCStorage} interface.
*/
require_once 'storage.intf.php';
/**
* XML storage class for KlarnaPClass
*
* This class is an XML implementation of the PCStorage interface.
*
* @category Payment
* @package KlarnaAPI
* @author MS Dev <ms.modules@klarna.com>
* @copyright 2012 Klarna AB (http://klarna.com)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2
* @link http://integration.klarna.com/
*/
class XMLStorage extends PCStorage
{
/**
* The internal XML document.
*
* @var DOMDocument
*/
protected $dom;
/**
* XML version for the DOM document.
*
* @var string
*/
protected $version = '1.0';
/**
* Encoding for the DOM document.
*
* @var string
*/
protected $encoding = 'ISO-8859-1';
/**
* Class constructor
*/
public function __construct()
{
$this->dom = new DOMDocument($this->version, $this->encoding);
$this->dom->formatOutput = true;
$this->dom->preserveWhiteSpace = false;
}
/**
* return the name of the storage type
*
* @return string
*/
public function getName()
{
return "xml";
}
/**
* Checks if the file is writeable, readable or if the directory is.
*
* @param string $xmlFile URI to XML file.
*
* @throws KlarnaException
* @return void
*/
protected function checkURI($xmlFile)
{
//If file doesn't exist, check the directory.
if (!file_exists($xmlFile)) {
$xmlFile = dirname($xmlFile);
}
if (!is_writable($xmlFile)) {
throw new Klarna_FileNotWritableException($xmlFile);
}
if (!is_readable($xmlFile)) {
throw new Klarna_FileNotReadableException($xmlFile);
}
}
/**
* Load pclasses from file
*
* @param string $uri uri to file to load
*
* @throws KlarnaException
* @return void
*/
public function load($uri)
{
$this->checkURI($uri);
if (!file_exists($uri)) {
//Do not fail, if file doesn't exist.
return;
}
if (!@$this->dom->load($uri)) {
throw new Klarna_XMLParseException($uri);
}
$xpath = new DOMXpath($this->dom);
foreach ($xpath->query('/klarna/estore') as $estore) {
$eid = $estore->getAttribute('id');
foreach ($xpath->query('pclass', $estore) as $node) {
$pclass = new KlarnaPClass();
$pclass->setId(
$node->getAttribute('pid')
);
$pclass->setType(
$node->getAttribute('type')
);
$pclass->setEid($eid);
$pclass->setDescription(
$xpath->query('description', $node)->item(0)->textContent
);
$pclass->setMonths(
$xpath->query('months', $node)->item(0)->textContent
);
$pclass->setStartFee(
$xpath->query('startfee', $node)->item(0)->textContent
);
$pclass->setInvoiceFee(
$xpath->query('invoicefee', $node)->item(0)->textContent
);
$pclass->setInterestRate(
$xpath->query('interestrate', $node)->item(0)->textContent
);
$pclass->setMinAmount(
$xpath->query('minamount', $node)->item(0)->textContent
);
$pclass->setCountry(
$xpath->query('country', $node)->item(0)->textContent
);
$pclass->setExpire(
$xpath->query('expire', $node)->item(0)->textContent
);
$this->addPClass($pclass);
}
}
}
/**
* Creates DOMElement for all fields for specified PClass.
*
* @param KlarnaPClass $pclass pclass object
*
* @return array Array of DOMElements.
*/
protected function createFields($pclass)
{
$fields = array();
//This is to prevent HTMLEntities to be converted to the real character.
$fields[] = $this->dom->createElement('description');
end($fields)->appendChild(
$this->dom->createTextNode($pclass->getDescription())
);
$fields[] = $this->dom->createElement(
'months', $pclass->getMonths()
);
$fields[] = $this->dom->createElement(
'startfee', $pclass->getStartFee()
);
$fields[] = $this->dom->createElement(
'invoicefee', $pclass->getInvoiceFee()
);
$fields[] = $this->dom->createElement(
'interestrate', $pclass->getInterestRate()
);
$fields[] = $this->dom->createElement(
'minamount', $pclass->getMinAmount()
);
$fields[] = $this->dom->createElement(
'country', $pclass->getCountry()
);
$fields[] = $this->dom->createElement(
'expire', $pclass->getExpire()
);
return $fields;
}
/**
* Save pclasses to file
*
* @param string $uri uri to file to save
*
* @throws KlarnaException
* @return void
*/
public function save($uri)
{
$this->checkURI($uri);
//Reset DOMDocument.
if (!$this->dom->loadXML(
"<?xml version='$this->version' encoding='$this->encoding'?"
."><klarna/>"
)
) {
throw new Klarna_XMLParseException($uri);
}
ksort($this->pclasses, SORT_NUMERIC);
$xpath = new DOMXpath($this->dom);
foreach ($this->pclasses as $eid => $pclasses) {
$estore = $xpath->query('/klarna/estore[@id="'.$eid.'"]');
if ($estore === false || $estore->length === 0) {
//No estore with matching eid, create it.
$estore = $this->dom->createElement('estore');
$estore->setAttribute('id', $eid);
$this->dom->documentElement->appendChild($estore);
} else {
$estore = $estore->item(0);
}
foreach ($pclasses as $pclass) {
if ($eid != $pclass->getEid()) {
//This should never occur, failsafe.
continue;
}
$pnode = $this->dom->createElement('pclass');
foreach ($this->createFields($pclass) as $field) {
$pnode->appendChild($field);
}
$pnode->setAttribute('pid', $pclass->getId());
$pnode->setAttribute('type', $pclass->getType());
$estore->appendChild($pnode);
}
}
if (!$this->dom->save($uri)) {
throw new KlarnaException('Failed to save XML document!');
}
}
/**
* This uses unlink (delete) to clear the pclasses!
*
* @param string $uri uri to file to clear
*
* @throws KlarnaException
* @return void
*/
public function clear($uri)
{
$this->checkURI($uri);
unset($this->pclasses);
if (file_exists($uri)) {
unlink($uri);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,955 @@
<?php
/**
* PHP-XMLRPC "wrapper" functions
* Generate stubs to transparently access xmlrpc methods as php functions and viceversa
*
* @version $Id: xmlrpc_wrappers.inc,v 1.13 2008/09/20 01:23:47 ggiunta Exp $
* @author Gaetano Giunta
* @copyright (C) 2006-2009 G. Giunta
* @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt
*
* @todo separate introspection from code generation for func-2-method wrapping
* @todo use some better templating system for code generation?
* @todo implement method wrapping with preservation of php objs in calls
* @todo when wrapping methods without obj rebuilding, use return_type = 'phpvals' (faster)
* @todo implement self-parsing of php code for PHP <= 4
*/
// requires: xmlrpc.inc
/**
* Given a string defining a php type or phpxmlrpc type (loosely defined: strings
* accepted come from javadoc blocks), return corresponding phpxmlrpc type.
* NB: for php 'resource' types returns empty string, since resources cannot be serialized;
* for php class names returns 'struct', since php objects can be serialized as xmlrpc structs
* for php arrays always return array, even though arrays sometiles serialize as json structs
* @param string $phptype
* @return string
*/
function php_2_xmlrpc_type($phptype)
{
switch(strtolower($phptype))
{
case 'string':
return $GLOBALS['xmlrpcString'];
case 'integer':
case $GLOBALS['xmlrpcInt']: // 'int'
case $GLOBALS['xmlrpcI4']:
return $GLOBALS['xmlrpcInt'];
case 'double':
return $GLOBALS['xmlrpcDouble'];
case 'boolean':
return $GLOBALS['xmlrpcBoolean'];
case 'array':
return $GLOBALS['xmlrpcArray'];
case 'object':
return $GLOBALS['xmlrpcStruct'];
case $GLOBALS['xmlrpcBase64']:
case $GLOBALS['xmlrpcStruct']:
return strtolower($phptype);
case 'resource':
return '';
default:
if(class_exists($phptype))
{
return $GLOBALS['xmlrpcStruct'];
}
else
{
// unknown: might be any 'extended' xmlrpc type
return $GLOBALS['xmlrpcValue'];
}
}
}
/**
* Given a string defining a phpxmlrpc type return corresponding php type.
* @param string $xmlrpctype
* @return string
*/
function xmlrpc_2_php_type($xmlrpctype)
{
switch(strtolower($xmlrpctype))
{
case 'base64':
case 'datetime.iso8601':
case 'string':
return $GLOBALS['xmlrpcString'];
case 'int':
case 'i4':
return 'integer';
case 'struct':
case 'array':
return 'array';
case 'double':
return 'float';
case 'undefined':
return 'mixed';
case 'boolean':
case 'null':
default:
// unknown: might be any xmlrpc type
return strtolower($xmlrpctype);
}
}
/**
* Given a user-defined PHP function, create a PHP 'wrapper' function that can
* be exposed as xmlrpc method from an xmlrpc_server object and called from remote
* clients (as well as its corresponding signature info).
*
* Since php is a typeless language, to infer types of input and output parameters,
* it relies on parsing the javadoc-style comment block associated with the given
* function. Usage of xmlrpc native types (such as datetime.dateTime.iso8601 and base64)
* in the @param tag is also allowed, if you need the php function to receive/send
* data in that particular format (note that base64 encoding/decoding is transparently
* carried out by the lib, while datetime vals are passed around as strings)
*
* Known limitations:
* - requires PHP 5.0.3 +
* - only works for user-defined functions, not for PHP internal functions
* (reflection does not support retrieving number/type of params for those)
* - functions returning php objects will generate special xmlrpc responses:
* when the xmlrpc decoding of those responses is carried out by this same lib, using
* the appropriate param in php_xmlrpc_decode, the php objects will be rebuilt.
* In short: php objects can be serialized, too (except for their resource members),
* using this function.
* Other libs might choke on the very same xml that will be generated in this case
* (i.e. it has a nonstandard attribute on struct element tags)
* - usage of javadoc @param tags using param names in a different order from the
* function prototype is not considered valid (to be fixed?)
*
* Note that since rel. 2.0RC3 the preferred method to have the server call 'standard'
* php functions (ie. functions not expecting a single xmlrpcmsg obj as parameter)
* is by making use of the functions_parameters_type class member.
*
* @param string $funcname the name of the PHP user function to be exposed as xmlrpc method; array($obj, 'methodname') and array('class', 'methodname') are ok too
* @param string $newfuncname (optional) name for function to be created
* @param array $extra_options (optional) array of options for conversion. valid values include:
* bool return_source when true, php code w. function definition will be returned, not evaluated
* bool encode_php_objs let php objects be sent to server using the 'improved' xmlrpc notation, so server can deserialize them as php objects
* bool decode_php_objs --- WARNING !!! possible security hazard. only use it with trusted servers ---
* bool suppress_warnings remove from produced xml any runtime warnings due to the php function being invoked
* @return false on error, or an array containing the name of the new php function,
* its signature and docs, to be used in the server dispatch map
*
* @todo decide how to deal with params passed by ref: bomb out or allow?
* @todo finish using javadoc info to build method sig if all params are named but out of order
* @todo add a check for params of 'resource' type
* @todo add some trigger_errors / error_log when returning false?
* @todo what to do when the PHP function returns NULL? we are currently returning an empty string value...
* @todo add an option to suppress php warnings in invocation of user function, similar to server debug level 3?
* @todo if $newfuncname is empty, we could use create_user_func instead of eval, as it is possibly faster
* @todo add a verbatim_object_copy parameter to allow avoiding the same obj instance?
*/
function wrap_php_function($funcname, $newfuncname='', $extra_options=array())
{
$buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true;
$prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc';
$encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false;
$decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false;
$catch_warnings = isset($extra_options['suppress_warnings']) && $extra_options['suppress_warnings'] ? '@' : '';
if(version_compare(phpversion(), '5.0.3') == -1)
{
// up to php 5.0.3 some useful reflection methods were missing
error_log('XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3');
return false;
}
$exists = false;
if (is_string($funcname) && strpos($funcname, '::') !== false)
{
$funcname = explode('::', $funcname);
}
if(is_array($funcname))
{
if(count($funcname) < 2 || (!is_string($funcname[0]) && !is_object($funcname[0])))
{
error_log('XML-RPC: syntax for function to be wrapped is wrong');
return false;
}
if(is_string($funcname[0]))
{
$plainfuncname = implode('::', $funcname);
}
elseif(is_object($funcname[0]))
{
$plainfuncname = get_class($funcname[0]) . '->' . $funcname[1];
}
$exists = method_exists($funcname[0], $funcname[1]);
if (!$exists && version_compare(phpversion(), '5.1') < 0)
{
// workaround for php 5.0: static class methods are not seen by method_exists
$exists = is_callable( $funcname );
}
}
else
{
$plainfuncname = $funcname;
$exists = function_exists($funcname);
}
if(!$exists)
{
error_log('XML-RPC: function to be wrapped is not defined: '.$plainfuncname);
return false;
}
else
{
// determine name of new php function
if($newfuncname == '')
{
if(is_array($funcname))
{
if(is_string($funcname[0]))
$xmlrpcfuncname = "{$prefix}_".implode('_', $funcname);
else
$xmlrpcfuncname = "{$prefix}_".get_class($funcname[0]) . '_' . $funcname[1];
}
else
{
$xmlrpcfuncname = "{$prefix}_$funcname";
}
}
else
{
$xmlrpcfuncname = $newfuncname;
}
while($buildit && function_exists($xmlrpcfuncname))
{
$xmlrpcfuncname .= 'x';
}
// start to introspect PHP code
if(is_array($funcname))
{
$func = new ReflectionMethod($funcname[0], $funcname[1]);
if($func->isPrivate())
{
error_log('XML-RPC: method to be wrapped is private: '.$plainfuncname);
return false;
}
if($func->isProtected())
{
error_log('XML-RPC: method to be wrapped is protected: '.$plainfuncname);
return false;
}
if($func->isConstructor())
{
error_log('XML-RPC: method to be wrapped is the constructor: '.$plainfuncname);
return false;
}
// php 503 always says isdestructor = true...
if( version_compare(phpversion(), '5.0.3') != 0 && $func->isDestructor())
{
error_log('XML-RPC: method to be wrapped is the destructor: '.$plainfuncname);
return false;
}
if($func->isAbstract())
{
error_log('XML-RPC: method to be wrapped is abstract: '.$plainfuncname);
return false;
}
/// @todo add more checks for static vs. nonstatic?
}
else
{
$func = new ReflectionFunction($funcname);
}
if($func->isInternal())
{
// Note: from PHP 5.1.0 onward, we will possibly be able to use invokeargs
// instead of getparameters to fully reflect internal php functions ?
error_log('XML-RPC: function to be wrapped is internal: '.$plainfuncname);
return false;
}
// retrieve parameter names, types and description from javadoc comments
// function description
$desc = '';
// type of return val: by default 'any'
$returns = $GLOBALS['xmlrpcValue'];
// desc of return val
$returnsDocs = '';
// type + name of function parameters
$paramDocs = array();
$docs = $func->getDocComment();
if($docs != '')
{
$docs = explode("\n", $docs);
$i = 0;
foreach($docs as $doc)
{
$doc = trim($doc, " \r\t/*");
if(strlen($doc) && strpos($doc, '@') !== 0 && !$i)
{
if($desc)
{
$desc .= "\n";
}
$desc .= $doc;
}
elseif(strpos($doc, '@param') === 0)
{
// syntax: @param type [$name] desc
if(preg_match('/@param\s+(\S+)(\s+\$\S+)?\s+(.+)/', $doc, $matches))
{
if(strpos($matches[1], '|'))
{
//$paramDocs[$i]['type'] = explode('|', $matches[1]);
$paramDocs[$i]['type'] = 'mixed';
}
else
{
$paramDocs[$i]['type'] = $matches[1];
}
$paramDocs[$i]['name'] = trim($matches[2]);
$paramDocs[$i]['doc'] = $matches[3];
}
$i++;
}
elseif(strpos($doc, '@return') === 0)
{
// syntax: @return type desc
//$returns = preg_split('/\s+/', $doc);
if(preg_match('/@return\s+(\S+)\s+(.+)/', $doc, $matches))
{
$returns = php_2_xmlrpc_type($matches[1]);
if(isset($matches[2]))
{
$returnsDocs = $matches[2];
}
}
}
}
}
// execute introspection of actual function prototype
$params = array();
$i = 0;
foreach($func->getParameters() as $paramobj)
{
$params[$i] = array();
$params[$i]['name'] = '$'.$paramobj->getName();
$params[$i]['isoptional'] = $paramobj->isOptional();
$i++;
}
// start building of PHP code to be eval'd
$innercode = '';
$i = 0;
$parsvariations = array();
$pars = array();
$pnum = count($params);
foreach($params as $param)
{
if (isset($paramDocs[$i]['name']) && $paramDocs[$i]['name'] && strtolower($paramDocs[$i]['name']) != strtolower($param['name']))
{
// param name from phpdoc info does not match param definition!
$paramDocs[$i]['type'] = 'mixed';
}
if($param['isoptional'])
{
// this particular parameter is optional. save as valid previous list of parameters
$innercode .= "if (\$paramcount > $i) {\n";
$parsvariations[] = $pars;
}
$innercode .= "\$p$i = \$msg->getParam($i);\n";
if ($decode_php_objects)
{
$innercode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i, array('decode_php_objs'));\n";
}
else
{
$innercode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i);\n";
}
$pars[] = "\$p$i";
$i++;
if($param['isoptional'])
{
$innercode .= "}\n";
}
if($i == $pnum)
{
// last allowed parameters combination
$parsvariations[] = $pars;
}
}
$sigs = array();
$psigs = array();
if(count($parsvariations) == 0)
{
// only known good synopsis = no parameters
$parsvariations[] = array();
$minpars = 0;
}
else
{
$minpars = count($parsvariations[0]);
}
if($minpars)
{
// add to code the check for min params number
// NB: this check needs to be done BEFORE decoding param values
$innercode = "\$paramcount = \$msg->getNumParams();\n" .
"if (\$paramcount < $minpars) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}');\n" . $innercode;
}
else
{
$innercode = "\$paramcount = \$msg->getNumParams();\n" . $innercode;
}
$innercode .= "\$np = false;\n";
// since there are no closures in php, if we are given an object instance,
// we store a pointer to it in a global var...
if ( is_array($funcname) && is_object($funcname[0]) )
{
$GLOBALS['xmlrpcWPFObjHolder'][$xmlrpcfuncname] =& $funcname[0];
$innercode .= "\$obj =& \$GLOBALS['xmlrpcWPFObjHolder']['$xmlrpcfuncname'];\n";
$realfuncname = '$obj->'.$funcname[1];
}
else
{
$realfuncname = $plainfuncname;
}
foreach($parsvariations as $pars)
{
$innercode .= "if (\$paramcount == " . count($pars) . ") \$retval = {$catch_warnings}$realfuncname(" . implode(',', $pars) . "); else\n";
// build a 'generic' signature (only use an appropriate return type)
$sig = array($returns);
$psig = array($returnsDocs);
for($i=0; $i < count($pars); $i++)
{
if (isset($paramDocs[$i]['type']))
{
$sig[] = php_2_xmlrpc_type($paramDocs[$i]['type']);
}
else
{
$sig[] = $GLOBALS['xmlrpcValue'];
}
$psig[] = isset($paramDocs[$i]['doc']) ? $paramDocs[$i]['doc'] : '';
}
$sigs[] = $sig;
$psigs[] = $psig;
}
$innercode .= "\$np = true;\n";
$innercode .= "if (\$np) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}'); else {\n";
//$innercode .= "if (\$_xmlrpcs_error_occurred) return new xmlrpcresp(0, $GLOBALS['xmlrpcerr']user, \$_xmlrpcs_error_occurred); else\n";
$innercode .= "if (is_a(\$retval, '{$prefix}resp')) return \$retval; else\n";
if($returns == $GLOBALS['xmlrpcDateTime'] || $returns == $GLOBALS['xmlrpcBase64'])
{
$innercode .= "return new {$prefix}resp(new {$prefix}val(\$retval, '$returns'));";
}
else
{
if ($encode_php_objects)
$innercode .= "return new {$prefix}resp(php_{$prefix}_encode(\$retval, array('encode_php_objs')));\n";
else
$innercode .= "return new {$prefix}resp(php_{$prefix}_encode(\$retval));\n";
}
// shall we exclude functions returning by ref?
// if($func->returnsReference())
// return false;
$code = "function $xmlrpcfuncname(\$msg) {\n" . $innercode . "}\n}";
//print_r($code);
if ($buildit)
{
$allOK = 0;
eval($code.'$allOK=1;');
// alternative
//$xmlrpcfuncname = create_function('$m', $innercode);
if(!$allOK)
{
error_log('XML-RPC: could not create function '.$xmlrpcfuncname.' to wrap php function '.$plainfuncname);
return false;
}
}
/// @todo examine if $paramDocs matches $parsvariations and build array for
/// usage as method signature, plus put together a nice string for docs
$ret = array('function' => $xmlrpcfuncname, 'signature' => $sigs, 'docstring' => $desc, 'signature_docs' => $psigs, 'source' => $code);
return $ret;
}
}
/**
* Given a user-defined PHP class or php object, map its methods onto a list of
* PHP 'wrapper' functions that can be exposed as xmlrpc methods from an xmlrpc_server
* object and called from remote clients (as well as their corresponding signature info).
*
* @param mixed $classname the name of the class whose methods are to be exposed as xmlrpc methods, or an object instance of that class
* @param array $extra_options see the docs for wrap_php_method for more options
* string method_type 'static', 'nonstatic', 'all' and 'auto' (default); the latter will switch between static and non-static depending on wheter $classname is a class name or object instance
* @return array or false on failure
*
* @todo get_class_methods will return both static and non-static methods.
* we have to differentiate the action, depending on wheter we recived a class name or object
*/
function wrap_php_class($classname, $extra_options=array())
{
$methodfilter = isset($extra_options['method_filter']) ? $extra_options['method_filter'] : '';
$methodtype = isset($extra_options['method_type']) ? $extra_options['method_type'] : 'auto';
if(version_compare(phpversion(), '5.0.3') == -1)
{
// up to php 5.0.3 some useful reflection methods were missing
error_log('XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3');
return false;
}
$result = array();
$mlist = get_class_methods($classname);
foreach($mlist as $mname)
{
if ($methodfilter == '' || preg_match($methodfilter, $mname))
{
// echo $mlist."\n";
$func = new ReflectionMethod($classname, $mname);
if(!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract())
{
if(($func->isStatic && ($methodtype == 'all' || $methodtype == 'static' || ($methodtype == 'auto' && is_string($classname)))) ||
(!$func->isStatic && ($methodtype == 'all' || $methodtype == 'nonstatic' || ($methodtype == 'auto' && is_object($classname)))))
{
$methodwrap = wrap_php_function(array($classname, $mname), '', $extra_options);
if ( $methodwrap )
{
$result[$methodwrap['function']] = $methodwrap['function'];
}
}
}
}
}
return $result;
}
/**
* Given an xmlrpc client and a method name, register a php wrapper function
* that will call it and return results using native php types for both
* params and results. The generated php function will return an xmlrpcresp
* oject for failed xmlrpc calls
*
* Known limitations:
* - server must support system.methodsignature for the wanted xmlrpc method
* - for methods that expose many signatures, only one can be picked (we
* could in priciple check if signatures differ only by number of params
* and not by type, but it would be more complication than we can spare time)
* - nested xmlrpc params: the caller of the generated php function has to
* encode on its own the params passed to the php function if these are structs
* or arrays whose (sub)members include values of type datetime or base64
*
* Notes: the connection properties of the given client will be copied
* and reused for the connection used during the call to the generated
* php function.
* Calling the generated php function 'might' be slow: a new xmlrpc client
* is created on every invocation and an xmlrpc-connection opened+closed.
* An extra 'debug' param is appended to param list of xmlrpc method, useful
* for debugging purposes.
*
* @param xmlrpc_client $client an xmlrpc client set up correctly to communicate with target server
* @param string $methodname the xmlrpc method to be mapped to a php function
* @param array $extra_options array of options that specify conversion details. valid ptions include
* integer signum the index of the method signature to use in mapping (if method exposes many sigs)
* integer timeout timeout (in secs) to be used when executing function/calling remote method
* string protocol 'http' (default), 'http11' or 'https'
* string new_function_name the name of php function to create. If unsepcified, lib will pick an appropriate name
* string return_source if true return php code w. function definition instead fo function name
* bool encode_php_objs let php objects be sent to server using the 'improved' xmlrpc notation, so server can deserialize them as php objects
* bool decode_php_objs --- WARNING !!! possible security hazard. only use it with trusted servers ---
* mixed return_on_fault a php value to be returned when the xmlrpc call fails/returns a fault response (by default the xmlrpcresp object is returned in this case). If a string is used, '%faultCode%' and '%faultString%' tokens will be substituted with actual error values
* bool debug set it to 1 or 2 to see debug results of querying server for method synopsis
* @return string the name of the generated php function (or false) - OR AN ARRAY...
*/
function wrap_xmlrpc_method($client, $methodname, $extra_options=0, $timeout=0, $protocol='', $newfuncname='')
{
// mind numbing: let caller use sane calling convention (as per javadoc, 3 params),
// OR the 2.0 calling convention (no options) - we really love backward compat, don't we?
if (!is_array($extra_options))
{
$signum = $extra_options;
$extra_options = array();
}
else
{
$signum = isset($extra_options['signum']) ? (int)$extra_options['signum'] : 0;
$timeout = isset($extra_options['timeout']) ? (int)$extra_options['timeout'] : 0;
$protocol = isset($extra_options['protocol']) ? $extra_options['protocol'] : '';
$newfuncname = isset($extra_options['new_function_name']) ? $extra_options['new_function_name'] : '';
}
//$encode_php_objects = in_array('encode_php_objects', $extra_options);
//$verbatim_client_copy = in_array('simple_client_copy', $extra_options) ? 1 :
// in_array('build_class_code', $extra_options) ? 2 : 0;
$encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false;
$decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false;
$simple_client_copy = isset($extra_options['simple_client_copy']) ? (int)($extra_options['simple_client_copy']) : 0;
$buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true;
$prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc';
if (isset($extra_options['return_on_fault']))
{
$decode_fault = true;
$fault_response = $extra_options['return_on_fault'];
}
else
{
$decode_fault = false;
$fault_response = '';
}
$debug = isset($extra_options['debug']) ? ($extra_options['debug']) : 0;
$msgclass = $prefix.'msg';
$valclass = $prefix.'val';
$decodefunc = 'php_'.$prefix.'_decode';
$msg = new $msgclass('system.methodSignature');
$msg->addparam(new $valclass($methodname));
$client->setDebug($debug);
$response =& $client->send($msg, $timeout, $protocol);
if($response->faultCode())
{
error_log('XML-RPC: could not retrieve method signature from remote server for method '.$methodname);
return false;
}
else
{
$msig = $response->value();
if ($client->return_type != 'phpvals')
{
$msig = $decodefunc($msig);
}
if(!is_array($msig) || count($msig) <= $signum)
{
error_log('XML-RPC: could not retrieve method signature nr.'.$signum.' from remote server for method '.$methodname);
return false;
}
else
{
// pick a suitable name for the new function, avoiding collisions
if($newfuncname != '')
{
$xmlrpcfuncname = $newfuncname;
}
else
{
// take care to insure that methodname is translated to valid
// php function name
$xmlrpcfuncname = $prefix.'_'.preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
array('_', ''), $methodname);
}
while($buildit && function_exists($xmlrpcfuncname))
{
$xmlrpcfuncname .= 'x';
}
$msig = $msig[$signum];
$mdesc = '';
// if in 'offline' mode, get method description too.
// in online mode, favour speed of operation
if(!$buildit)
{
$msg = new $msgclass('system.methodHelp');
$msg->addparam(new $valclass($methodname));
$response =& $client->send($msg, $timeout, $protocol);
if (!$response->faultCode())
{
$mdesc = $response->value();
if ($client->return_type != 'phpvals')
{
$mdesc = $mdesc->scalarval();
}
}
}
$results = build_remote_method_wrapper_code($client, $methodname,
$xmlrpcfuncname, $msig, $mdesc, $timeout, $protocol, $simple_client_copy,
$prefix, $decode_php_objects, $encode_php_objects, $decode_fault,
$fault_response);
//print_r($code);
if ($buildit)
{
$allOK = 0;
eval($results['source'].'$allOK=1;');
// alternative
//$xmlrpcfuncname = create_function('$m', $innercode);
if($allOK)
{
return $xmlrpcfuncname;
}
else
{
error_log('XML-RPC: could not create function '.$xmlrpcfuncname.' to wrap remote method '.$methodname);
return false;
}
}
else
{
$results['function'] = $xmlrpcfuncname;
return $results;
}
}
}
}
/**
* Similar to wrap_xmlrpc_method, but will generate a php class that wraps
* all xmlrpc methods exposed by the remote server as own methods.
* For more details see wrap_xmlrpc_method.
* @param xmlrpc_client $client the client obj all set to query the desired server
* @param array $extra_options list of options for wrapped code
* @return mixed false on error, the name of the created class if all ok or an array with code, class name and comments (if the appropriatevoption is set in extra_options)
*/
function wrap_xmlrpc_server($client, $extra_options=array())
{
$methodfilter = isset($extra_options['method_filter']) ? $extra_options['method_filter'] : '';
//$signum = isset($extra_options['signum']) ? (int)$extra_options['signum'] : 0;
$timeout = isset($extra_options['timeout']) ? (int)$extra_options['timeout'] : 0;
$protocol = isset($extra_options['protocol']) ? $extra_options['protocol'] : '';
$newclassname = isset($extra_options['new_class_name']) ? $extra_options['new_class_name'] : '';
$encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false;
$decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false;
$verbatim_client_copy = isset($extra_options['simple_client_copy']) ? !($extra_options['simple_client_copy']) : true;
$buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true;
$prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc';
$msgclass = $prefix.'msg';
//$valclass = $prefix.'val';
$decodefunc = 'php_'.$prefix.'_decode';
$msg = new $msgclass('system.listMethods');
$response =& $client->send($msg, $timeout, $protocol);
if($response->faultCode())
{
error_log('XML-RPC: could not retrieve method list from remote server');
return false;
}
else
{
$mlist = $response->value();
if ($client->return_type != 'phpvals')
{
$mlist = $decodefunc($mlist);
}
if(!is_array($mlist) || !count($mlist))
{
error_log('XML-RPC: could not retrieve meaningful method list from remote server');
return false;
}
else
{
// pick a suitable name for the new function, avoiding collisions
if($newclassname != '')
{
$xmlrpcclassname = $newclassname;
}
else
{
$xmlrpcclassname = $prefix.'_'.preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
array('_', ''), $client->server).'_client';
}
while($buildit && class_exists($xmlrpcclassname))
{
$xmlrpcclassname .= 'x';
}
/// @todo add function setdebug() to new class, to enable/disable debugging
$source = "class $xmlrpcclassname\n{\nvar \$client;\n\n";
$source .= "function $xmlrpcclassname()\n{\n";
$source .= build_client_wrapper_code($client, $verbatim_client_copy, $prefix);
$source .= "\$this->client =& \$client;\n}\n\n";
$opts = array('simple_client_copy' => 2, 'return_source' => true,
'timeout' => $timeout, 'protocol' => $protocol,
'encode_php_objs' => $encode_php_objects, 'prefix' => $prefix,
'decode_php_objs' => $decode_php_objects
);
/// @todo build javadoc for class definition, too
foreach($mlist as $mname)
{
if ($methodfilter == '' || preg_match($methodfilter, $mname))
{
$opts['new_function_name'] = preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'),
array('_', ''), $mname);
$methodwrap = wrap_xmlrpc_method($client, $mname, $opts);
if ($methodwrap)
{
if (!$buildit)
{
$source .= $methodwrap['docstring'];
}
$source .= $methodwrap['source']."\n";
}
else
{
error_log('XML-RPC: will not create class method to wrap remote method '.$mname);
}
}
}
$source .= "}\n";
if ($buildit)
{
$allOK = 0;
eval($source.'$allOK=1;');
// alternative
//$xmlrpcfuncname = create_function('$m', $innercode);
if($allOK)
{
return $xmlrpcclassname;
}
else
{
error_log('XML-RPC: could not create class '.$xmlrpcclassname.' to wrap remote server '.$client->server);
return false;
}
}
else
{
return array('class' => $xmlrpcclassname, 'code' => $source, 'docstring' => '');
}
}
}
}
/**
* Given the necessary info, build php code that creates a new function to
* invoke a remote xmlrpc method.
* Take care that no full checking of input parameters is done to ensure that
* valid php code is emitted.
* Note: real spaghetti code follows...
* @access private
*/
function build_remote_method_wrapper_code($client, $methodname, $xmlrpcfuncname,
$msig, $mdesc='', $timeout=0, $protocol='', $client_copy_mode=0, $prefix='xmlrpc',
$decode_php_objects=false, $encode_php_objects=false, $decode_fault=false,
$fault_response='')
{
$code = "function $xmlrpcfuncname (";
if ($client_copy_mode < 2)
{
// client copy mode 0 or 1 == partial / full client copy in emitted code
$innercode = build_client_wrapper_code($client, $client_copy_mode, $prefix);
$innercode .= "\$client->setDebug(\$debug);\n";
$this_ = '';
}
else
{
// client copy mode 2 == no client copy in emitted code
$innercode = '';
$this_ = 'this->';
}
$innercode .= "\$msg = new {$prefix}msg('$methodname');\n";
if ($mdesc != '')
{
// take care that PHP comment is not terminated unwillingly by method description
$mdesc = "/**\n* ".str_replace('*/', '* /', $mdesc)."\n";
}
else
{
$mdesc = "/**\nFunction $xmlrpcfuncname\n";
}
// param parsing
$plist = array();
$pcount = count($msig);
for($i = 1; $i < $pcount; $i++)
{
$plist[] = "\$p$i";
$ptype = $msig[$i];
if($ptype == 'i4' || $ptype == 'int' || $ptype == 'boolean' || $ptype == 'double' ||
$ptype == 'string' || $ptype == 'dateTime.iso8601' || $ptype == 'base64' || $ptype == 'null')
{
// only build directly xmlrpcvals when type is known and scalar
$innercode .= "\$p$i = new {$prefix}val(\$p$i, '$ptype');\n";
}
else
{
if ($encode_php_objects)
{
$innercode .= "\$p$i =& php_{$prefix}_encode(\$p$i, array('encode_php_objs'));\n";
}
else
{
$innercode .= "\$p$i =& php_{$prefix}_encode(\$p$i);\n";
}
}
$innercode .= "\$msg->addparam(\$p$i);\n";
$mdesc .= '* @param '.xmlrpc_2_php_type($ptype)." \$p$i\n";
}
if ($client_copy_mode < 2)
{
$plist[] = '$debug=0';
$mdesc .= "* @param int \$debug when 1 (or 2) will enable debugging of the underlying {$prefix} call (defaults to 0)\n";
}
$plist = implode(', ', $plist);
$mdesc .= '* @return '.xmlrpc_2_php_type($msig[0])." (or an {$prefix}resp obj instance if call fails)\n*/\n";
$innercode .= "\$res =& \${$this_}client->send(\$msg, $timeout, '$protocol');\n";
if ($decode_fault)
{
if (is_string($fault_response) && ((strpos($fault_response, '%faultCode%') !== false) || (strpos($fault_response, '%faultString%') !== false)))
{
$respcode = "str_replace(array('%faultCode%', '%faultString%'), array(\$res->faultCode(), \$res->faultString()), '".str_replace("'", "''", $fault_response)."')";
}
else
{
$respcode = var_export($fault_response, true);
}
}
else
{
$respcode = '$res';
}
if ($decode_php_objects)
{
$innercode .= "if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value(), array('decode_php_objs'));";
}
else
{
$innercode .= "if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value());";
}
$code = $code . $plist. ") {\n" . $innercode . "\n}\n";
return array('source' => $code, 'docstring' => $mdesc);
}
/**
* Given necessary info, generate php code that will rebuild a client object
* Take care that no full checking of input parameters is done to ensure that
* valid php code is emitted.
* @access private
*/
function build_client_wrapper_code($client, $verbatim_client_copy, $prefix='xmlrpc')
{
$code = "\$client = new {$prefix}_client('".str_replace("'", "\'", $client->path).
"', '" . str_replace("'", "\'", $client->server) . "', $client->port);\n";
// copy all client fields to the client that will be generated runtime
// (this provides for future expansion or subclassing of client obj)
if ($verbatim_client_copy)
{
foreach($client as $fld => $val)
{
if($fld != 'debug' && $fld != 'return_type')
{
$val = var_export($val, true);
$code .= "\$client->$fld = $val;\n";
}
}
}
// only make sure that client always returns the correct data type
$code .= "\$client->return_type = '{$prefix}vals';\n";
//$code .= "\$client->setDebug(\$debug);\n";
return $code;
}
?>
File diff suppressed because it is too large Load Diff