├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── examples ├── Billcode.php ├── BillcodeDetails.php ├── Ideal.php ├── IdealBanks.php ├── Paycode.php ├── PaycodeDetails.php ├── Refund.php ├── Sofortueberweisung.php └── TransactionData.php ├── phpunit.xml.dist ├── src ├── Sofort │ └── SofortLib │ │ ├── AbstractDataHandler.php │ │ ├── AbstractHttp.php │ │ ├── AbstractLoggerHandler.php │ │ ├── AbstractWrapper.php │ │ ├── Billcode.php │ │ ├── BillcodeDetails.php │ │ ├── Factory.php │ │ ├── FileLogger.php │ │ ├── HttpCurl.php │ │ ├── HttpSocket.php │ │ ├── Ideal.php │ │ ├── IdealBanks.php │ │ ├── IdealNotification.php │ │ ├── Multipay.php │ │ ├── Notification.php │ │ ├── Paycode.php │ │ ├── PaycodeAbstract.php │ │ ├── PaycodeDetails.php │ │ ├── PaycodeDetailsAbstract.php │ │ ├── Refund.php │ │ ├── Sofortueberweisung.php │ │ ├── TransactionData.php │ │ ├── Xml │ │ ├── ArrayToXml.php │ │ ├── ArrayToXmlException.php │ │ ├── Element │ │ │ ├── Element.php │ │ │ ├── Tag.php │ │ │ └── Text.php │ │ ├── XmlToArray.php │ │ ├── XmlToArrayException.php │ │ └── XmlToArrayNode.php │ │ └── XmlDataHandler.php └── logs │ └── .gitignore └── tests ├── bootstrap.php └── unit ├── AbstractClassTest.php ├── AbstractDataHandlerTest.php ├── AbstractHttpTest.php ├── AbstractWrapperTest.php ├── BillcodeDetailsTest.php ├── BillcodeTest.php ├── FileLoggerTest.php ├── HttpCurlTest.php ├── HttpSocketTest.php ├── IdealBanksTest.php ├── IdealNotificationTest.php ├── IdealTest.php ├── MultipayTest.php ├── NotificationTest.php ├── PaycodeAbstractTest.php ├── PaycodeDetailsAbstractTest.php ├── PaycodeDetailsTest.php ├── PaycodeTest.php ├── RefundTest.php ├── SofortLibTest.xml ├── SofortObject.php ├── SofortUeberweisungTest.php ├── TestWrapper.php ├── TransactionDataTest.php └── Xml ├── ArrayToXmlTest.php ├── XmlToArrayNodeTest.php └── XmlToArrayTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.project 3 | /vimrc 4 | /.DS_Store 5 | /vendor 6 | /composer.lock 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | - 5.6 7 | - 7.0 8 | - 7.1 9 | 10 | before_script: 11 | - composer install 12 | 13 | script: 14 | - vendor/bin/phpunit -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ========================= 2 | SofortLib PHP @ SOFORT GmbH 3 | ========================= 4 | 5 | v3.0.6 6 | ------ 7 | Date: 2016-09-16 8 | 9 | SOFORT GmbH 10 | Fixed https://github.com/sofort/sofortlib-php/issues/10 11 | Code cleanup and housekeeping 12 | 13 | v3.0.5 14 | ------ 15 | Date: 2016-01-21 16 | 17 | SOFORT GmbH 18 | Merge pull request #7 from vojtasvoboda/feature/transaction-id-example 19 | Update payment example 20 | 21 | v3.0.4 22 | ---------------- 23 | Date: 2015-11-26 24 | 25 | SOFORT GmbH 26 | removed static urls from examples 27 | 28 | v3.0.3 29 | ---------------- 30 | Date: 2015-10-XX 31 | 32 | SOFORT GmbH 33 | Added productCode param in Multipay setPurpose function 34 | 35 | v3.0.1 36 | ---------------- 37 | Date: 2015-06-XX 38 | 39 | SOFORT GmbH 40 | Changed legal form 41 | 42 | 43 | v3.0.0 44 | ---------------- 45 | Date: 2015-04-XX 46 | 47 | SOFORT AG 48 | Added namespaces and composer 49 | 50 | 51 | v2.2.0 52 | ---------------- 53 | Date: 2015-04-XX 54 | 55 | SOFORT AG 56 | Merged the different modules (bill-, paycode, ideal, payment, refund) into one Lib 57 | 58 | 59 | v2.1.2 60 | ---------------- 61 | Date: 2014-12-02 62 | 63 | SOFORT AG 64 | Adjustments for SEPA support 65 | 66 | 67 | v2.1.1 68 | ---------------- 69 | Date: 2014-07-10 70 | 71 | SOFORT AG 72 | Adjustments for SEPA support 73 | 74 | 75 | 76 | v2.1.0 77 | ---------------- 78 | Date: 2014-05-15 79 | 80 | SOFORT AG 81 | Cleaning code 82 | 83 | 84 | v2.0.1 85 | ---------------- 86 | Date: 2013-10-23 87 | 88 | SOFORT AG 89 | Paycode/Billcode integration 90 | 91 | 92 | v2.0.0 93 | ---------------- 94 | Date: 2013-05-22 95 | 96 | SOFORT AG 97 | Initial release 98 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2016 SOFORT GmbH 2 | 3 | Released under the GNU LESSER GENERAL PUBLIC LICENSE 4 | 5 | http://www.gnu.org/licenses/lgpl.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SofortLib-PHP @ SOFORT GmbH 2 | 3 | [![Build Status](https://travis-ci.org/sofort/sofortlib-php.svg)](https://travis-ci.org/sofort/sofortlib-php) 4 | 5 | This documentation explains the SofortLib PHP, its parts, how to set it up and how to test it. 6 | 7 | ## DESCRIPTION 8 | 9 | Integrate the SofortLib PHP into your project to communicate via PHP with the SOFORT API. 10 | 11 | Find out more about the SOFORT API/SDK here: 12 | https://www.sofort.com/integrationCenter-eng-DE/integration/API-SDK/ 13 | 14 | SofortLib PHP Supports the following SOFORT Products: 15 | 16 | 1. SOFORT Überweisung (SOFORT Banking/Payment) 17 | 2. SOFORT Paycode 18 | 3. SOFORT Billcode 19 | 4. Refund 20 | 5. iDEAL 21 | 22 | 23 | ## Install 24 | 25 | Install the `sofort/sofortlib-php` package using composer: 26 | 27 | ```json 28 | { 29 | "require": { 30 | "sofort/sofortlib-php": "3.*" 31 | } 32 | } 33 | ``` 34 | 35 | 36 | ## SofortLib Package 37 | 38 | The SofortLib PHP package contains the following: 39 | 40 | - the `/src` directory with the class-files 41 | - an `/examples` folder, with examples of usage 42 | - the folder `/test` with the unittests (for PHP Unit). 43 | 44 | 45 | 46 | ## Functionality 47 | 48 | - initiate a SOFORT Überweisung 49 | - create/initiate a SOFORT Überweisung Paycode 50 | - create/initiate a SOFORT Überweisung Billcode 51 | - getting the details for one or more transactions 52 | - getting the details for a period and/or status 53 | - convert received XML to a PHP Object 54 | - marking refunds 55 | - getting the current iDEAL Bank list 56 | - generate a forward URL for the iDEAL payment data 57 | - creating checksum/hash for iDEAL Payment data 58 | - creating checksum/hash for iDEAL Notifications 59 | 60 | 61 | ## Usage 62 | 63 | Find examples of usage for the different modules in the `/examples` directory. 64 | 65 | ## Testing 66 | 67 | Run the tests 68 | 69 | ``` 70 | ./vendor/bin/phpunit 71 | ``` 72 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sofort/sofortlib-php", 3 | "description": "SOFORT API wrapper for PHP", 4 | "license": "LGPL-3", 5 | "authors": [ 6 | { 7 | "name": "Sofort GmbH", 8 | "email": "opensource@sofort.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=5.3.10" 13 | }, 14 | "minimum-stability": "stable", 15 | "require-dev": { 16 | "phpunit/phpunit": "~4.5.1" 17 | }, 18 | "suggest": { 19 | "ext-curl": "*" 20 | }, 21 | "autoload": { 22 | "psr-0": {"Sofort\\SofortLib\\": "src"} 23 | }, 24 | "autoload-dev": { 25 | "psr-4": {"Sofort\\SofortLib\\": "tests/unit"} 26 | } 27 | } -------------------------------------------------------------------------------- /examples/Billcode.php: -------------------------------------------------------------------------------- 1 | setAmount(5.55) 14 | ->setCurrencyCode('EUR') 15 | ->setSenderBankCode('00000') 16 | ->setReason('Reason Line 1', 'Reason Line 2') 17 | ->setSuccessUrl('http://www.google.de') 18 | ->setSuccessLinkRedirect(0) 19 | ->setAbortUrl('http://www.sofort.com') 20 | ->setNotificationUrl('http://www.diesundjenes.de/notify') 21 | ->setUserVariable('schwuppsen') 22 | // ->setLanguageCode('de') 23 | // ->setVersion('4711-08/15') 24 | // ->setEndDate('2014-10-10 23:59:59') 25 | // ->setSenderIban('00000') 26 | // ->setSenderBic('SKGIDE5FXXX') 27 | // ->setSenderCountryCode('de') 28 | ; 29 | 30 | //echo '
' . print_r($SofortBillcode, true) . '
'; 31 | 32 | $SofortLibBillcode->createBillcode(); 33 | 34 | if($SofortLibBillcode->isError()) { 35 | // SOFORT-API didn't accept the data 36 | echo $SofortLibBillcode->getError(); 37 | } else { 38 | // Retrieve Billcode or Billcode URL 39 | echo $SofortLibBillcode->getBillcode(); 40 | echo '
'; 41 | echo $SofortLibBillcode->getBillcodeUrl(); 42 | 43 | //echo '
' . print_r($SofortLibBillcode, true) . '
'; 44 | } 45 | -------------------------------------------------------------------------------- /examples/BillcodeDetails.php: -------------------------------------------------------------------------------- 1 | setAmount(5.55) 13 | ->setCurrencyCode('EUR') 14 | ->setSenderBankCode('00000') 15 | ->setReason('Reason Line 1', 'Reason Line 2') 16 | ->setSuccessUrl('http://www.google.de') 17 | ->setSuccessLinkRedirect(0) 18 | ->setAbortUrl('http://www.sofort.com') 19 | ->setNotificationUrl('http://www.diesundjenes.de/notify') 20 | ->setUserVariable('schwuppsen') 21 | // ->setLanguageCode('de') 22 | // ->setVersion('4711-08/15') 23 | // ->setEndDate('2014-10-10 23:59:59') 24 | // ->setSenderIban('00000') 25 | // ->setSenderBic('SKGIDE5FXXX') 26 | // ->setSenderCountryCode('de') 27 | ; 28 | 29 | $SofortLibBillcode->createBillcode(); 30 | 31 | if($SofortLibBillcode->isError()) { 32 | // SOFORT-API didn't accept the data 33 | echo $SofortLibBillcode->getError(); 34 | } else { 35 | // Retrieve Paycode or Paycode URL 36 | require_once(dirname(__FILE__) . '/../src/BillcodeDetails.php'); 37 | 38 | $SofortLibBillcodeDetails = new BillcodeDetails($configkey); 39 | 40 | $SofortLibBillcodeDetails->setBillcode($SofortLibBillcode->getBillcode()); 41 | 42 | $SofortLibBillcodeDetails->sendRequest(); 43 | 44 | echo $SofortLibBillcodeDetails->getStatus().'
'; 45 | echo $SofortLibBillcodeDetails->getProjectId().'
'; 46 | echo $SofortLibBillcodeDetails->getTransaction().'
'; 47 | echo $SofortLibBillcodeDetails->getAmount().'
'; 48 | echo $SofortLibBillcodeDetails->getReason().'
'; 49 | echo $SofortLibBillcodeDetails->getReason(0).'
'; 50 | echo $SofortLibBillcodeDetails->getReason(1).'
'; 51 | echo $SofortLibBillcodeDetails->getTimeCreated().'
'; 52 | echo $SofortLibBillcodeDetails->getStartDate().'
'; 53 | echo $SofortLibBillcodeDetails->getTimeUsed().'
'; 54 | echo $SofortLibBillcodeDetails->getEndDate().'
'; 55 | echo $SofortLibBillcodeDetails->getCurrencyCode().'
'; 56 | echo $SofortLibBillcodeDetails->getLanguageCode().'
'; 57 | echo $SofortLibBillcodeDetails->getSenderBankCode().'
'; 58 | echo $SofortLibBillcodeDetails->getSenderCountryCode().'
'; 59 | echo $SofortLibBillcodeDetails->getSenderBic().'
'; 60 | echo $SofortLibBillcodeDetails->getUserVariable().'
'; 61 | echo $SofortLibBillcodeDetails->getUserVariable(0).'
'; 62 | 63 | //echo '
' . print_r($SofortLibBillcodeDetails, true) . '
'; 64 | } -------------------------------------------------------------------------------- /examples/Ideal.php: -------------------------------------------------------------------------------- 1 | setReason('Testzweck', 'Testzweck4'); 15 | $SofortIdeal->setAmount(10); 16 | //$SofortIdeal->setSenderAccountNumber('2345678902'); 17 | $SofortIdeal->setSenderBankCode('31'); 18 | $SofortIdeal->setSenderCountryId('NL'); 19 | $SofortIdeal->setSuccessUrl('http://www.yourdomain.org/yourshop/success.php'); 20 | $SofortIdeal->setAbortUrl('http://www.yourdomain.org/yourshop/abort.php?transaction=-TRANSACTION-'); 21 | $SofortIdeal->setNotificationUrl('http://www.yourdomain.org/yourshop/notification.php?transaction=-TRANSACTION-'); 22 | //$SofortIdeal->setVersion('Framework 0.0.1'); 23 | 24 | echo 'User should be redirected to: Link'; 25 | -------------------------------------------------------------------------------- /examples/IdealBanks.php: -------------------------------------------------------------------------------- 1 | sendRequest(); 11 | 12 | print_r($SofortLibIdealBanks->getBanks()); 13 | -------------------------------------------------------------------------------- /examples/Paycode.php: -------------------------------------------------------------------------------- 1 | setAmount(5.55) 13 | // ->setLanguageCode('de') 14 | // ->setVersion('4711-08/15') 15 | // ->setEndDate('2014-10-10 23:59:59') 16 | ->setCurrencyCode('EUR') 17 | // ->setSenderBankCode('00000') 18 | // ->setSenderIban('00000') 19 | // ->setSenderBic('SKGIDE5FXXX') 20 | // ->setSenderCountryCode('de') 21 | ->setReason('Reason Line 1', 'Reason Line 2') 22 | ->setSuccessUrl('http://www.google.de') 23 | ->setSuccessLinkRedirect(0) 24 | ->setAbortUrl('http://www.sofort.com') 25 | ->setNotificationUrl('http://www.diesundjenes.de/notify') 26 | ->setUserVariable('schwuppsen'); 27 | 28 | $SofortLibPaycode->createPaycode(); 29 | 30 | if($SofortLibPaycode->isError()) { 31 | // SOFORT-API didn't accept the data 32 | echo $SofortLibPaycode->getError(); 33 | } else { 34 | // Retrieve Paycode or Paycode URL 35 | echo $SofortLibPaycode->getPaycode(); 36 | echo '
'; 37 | echo $SofortLibPaycode->getPaycodeUrl(); 38 | 39 | //echo '
' . print_r($SofortLibPaycode, true) . '
'; 40 | } 41 | -------------------------------------------------------------------------------- /examples/PaycodeDetails.php: -------------------------------------------------------------------------------- 1 | setAmount(5.55) 13 | // ->setLanguageCode('de') 14 | // ->setVersion('4711-08/15') 15 | // ->setEndDate('2014-10-10 23:59:59') 16 | ->setCurrencyCode('EUR') 17 | // ->setSenderBankCode('00000') 18 | // ->setSenderIban('00000') 19 | // ->setSenderBic('SKGIDE5FXXX') 20 | // ->setSenderCountryCode('de') 21 | ->setReason('Reason Line 1', 'Reason Line 2') 22 | ->setSuccessUrl('http://www.google.de') 23 | ->setSuccessLinkRedirect(0) 24 | ->setAbortUrl('http://www.sofort.com') 25 | ->setNotificationUrl('http://www.diesundjenes.de/notify') 26 | ->setUserVariable('schwuppsen'); 27 | 28 | $SofortLibPaycode->createPaycode(); 29 | 30 | if($SofortLibPaycode->isError()) { 31 | // SOFORT-API didn't accept the data 32 | echo $SofortLibPaycode->getError(); 33 | } else { 34 | // Retrieve Paycode or Paycode URL 35 | $SofortPaycodeDetails = new PaycodeDetails($configkey); 36 | 37 | $SofortPaycodeDetails->setPaycode($SofortLibPaycode->getPaycode()); 38 | 39 | $SofortPaycodeDetails->sendRequest(); 40 | 41 | echo $SofortPaycodeDetails->getStatus().'
'; 42 | echo $SofortPaycodeDetails->getProjectId().'
'; 43 | echo $SofortPaycodeDetails->getTransaction().'
'; 44 | echo $SofortPaycodeDetails->getAmount().'
'; 45 | echo $SofortPaycodeDetails->getReason().'
'; 46 | echo $SofortPaycodeDetails->getReason(0).'
'; 47 | echo $SofortPaycodeDetails->getReason(1).'
'; 48 | echo $SofortPaycodeDetails->getStartDate().'
'; 49 | echo $SofortPaycodeDetails->getTimeCreated().'
'; 50 | echo $SofortPaycodeDetails->getTimeUsed().'
'; 51 | echo $SofortPaycodeDetails->getEndDate().'
'; 52 | echo $SofortPaycodeDetails->getCurrencyCode().'
'; 53 | echo $SofortPaycodeDetails->getLanguageCode().'
'; 54 | echo $SofortPaycodeDetails->getSenderBankCode().'
'; 55 | echo $SofortPaycodeDetails->getSenderCountryCode().'
'; 56 | echo $SofortPaycodeDetails->getSenderBic().'
'; 57 | echo $SofortPaycodeDetails->getUserVariable().'
'; 58 | echo $SofortPaycodeDetails->getUserVariable(0).'
'; 59 | 60 | //echo '
' . print_r($SofortPaycodeDetails, true) . '
'; 61 | } -------------------------------------------------------------------------------- /examples/Refund.php: -------------------------------------------------------------------------------- 1 | setSenderSepaAccount('SFRTDE20XXX', 'DE11888888889999999999', 'Max Mustermann'); 12 | $transactionId = '00907-01222-50D43927-FFDF'; 13 | $SofortLibRefund->addRefund($transactionId, 1, '17:43 auf gehts'); 14 | $SofortLibRefund->setPartialRefundId('454545'); 15 | $SofortLibRefund->setReason('reason1', 'reason2'); 16 | 17 | 18 | $SofortLibRefund->sendRequest(); 19 | 20 | 21 | if($SofortLibRefund->isError()) { 22 | // SOFORT-API didn't accept the data 23 | echo $SofortLibRefund->getError(); 24 | } else { 25 | // buyer must be redirected to $paymentUrl else payment cannot be successfully completed! 26 | $paymentUrl = $SofortLibRefund->getPaymentUrl(); 27 | header('Location: '.$paymentUrl); 28 | } 29 | 30 | /* 31 | echo $SofortLibRefund->getSenderHolder().'
'; 32 | echo $SofortLibRefund->getSenderBic().'
'; 33 | echo $SofortLibRefund->getSenderIban().'
'; 34 | echo $SofortLibRefund->getTitle().'
'; 35 | echo $SofortLibRefund->getPain().'
'; 36 | echo $SofortLibRefund->getRecipientBankName(0).'
'; 37 | echo $SofortLibRefund->getRecipientHolder(0).'
'; 38 | echo $SofortLibRefund->getRecipientBic(0).'
'; 39 | echo $SofortLibRefund->getRecipientIban(0).'
'; 40 | echo $SofortLibRefund->getTransactionId(0).'
'; 41 | echo $SofortLibRefund->getAmount(0).'
'; 42 | echo $SofortLibRefund->getComment(0).'
'; 43 | echo $SofortLibRefund->getStatus(0).'
'; 44 | echo $SofortLibRefund->getTime(0).'
'; 45 | echo $SofortLibRefund->getPartialRefundId(0).'
'; 46 | */ -------------------------------------------------------------------------------- /examples/Sofortueberweisung.php: -------------------------------------------------------------------------------- 1 | setAmount(10.21); 13 | $Sofortueberweisung->setCurrencyCode('EUR'); 14 | $Sofortueberweisung->setReason('Testueberweisung', 'Verwendungszweck'); 15 | $Sofortueberweisung->setSuccessUrl('YOUR_SUCCESS_URL', true); // i.e. http://my.shop/order/success 16 | $Sofortueberweisung->setAbortUrl('YOUR_ABORT_URL'); 17 | // $Sofortueberweisung->setSenderSepaAccount('SFRTDE20XXX', 'DE06000000000023456789', 'Max Mustermann'); 18 | // $Sofortueberweisung->setSenderCountryCode('DE'); 19 | // $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL', 'loss,pending'); 20 | // $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL', 'loss'); 21 | // $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL', 'pending'); 22 | // $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL', 'received'); 23 | // $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL', 'refunded'); 24 | $Sofortueberweisung->setNotificationUrl('YOUR_NOTIFICATION_URL'); 25 | //$Sofortueberweisung->setCustomerprotection(true); 26 | 27 | 28 | $Sofortueberweisung->sendRequest(); 29 | 30 | if($Sofortueberweisung->isError()) { 31 | // SOFORT-API didn't accept the data 32 | echo $Sofortueberweisung->getError(); 33 | } else { 34 | // get unique transaction-ID useful for check payment status 35 | $transactionId = $Sofortueberweisung->getTransactionId(); 36 | // buyer must be redirected to $paymentUrl else payment cannot be successfully completed! 37 | $paymentUrl = $Sofortueberweisung->getPaymentUrl(); 38 | header('Location: '.$paymentUrl); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /examples/TransactionData.php: -------------------------------------------------------------------------------- 1 | getNotification(file_get_contents('php://input')); 15 | 16 | //echo $SofortLib_Notification->getTransactionId(); 17 | //echo '
'; 18 | //echo $SofortLib_Notification->getTime(); 19 | //echo '
'; 20 | 21 | $SofortLibTransactionData = new TransactionData($configkey); 22 | 23 | // If SofortLib_Notification returns a transaction_id: 24 | $SofortLibTransactionData->addTransaction($TestNotification); 25 | 26 | //$SofortLibTransactionData->addTransaction(array('00907-01222-50F00112-D86E', '00907-01222-50EFFC79-7E33')); 27 | //$SofortLibTransactionData->addTransaction(array('00907-37660-51D2CD5E-8182')); 28 | //$SofortLibTransactionData->addTransaction('00907-01222-51ADD8C9-86C8'); 29 | 30 | // By default without setter Api version 1.0 will be used due to backward compatibility, please set ApiVersion to 31 | // latest version. Please note that the response might have a different structure and values For more details please 32 | // see our Api documentation on https://www.sofort.com/integrationCenter-ger-DE/integration/API-SDK/ 33 | $SofortLibTransactionData->setApiVersion('2.0'); 34 | 35 | //$SofortLibTransactionData->setTime('2012-11-14T18:00+02:00', '2012-12-13T00:00+02:00'); 36 | //$SofortLibTransactionData->setNumber(5, 1); 37 | 38 | $SofortLibTransactionData->sendRequest(); 39 | 40 | 41 | $output = array(); 42 | $methods = array( 43 | 'getAmount' => '', 44 | 'getAmountRefunded' => '', 45 | 'getCount' => '', 46 | 'getPaymentMethod' => '', 47 | 'getConsumerProtection' => '', 48 | 'getStatus' => '', 49 | 'getStatusReason' => '', 50 | 'getStatusModifiedTime' => '', 51 | 'getLanguageCode' => '', 52 | 'getCurrency' => '', 53 | 'getTransaction' => '', 54 | 'getReason' => array(0,0), 55 | 'getUserVariable' => 0, 56 | 'getTime' => '', 57 | 'getProjectId' => '', 58 | 'getRecipientHolder' => '', 59 | 'getRecipientAccountNumber' => '', 60 | 'getRecipientBankCode' => '', 61 | 'getRecipientCountryCode' => '', 62 | 'getRecipientBankName' => '', 63 | 'getRecipientBic' => '', 64 | 'getRecipientIban' => '', 65 | 'getSenderHolder' => '', 66 | 'getSenderAccountNumber' => '', 67 | 'getSenderBankCode' => '', 68 | 'getSenderCountryCode' => '', 69 | 'getSenderBankName' => '', 70 | 'getSenderBic' => '', 71 | 'getSenderIban' => '', 72 | ); 73 | 74 | foreach($methods as $method => $params) { 75 | if(count($params) == 2) { 76 | $output[] = $method . ': ' . $SofortLibTransactionData->$method($params[0], $params[1]); 77 | } else if($params !== '') { 78 | $output[] = $method . ': ' . $SofortLibTransactionData->$method($params); 79 | } else { 80 | $output[] = $method . ': ' . $SofortLibTransactionData->$method(); 81 | } 82 | } 83 | 84 | if($SofortLibTransactionData->isError()) { 85 | echo $SofortLibTransactionData->getError(); 86 | } else { 87 | echo implode('
', $output); 88 | } 89 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | tests 20 | 21 | 22 | 23 | 24 | src/ 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Sofort/SofortLib/AbstractDataHandler.php: -------------------------------------------------------------------------------- 1 | setConfigKey($configKey); 98 | } 99 | 100 | 101 | /** 102 | * Getter for the apiKey 103 | * 104 | * @return string 105 | */ 106 | public function getApiKey() 107 | { 108 | return $this->_apiKey; 109 | } 110 | 111 | 112 | /** 113 | * Returns the connection, normally a http instance 114 | * 115 | * @return AbstractHttp Object 116 | */ 117 | public function getConnection() 118 | { 119 | return $this->_Connection; 120 | } 121 | 122 | 123 | /** 124 | * Getter for the projectId 125 | * 126 | * @return string 127 | */ 128 | public function getProjectId() 129 | { 130 | return $this->_projectId; 131 | } 132 | 133 | 134 | /** 135 | * Getter for the raw request data 136 | * 137 | * @return string 138 | */ 139 | public function getRawRequest() 140 | { 141 | return $this->_rawRequest; 142 | } 143 | 144 | 145 | /** 146 | * Getter for the raw response data 147 | * 148 | * @return string 149 | */ 150 | public function getRawResponse() 151 | { 152 | return $this->_rawResponse; 153 | } 154 | 155 | 156 | /** 157 | * Getter for the request 158 | * 159 | * @return mixed 160 | */ 161 | public function getRequest() 162 | { 163 | return $this->_request; 164 | } 165 | 166 | 167 | /** 168 | * Getter for the response 169 | * 170 | * @return mixed 171 | */ 172 | public function getResponse() 173 | { 174 | return $this->_response; 175 | } 176 | 177 | 178 | /** 179 | * Getter for the userId 180 | * 181 | * @return string 182 | */ 183 | public function getUserId() 184 | { 185 | return $this->_userId; 186 | } 187 | 188 | 189 | abstract function handle($data); 190 | 191 | 192 | abstract function sendMessage($data); 193 | 194 | 195 | /** 196 | * Setter for the apiKey 197 | * 198 | * @param string $apiKey 199 | * @return AbstractDataHandler $this 200 | */ 201 | public function setApiKey($apiKey) 202 | { 203 | $this->_apiKey = $apiKey; 204 | 205 | return $this; 206 | } 207 | 208 | 209 | /** 210 | * Setting the configKey and extracting userId, projectId and apiKey from configKey 211 | * 212 | * @param string $configKey 213 | * @return AbstractDataHandler $this 214 | */ 215 | public function setConfigKey($configKey) 216 | { 217 | $this->_configKey = $configKey; 218 | list($this->_userId, $this->_projectId, $this->_apiKey) = explode(':', $configKey); 219 | 220 | return $this; 221 | } 222 | 223 | 224 | /** 225 | * Setting the connection (standard: http instance) and the configkey 226 | * 227 | * @param string $Connection 228 | * @return AbstractDataHandler $this 229 | */ 230 | public function setConnection($Connection) 231 | { 232 | $this->_Connection = $Connection; 233 | $this->_Connection->setConfigKey($this->_configKey); 234 | 235 | return $this; 236 | } 237 | 238 | 239 | /** 240 | * Setter for the projectId 241 | * 242 | * @param string $projectId 243 | * @return AbstractDataHandler $this 244 | */ 245 | public function setProjectId($projectId) 246 | { 247 | $this->_projectId = $projectId; 248 | 249 | return $this; 250 | } 251 | 252 | 253 | /** 254 | * Setter for the userId 255 | * 256 | * @param string $userId 257 | * @return AbstractDataHandler $this 258 | */ 259 | public function setUserId($userId) 260 | { 261 | $this->_userId = $userId; 262 | 263 | return $this; 264 | } 265 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/AbstractHttp.php: -------------------------------------------------------------------------------- 1 | url = $url; 121 | $this->compression = $compression; 122 | $this->proxy = $proxy; 123 | 124 | return $this; 125 | } 126 | 127 | 128 | /** 129 | * Send data to server with POST request 130 | * 131 | * @param string $data 132 | * @param string|bool $url (optional) 133 | * @param string|bool $headers (optional) 134 | * @return string 135 | */ 136 | public abstract function post($data, $url = null, $headers = null); 137 | 138 | 139 | /** 140 | * HTTP error handling 141 | * 142 | * @return array(code, message, response) [if available] 143 | */ 144 | public function getHttpCode() 145 | { 146 | switch ($this->httpStatus) { 147 | case(200): 148 | return array( 149 | 'code' => 200, 150 | 'message' => $this->_xmlError($this->httpStatus, 'OK'), 151 | 'response' => $this->_response 152 | ); 153 | break; 154 | case(301): 155 | case(302): 156 | return array( 157 | 'code' => $this->httpStatus, 158 | 'message' => $this->_xmlError($this->httpStatus, 'Redirected Request'), 159 | 'response' => $this->_response 160 | ); 161 | break; 162 | case(401): 163 | $this->error = 'Unauthorized'; 164 | 165 | return array( 166 | 'code' => 401, 167 | 'message' => $this->_xmlError($this->httpStatus, $this->error), 168 | 'response' => $this->_response 169 | ); 170 | break; 171 | case(0): 172 | case(404): 173 | $this->httpStatus = 404; 174 | $this->error = 'URL not found ' . $this->url; 175 | 176 | return array( 177 | 'code' => 404, 178 | 'message' => $this->_xmlError($this->httpStatus, $this->error), 179 | 'response' => '' 180 | ); 181 | break; 182 | case(500): 183 | $this->error = 'An error occurred'; 184 | 185 | return array( 186 | 'code' => 500, 187 | 'message' => $this->_xmlError($this->httpStatus, $this->error), 188 | 'response' => $this->_response 189 | ); 190 | break; 191 | default: 192 | $this->error = 'Something went wrong, not handled httpStatus'; 193 | 194 | return array( 195 | 'code' => $this->httpStatus, 196 | 'message' => $this->_xmlError($this->httpStatus, $this->error), 197 | 'response' => $this->_response 198 | ); 199 | break; 200 | } 201 | } 202 | 203 | 204 | /** 205 | * Getter for HTTP status code 206 | * 207 | * @return string 208 | */ 209 | public function getHttpStatusCode() 210 | { 211 | $status = $this->getHttpCode(); 212 | 213 | return $status['code']; 214 | } 215 | 216 | 217 | /** 218 | * Getter for HTTP status message 219 | * 220 | * @return string 221 | */ 222 | public function getHttpStatusMessage() 223 | { 224 | $status = $this->getHttpCode(); 225 | 226 | return $status['message']; 227 | } 228 | 229 | 230 | /** 231 | * Getter for information 232 | * 233 | * @param string $opt (optional) 234 | * @return string 235 | */ 236 | public function getInfo($opt = '') 237 | { 238 | if (!empty($opt)) { 239 | return $this->info[$opt]; 240 | } else { 241 | return $this->info; 242 | } 243 | } 244 | 245 | 246 | /** 247 | * Setter for configKey and parsing configKey into userId, projectId and apiKey 248 | * 249 | * @param string $configKey 250 | * @return void 251 | */ 252 | public function setConfigKey($configKey) 253 | { 254 | $this->_configKey = $configKey; 255 | list($this->_userId, $this->_projectId, $this->_apiKey) = explode(':', $configKey); 256 | $this->setHeaders(); 257 | } 258 | 259 | 260 | /** 261 | * Setting headers to be sent 262 | * 263 | * @return void 264 | */ 265 | public function setHeaders() 266 | { 267 | $header[] = 'Authorization: Basic ' . base64_encode($this->_userId . ':' . $this->_apiKey); 268 | $header[] = 'Content-Type: application/xml; charset=UTF-8'; 269 | $header[] = 'Accept: application/xml; charset=UTF-8'; 270 | $header[] = 'X-Powered-By: PHP/' . phpversion(); 271 | $this->headers = $header; 272 | } 273 | 274 | 275 | /** 276 | * Output an xml error 277 | * 278 | * @param string $code 279 | * @param string $message 280 | * @return string xml error 281 | */ 282 | protected function _xmlError($code, $message) 283 | { 284 | return '0' . $code . '' . $message . ''; 285 | } 286 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/AbstractLoggerHandler.php: -------------------------------------------------------------------------------- 1 | _parameters['project_id'] = $this->_projectId; 32 | parent::sendRequest(); 33 | } 34 | 35 | 36 | /** 37 | * Wrapper to get the Billcode from the response 38 | * 39 | * @return string 40 | */ 41 | public function getBillcode() 42 | { 43 | return parent::getCode(); 44 | } 45 | 46 | 47 | /** 48 | * Wrapper to get the Billcode URL 49 | * 50 | * @return string 51 | */ 52 | public function getBillcodeUrl() 53 | { 54 | return parent::getCodeUrl(); 55 | } 56 | 57 | 58 | /** 59 | * AbortURL is not available in Billcode, superclass' method will be overwritten 60 | * 61 | * @see SofortLibAbstract::setAbortUrl() 62 | * @param string $abortUrl 63 | * 64 | * @return Billcode 65 | */ 66 | public function setAbortUrl($abortUrl = '') 67 | { 68 | return $this; 69 | } 70 | 71 | 72 | /** 73 | * SuccessURL is not available in Billcode, superclass' method will be overwritten 74 | * 75 | * @see SofortLibAbstract::setSuccessUrl() 76 | * @param string $successUrl 77 | * @param bool $redirect 78 | * @return Billcode 79 | */ 80 | public function setSuccessUrl($successUrl = '', $redirect = true) 81 | { 82 | return $this; 83 | } 84 | 85 | 86 | /** 87 | * TimeoutURL is not available in Billcode, superclass' method will be overwritten 88 | * 89 | * @see SofortLibAbstract::setTimeoutUrl() 90 | * @param string $timeoutUrl 91 | * @return Billcode 92 | */ 93 | public function setTimeoutUrl($timeoutUrl = '') 94 | { 95 | return $this; 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/BillcodeDetails.php: -------------------------------------------------------------------------------- 1 | _extractValue('billcode'); 27 | } 28 | 29 | 30 | /** 31 | * Setter for the billcode of the request 32 | * 33 | * @param string $billcode 34 | * @return BillcodeDetails $this 35 | */ 36 | public function setBillcode($billcode) 37 | { 38 | $this->_parameters['billcode'] = $billcode; 39 | 40 | return $this; 41 | } 42 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Factory.php: -------------------------------------------------------------------------------- 1 | _logfilePath = ($path != '') ? $path : $srcDir . '/logs/log.txt'; 65 | $this->_errorLogfilePath = $srcDir . '/logs/error_log.txt'; 66 | $this->_warningsLogfilePath = $srcDir . '/logs/warning_log.txt'; 67 | } 68 | 69 | 70 | /** 71 | * Setting a log entry 72 | * 73 | * @param string $message 74 | * @param string $log (default = 'log') 75 | * @return bool 76 | */ 77 | public function log($message, $log = 'log') 78 | { 79 | return $this->_log($message, $log); 80 | } 81 | 82 | 83 | /** 84 | * Set the path of the logfile 85 | * 86 | * @param string $path 87 | * @return void 88 | */ 89 | public function setLogfilePath($path) 90 | { 91 | $this->_logfilePath = $path; 92 | } 93 | 94 | 95 | /** 96 | * Logs $msg to a file which path is being set by it's unified resource locator 97 | * 98 | * @param string $message 99 | * @param string $log (default = 'log') 100 | * @return bool 101 | */ 102 | protected function _log($message, $log = 'log') 103 | { 104 | switch ($log) { 105 | case 'error': 106 | $file = $this->_errorLogfilePath; 107 | break; 108 | case 'warning': 109 | $file = $this->_warningsLogfilePath; 110 | break; 111 | default: 112 | case 'log': 113 | $file = $this->_logfilePath; 114 | } 115 | 116 | if (!is_file($file)) { 117 | $this->fp = fopen($file, 'w'); 118 | fclose($this->fp); 119 | } 120 | 121 | if (is_writable($file)) { 122 | if ($log == 'log' && $this->_logRotate()) { 123 | $this->fp = fopen($file, 'w'); 124 | fclose($this->fp); 125 | } 126 | 127 | $this->fp = fopen($file, 'a'); 128 | fwrite($this->fp, '[' . date('Y-m-d H:i:s') . '] ' . $message . "\n"); 129 | fclose($this->fp); 130 | 131 | return true; 132 | } 133 | 134 | return false; 135 | } 136 | 137 | 138 | /** 139 | * Copy the content of the logfile to a backup file if file size got too large Put the old log file into a tarball 140 | * for later reference 141 | * 142 | * @return bool 143 | */ 144 | protected function _logRotate() 145 | { 146 | if (!is_writable($this->_logfilePath)) { 147 | return false; 148 | } 149 | 150 | $date = date('Y-m-d_h-i-s', time()); 151 | 152 | if (file_exists($this->_logfilePath)) { 153 | if ($this->fp != null 154 | && filesize($this->_logfilePath) != false 155 | && filesize($this->_logfilePath) >= $this->maxFilesize 156 | ) { 157 | $oldUri = $this->_logfilePath; 158 | // file ending 159 | $ending = $ext = pathinfo($oldUri, PATHINFO_EXTENSION); 160 | $newUri = dirname($oldUri) . '/log_' . $date . '.' . $ending; 161 | rename($oldUri, $newUri); 162 | 163 | if (file_exists($oldUri)) { 164 | unlink($oldUri); 165 | } 166 | 167 | return true; 168 | } 169 | } 170 | 171 | return false; 172 | } 173 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/HttpCurl.php: -------------------------------------------------------------------------------- 1 | connectionMethod = 'cURL'; 27 | 28 | if ($url === false) { 29 | $url = $this->url; 30 | } 31 | 32 | if ($headers === false) { 33 | $headers = $this->headers; 34 | } 35 | 36 | $curlOpt = array(); 37 | $headers[] = 'User-Agent: SofortLib-php/' . SOFORTLIB_VERSION . '-' . $this->connectionMethod; 38 | $curlOpt[CURLOPT_HTTPHEADER] = array_merge($headers, array('Expect:')); 39 | //print_r($curlOpt[CURLOPT_HTTPHEADER]); die(); 40 | $curlOpt[CURLOPT_POST] = 1; 41 | $curlOpt[CURLOPT_HEADER] = false; 42 | 43 | if ($this->compression !== false) { 44 | $curlOpt[CURLOPT_ENCODING] = $this->compression; 45 | } 46 | 47 | $curlOpt[CURLOPT_TIMEOUT] = 15; 48 | 49 | if ($this->proxy) { 50 | $curlOpt[CURLOPT_PROXY] = $this->proxy; 51 | } 52 | 53 | $curlOpt[CURLOPT_POSTFIELDS] = $data; 54 | $curlOpt[CURLOPT_RETURNTRANSFER] = 1; 55 | 56 | $return = $this->_curlRequest($url, $curlOpt); 57 | 58 | if ($this->error) { 59 | return $this->_xmlError('00' . $this->error, $this->_response); 60 | } 61 | 62 | return $return; 63 | } 64 | 65 | 66 | /** 67 | * Post data using curl 68 | * 69 | * @param string $url 70 | * @param array $curlOpt (optional) 71 | * @return string 72 | */ 73 | protected function _curlRequest($url, $curlOpt = array()) 74 | { 75 | $process = curl_init($url); 76 | 77 | foreach ($curlOpt as $curlKey => $curlValue) { 78 | curl_setopt($process, $curlKey, $curlValue); 79 | } 80 | 81 | $return = curl_exec($process); 82 | $this->info = curl_getinfo($process); 83 | $this->error = curl_error($process); 84 | $this->httpStatus = $this->info['http_code']; 85 | $this->_response = $return; 86 | curl_close($process); 87 | 88 | return $return; 89 | } 90 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/HttpSocket.php: -------------------------------------------------------------------------------- 1 | connectionMethod = 'Socket'; 33 | 34 | if ($url === null) { 35 | $url = $this->url; 36 | } 37 | 38 | if (!$useHeaders) { 39 | $headers = $this->headers; 40 | } else { 41 | $headers = array(); 42 | } 43 | 44 | $headers[] = 'User-Agent: SofortLib-php/' . SOFORTLIB_VERSION . '-' . $this->connectionMethod; 45 | $uri = parse_url($url); 46 | // set a fallback to connection via HTTPS 47 | $this->scheme = (isset($uri['scheme'])) ? $uri['scheme'] : 'https'; 48 | $post = (isset($uri['path'])) ? 'POST ' . $uri['path'] . ' HTTP/1.1' . "\r\n" : ''; 49 | $host = (isset($uri['host'])) ? 'HOST: ' . $uri['host'] . "\r\n" : ''; 50 | $connection = 'Connection: close' . "\r\n"; 51 | $contentLength = 'Content-Length: ' . strlen($data) . "\r\n"; 52 | $out = $post . $host . $connection . $contentLength; 53 | 54 | foreach ($headers as $header) { 55 | $out .= $header . "\r\n"; 56 | } 57 | 58 | $out .= "\r\n" . $data; 59 | $return = $this->_socketRequest($uri, $out); 60 | 61 | if ($this->error) { 62 | return $this->_xmlError('00' . $this->error, $this->_response); 63 | } 64 | 65 | preg_match('#^(.+?)\r\n\r\n(.*)#ms', $return, $body); 66 | 67 | // get status code 68 | preg_match('#HTTP/1.*([0-9]{3}).*#i', $body[1], $status); 69 | $this->info['http_code'] = $status[1]; 70 | $this->httpStatus = $status[1]; 71 | 72 | return $body[2]; 73 | } 74 | 75 | 76 | /** 77 | * This is a fallback with fsockopen if curl is not activated 78 | * we still need openssl and ssl wrapper support (PHP >= 4.3.0) 79 | * 80 | * @param string $uri 81 | * @param string $out 82 | * @return string 83 | */ 84 | protected function _socketRequest($uri, $out) 85 | { 86 | // connect to webservice 87 | $ssl = ($this->scheme === 'https') ? 'ssl://' : ''; 88 | $port = ($this->scheme === 'http') ? 80 : 443; 89 | 90 | if (!$fp = fsockopen($ssl . $uri['host'], $port, $errno, $errstr, 15)) { 91 | $this->error = 'fsockopen() failed, enable ssl and curl: ' . $errno . ' ' . $errstr; 92 | 93 | return false; 94 | } 95 | 96 | // send data 97 | stream_set_timeout($fp, 15); 98 | fwrite($fp, $out); 99 | 100 | // read response 101 | $return = ''; 102 | 103 | while (!feof($fp)) { 104 | $return .= fgets($fp, 512); 105 | } 106 | 107 | fclose($fp); 108 | 109 | return $return; 110 | } 111 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Ideal.php: -------------------------------------------------------------------------------- 1 | _password = $password; 74 | $this->_userId = $this->_parameters['user_id'] = $userId; 75 | $this->_projectId = $this->_parameters['project_id'] = $projectId; 76 | $this->_hashFunction = strtolower($hashFunction); 77 | $this->_paymentUrl = $this->_getPaymentDomain(); 78 | } 79 | 80 | 81 | /** 82 | * Get the hash value 83 | * 84 | * @param string $data string to be hashed 85 | * @param string @hashFunction (default sha1) 86 | * @return string the hash 87 | */ 88 | public function getHashHexValue($data, $hashFunction = 'sha1') 89 | { 90 | if ($hashFunction == 'sha1') { 91 | return sha1($data); 92 | } 93 | if ($hashFunction == 'md5') { 94 | return md5($data); 95 | } 96 | 97 | //mcrypt installed? 98 | if (function_exists('hash') && in_array($hashFunction, hash_algos())) { 99 | return hash($hashFunction, $data); 100 | } 101 | 102 | return false; 103 | } 104 | 105 | 106 | /** 107 | * Getter for payment URL 108 | * 109 | * @return string Url 110 | */ 111 | public function getPaymentUrl() 112 | { 113 | //fields required for hash 114 | $hashFields = $this->_hashFields; 115 | //build parameter-string for hashing 116 | $hashString = ''; 117 | 118 | foreach ($hashFields as $value) { 119 | if (array_key_exists($value, $this->_parameters)) { 120 | $hashString .= $this->_parameters[$value]; 121 | } 122 | 123 | $hashString .= '|'; 124 | } 125 | 126 | $hashString .= $this->_password; 127 | //calculate hash 128 | $hash = $this->getHashHexValue($hashString, $this->_hashFunction); 129 | $this->_parameters['hash'] = $hash; 130 | //create parameter string 131 | $paramString = ''; 132 | 133 | foreach ($this->_parameters as $key => $value) { 134 | $paramString .= $key . '=' . urlencode($value) . '&'; 135 | } 136 | 137 | $paramString = substr($paramString, 0, -1); //remove last "&" 138 | 139 | return $this->_paymentUrl . '?' . $paramString; 140 | } 141 | 142 | 143 | /** 144 | * Set the url where you want forward after successful transaction 145 | * 146 | * @param string $abortUrl url 147 | * @return Ideal $this 148 | */ 149 | public function setAbortUrl($abortUrl) 150 | { 151 | $this->_parameters['user_variable_4'] = $abortUrl; 152 | 153 | return $this; 154 | } 155 | 156 | 157 | /** 158 | * Setter for Amount 159 | * 160 | * @param float $amount 161 | * @return Ideal 162 | */ 163 | public function setAmount($amount = 0.00) 164 | { 165 | $this->_setAmount($amount); 166 | 167 | return $this; 168 | } 169 | 170 | 171 | /** 172 | * Set the url where you want notification about status changes 173 | * being sent to. Use SofortLibTransactionData 174 | * to further process that notification 175 | * 176 | * @param string $notificationUrl url 177 | * @param string $notifyOn 178 | * @return Ideal 179 | */ 180 | public function setNotificationUrl($notificationUrl, $notifyOn = '') 181 | { 182 | $this->_parameters['user_variable_5'] = $notificationUrl; 183 | 184 | return $this; 185 | } 186 | 187 | 188 | /** 189 | * Set the reason (Verwendungszweck) for sending money 190 | * 191 | * @param string $reason1 192 | * @param string $reason2 (optional) 193 | * @param string $productCode (unused in this implementation) 194 | * 195 | * @return Ideal 196 | */ 197 | public function setReason($reason1, $reason2 = '', $productCode = null) 198 | { 199 | $this->_parameters['reason_1'] = preg_replace('#[^a-zA-Z0-9+-\.,]#', ' ', $reason1); 200 | $this->_parameters['reason_2'] = preg_replace('#[^a-zA-Z0-9+-\.,]#', ' ', $reason2); 201 | 202 | return $this; 203 | } 204 | 205 | 206 | /** 207 | * Setter for sender's account number 208 | * 209 | * @param string $senderAccountNumber 210 | * @return string 211 | */ 212 | public function setSenderAccountNumber($senderAccountNumber) 213 | { 214 | $this->_parameters['sender_account_number'] = $senderAccountNumber; 215 | 216 | return $this; 217 | } 218 | 219 | 220 | /** 221 | * Set sender's bank code 222 | * 223 | * @param string $senderBankCode 224 | * @return Ideal 225 | */ 226 | public function setSenderBankCode($senderBankCode) 227 | { 228 | $this->_parameters['sender_bank_code'] = $senderBankCode; 229 | 230 | return $this; 231 | } 232 | 233 | 234 | /** 235 | * Set sender's country id 236 | * 237 | * @param string $senderCountryId (default NL) 238 | * @return Ideal 239 | */ 240 | public function setSenderCountryId($senderCountryId = 'NL') 241 | { 242 | $this->_parameters['sender_country_id'] = $senderCountryId; 243 | 244 | return $this; 245 | } 246 | 247 | 248 | /** 249 | * Setter for sender and holder 250 | * 251 | * @param string $senderHolder 252 | * @return Ideal 253 | */ 254 | public function setSenderHolder($senderHolder) 255 | { 256 | $this->_parameters['sender_holder'] = $senderHolder; 257 | 258 | return $this; 259 | } 260 | 261 | 262 | /** 263 | * The customer will be redirected to this url after a successful 264 | * transaction, this should be a page where a short confirmation is 265 | * displayed 266 | * 267 | * @param string $successUrl url 268 | * @param bool $redirect (default true) 269 | * @return Ideal 270 | */ 271 | public function setSuccessUrl($successUrl, $redirect = true) 272 | { 273 | $this->_parameters['user_variable_3'] = $successUrl; 274 | $this->setSuccessLinkRedirect($redirect); 275 | 276 | return $this; 277 | } 278 | 279 | 280 | /** 281 | * Getter for the payment domain 282 | * 283 | * @return string 284 | */ 285 | protected function _getPaymentDomain() 286 | { 287 | return (getenv('idealApiUrl') != '') ? getenv('idealApiUrl') : $this->_paymentUrl; 288 | } 289 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/IdealBanks.php: -------------------------------------------------------------------------------- 1 | _rootTag = 'ideal'; 35 | 36 | if ($apiUrl == '') { 37 | $apiUrl = (getenv('idealApiUrl') != '') ? getenv('idealApiUrl') . '/banks' : self::IDEAL_BANKS_URL; 38 | } 39 | 40 | parent::__construct($configKey, $apiUrl); 41 | } 42 | 43 | 44 | /** 45 | * Getter for bank list 46 | * 47 | * @return array 48 | */ 49 | public function getBanks() 50 | { 51 | return $this->_banks; 52 | } 53 | 54 | 55 | /** 56 | * Parse the xml (override) 57 | * 58 | * @see SofortLib_Abstract::_parse() 59 | * @return void 60 | */ 61 | protected function _parse() 62 | { 63 | if (isset($this->_response['ideal']['banks']['bank'][0]['code']['@data'])) { 64 | foreach ($this->_response['ideal']['banks']['bank'] as $key => $bank) { 65 | $this->_banks[$key]['code'] = $bank['code']['@data']; 66 | $this->_banks[$key]['name'] = $bank['name']['@data']; 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/IdealNotification.php: -------------------------------------------------------------------------------- 1 | _password = $password; 77 | $this->_userId = $userId; 78 | $this->_projectId = $projectId; 79 | $this->_hashFunction = strtolower($hashFunction); 80 | $this->_statusReason = false; 81 | } 82 | 83 | 84 | /** 85 | * Getter for amount 86 | * 87 | * @return float 88 | */ 89 | public function getAmount() 90 | { 91 | return $this->params['amount']; 92 | } 93 | 94 | 95 | /** 96 | * Getter for currency 97 | * 98 | * @return string 99 | */ 100 | public function getCurrency() 101 | { 102 | return $this->params['currency_id']; 103 | } 104 | 105 | 106 | /** 107 | * Get the notification details 108 | * 109 | * @param string $request (POST-Data) 110 | * @return IdealNotification $this 111 | */ 112 | public function getNotification($request) 113 | { 114 | if (array_key_exists('status_reason', $request) && !empty($request['status_reason'])) { 115 | $this->_statusReason = $request['status_reason']; 116 | } 117 | 118 | // ideal 119 | $fields = array( 120 | 'transaction', 121 | 'user_id', 122 | 'project_id', 123 | 'sender_holder', 124 | 'sender_account_number', 125 | 'sender_bank_name', 126 | 'sender_bank_bic', 127 | 'sender_iban', 128 | 'sender_country_id', 129 | 'recipient_holder', 130 | 'recipient_account_number', 131 | 'recipient_bank_code', 132 | 'recipient_bank_name', 133 | 'recipient_bank_bic', 134 | 'recipient_iban', 135 | 'recipient_country_id', 136 | 'amount', 137 | 'currency_id', 138 | 'reason_1', 139 | 'reason_2', 140 | 'user_variable_0', 141 | 'user_variable_1', 142 | 'user_variable_2', 143 | 'user_variable_3', 144 | 'user_variable_4', 145 | 'user_variable_5', 146 | 'created', 147 | ); 148 | 149 | // http-notification with status 150 | if (array_key_exists('status', $request) && !empty($request['status'])) { 151 | array_push($fields, 'status', 'status_modified'); 152 | } 153 | 154 | $this->params = array(); 155 | 156 | foreach ($fields as $key) { 157 | $this->params[$key] = $request[$key]; 158 | } 159 | 160 | $this->params['project_password'] = $this->_password; 161 | $validationHash = $this->_getHashHexValue(implode('|', $this->params), $this->_hashFunction); 162 | $messageHash = $request['hash']; 163 | $this->_hashCheck = ($validationHash === $messageHash); 164 | 165 | return $this; 166 | } 167 | 168 | 169 | /** 170 | * Getter for status 171 | * 172 | * @return string 173 | */ 174 | public function getStatus() 175 | { 176 | return $this->params['status']; 177 | } 178 | 179 | 180 | /** 181 | * Getter for status reason 182 | * 183 | * @return string 184 | */ 185 | public function getStatusReason() 186 | { 187 | return $this->_statusReason; 188 | } 189 | 190 | 191 | /** 192 | * Getter for time 193 | * 194 | * @return string 195 | */ 196 | public function getTime() 197 | { 198 | return $this->params['created']; 199 | } 200 | 201 | 202 | /** 203 | * Getter for transactionId 204 | * 205 | * @return string 206 | */ 207 | public function getTransaction() 208 | { 209 | return $this->params['transaction']; 210 | } 211 | 212 | 213 | /** 214 | * Getter for user variables 215 | * 216 | * @param int $i (default 0) 217 | * @return string 218 | */ 219 | public function getUserVariable($i = 0) 220 | { 221 | return $this->params['user_variable_' . $i]; 222 | } 223 | 224 | 225 | /** 226 | * Getter for Hash Hex Value 227 | * 228 | * @param string $data string to be hashed 229 | * @param string $hashFunction (default sha1) 230 | * @return string the hash 231 | */ 232 | protected function _getHashHexValue($data, $hashFunction = 'sha1') 233 | { 234 | if ($hashFunction == 'sha1') { 235 | return sha1($data); 236 | } 237 | 238 | if ($hashFunction == 'md5') { 239 | return md5($data); 240 | } 241 | 242 | // mcrypt installed? 243 | if (function_exists('hash') && in_array($hashFunction, hash_algos())) { 244 | return hash($hashFunction, $data); 245 | } 246 | 247 | return false; 248 | } 249 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Multipay.php: -------------------------------------------------------------------------------- 1 | _paymentUrl = isset($this->_response['new_transaction']['payment_url']['@data']) 47 | ? $this->_response['new_transaction']['payment_url']['@data'] 48 | : false; 49 | 50 | return $this->_paymentUrl; 51 | } 52 | 53 | 54 | /** 55 | * Getter for reasons 56 | * 57 | * @return string 58 | */ 59 | public function getReason() 60 | { 61 | if (isset($this->_parameters['reasons']['reason'])) { 62 | return $this->_parameters['reasons']['reason']; 63 | } else { 64 | return false; 65 | } 66 | } 67 | 68 | 69 | /** 70 | * After configuration and sending this request you can use this function to get the transactions transaction-ID 71 | * 72 | * @return string 73 | */ 74 | public function getTransactionId() 75 | { 76 | $this->_transaction = isset($this->_response['new_transaction']['transaction']['@data']) 77 | ? $this->_response['new_transaction']['transaction']['@data'] 78 | : false; 79 | 80 | return $this->_transaction; 81 | } 82 | 83 | 84 | /** 85 | * Setter for amount 86 | * 87 | * @param float $amount 88 | * @return Multipay $this 89 | */ 90 | public function setAmount($amount = 0.00) 91 | { 92 | $this->_setAmount($amount); 93 | 94 | return $this; 95 | } 96 | 97 | 98 | /** 99 | * Set the email address of the customer 100 | * 101 | * @param string $customersEmail email address 102 | * @return Multipay $this 103 | */ 104 | public function setEmailCustomer($customersEmail) 105 | { 106 | $this->_parameters['email_customer'] = $customersEmail; 107 | 108 | return $this; 109 | } 110 | 111 | 112 | /** 113 | * Setter for languageCode 114 | * 115 | * @param string $languageCode | fallback EN 116 | * @return Multipay $this 117 | */ 118 | public function setLanguageCode($languageCode) 119 | { 120 | $this->_parameters['language_code'] = !empty($languageCode) ? $languageCode : 'EN'; 121 | 122 | return $this; 123 | } 124 | 125 | 126 | /** 127 | * Set the phone number of the customer 128 | * 129 | * @param string $customersPhone phone number 130 | * @return Multipay $this 131 | */ 132 | public function setPhoneCustomer($customersPhone) 133 | { 134 | $this->_parameters['phone_customer'] = $customersPhone; 135 | 136 | return $this; 137 | } 138 | 139 | 140 | /** 141 | * Setter for reasons 142 | * 143 | * @param string $reason1 144 | * @param string $reason2 (optional) defaults to empty string 145 | * @param string $productCode (optional) defaults to null 146 | * @return Multipay 147 | */ 148 | public function setReason($reason1, $reason2 = '', $productCode = null) { 149 | if (!empty($reason1)) { 150 | if (!$productCode) { 151 | $this->_parameters['reasons']['reason'] = array($reason1, $reason2); 152 | } else { 153 | $this->_parameters[$productCode]['reasons']['reason'] = array($reason1, $reason2); 154 | } 155 | } 156 | 157 | return $this; 158 | } 159 | 160 | 161 | /** 162 | * Set data of account 163 | * 164 | * @deprecated 165 | * @param string $bankCode bank code of bank 166 | * @param string $accountNumber account number 167 | * @param string $holder Name/Holder of this account 168 | * @return Multipay $this 169 | */ 170 | public function setSenderAccount($bankCode, $accountNumber, $holder) 171 | { 172 | $this->_parameters['sender'] = array( 173 | 'bank_code' => $bankCode, 174 | 'account_number' => $accountNumber, 175 | 'holder' => $holder, 176 | ); 177 | 178 | return $this; 179 | } 180 | 181 | 182 | /** 183 | * Setter for senders BIC 184 | * 185 | * @param string $bic 186 | * @return Multipay $this 187 | */ 188 | public function setSenderBic($bic) 189 | { 190 | $this->_parameters['sender']['bic'] = $bic; 191 | 192 | return $this; 193 | } 194 | 195 | 196 | /** 197 | * Setter for senders country code (ISO 3166-1) 198 | * 199 | * @param string $countryCode 200 | * @return Multipay $this 201 | */ 202 | public function setSenderCountryCode($countryCode) 203 | { 204 | $this->_parameters['sender']['country_code'] = $countryCode; 205 | 206 | return $this; 207 | } 208 | 209 | 210 | /** 211 | * Setter for senders holder (ISO 3166-1) 212 | * 213 | * @param string $holder 214 | * @return Multipay $this 215 | */ 216 | public function setSenderHolder($holder) 217 | { 218 | $this->_parameters['sender']['holder'] = $holder; 219 | 220 | return $this; 221 | } 222 | 223 | 224 | /** 225 | * Setter for senders iban 226 | * 227 | * @param string $iban 228 | * @return Multipay $this 229 | */ 230 | public function setSenderIban($iban) 231 | { 232 | $this->_parameters['sender']['iban'] = $iban; 233 | 234 | return $this; 235 | } 236 | 237 | 238 | /** 239 | * Set data of account, SEPA conform (iban & bic) 240 | * 241 | * @param string $bic bic of bank 242 | * @param string $iban iban of account 243 | * @param string $holder Name/Holder of this account 244 | * @return Multipay $this 245 | */ 246 | public function setSenderSepaAccount($bic, $iban, $holder) 247 | { 248 | $this->_parameters['sender'] = array( 249 | 'bic' => $bic, 250 | 'iban' => $iban, 251 | 'holder' => $holder, 252 | ); 253 | 254 | return $this; 255 | } 256 | 257 | 258 | /** 259 | * Timeout how long this transaction configuration will be valid for this is the time between the generation of the 260 | * payment url and the user completing the form, should be at least two to three minutes defaults to unlimited if 261 | * not set 262 | * 263 | * @param int $timeout timeout in seconds 264 | * @return Multipay $this 265 | */ 266 | public function setTimeout($timeout) 267 | { 268 | $this->_parameters['timeout'] = $timeout; 269 | 270 | return $this; 271 | } 272 | 273 | 274 | /** 275 | * Add another variable this can be your internal order-ID or multiple variables 276 | * 277 | * @param string|array $userVariable the contents of the variable 278 | * @return Multipay $this 279 | */ 280 | public function setUserVariable($userVariable) 281 | { 282 | if (!is_array($userVariable)) { 283 | $userVariable = array($userVariable); 284 | } 285 | 286 | $this->_parameters['user_variables']['user_variable'] = $userVariable; 287 | 288 | return $this; 289 | } 290 | 291 | 292 | /** 293 | * Set the version of this payment module 294 | * this is helpful so the support staff can easily find out if someone uses an outdated module 295 | * 296 | * @param string $version version string of your module 297 | * @return Multipay $this 298 | */ 299 | public function setVersion($version) 300 | { 301 | $this->_parameters['interface_version'] = $version; 302 | 303 | return $this; 304 | } 305 | 306 | 307 | /** 308 | * Setter for amount 309 | * 310 | * @param float $amount 311 | * @return Multipay $this 312 | */ 313 | protected function _setAmount($amount = 0.00) 314 | { 315 | $this->_parameters['amount'] = $amount; 316 | 317 | return $this; 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Notification.php: -------------------------------------------------------------------------------- 1 | errors['error']['message'] = 'could not parse message'; 51 | 52 | return false; 53 | } 54 | 55 | if (!isset($response['status_notification'])) { 56 | return false; 57 | } 58 | 59 | if (isset($response['status_notification']['transaction']['@data'])) { 60 | $this->_transactionId = $response['status_notification']['transaction']['@data']; 61 | 62 | if ($response['status_notification']['time']['@data']) { 63 | $this->_time = $response['status_notification']['time']['@data']; 64 | } 65 | 66 | return $this->_transactionId; 67 | } else { 68 | return false; 69 | } 70 | } 71 | 72 | 73 | /** 74 | * Getter for variable time 75 | * 76 | * @return string 77 | */ 78 | public function getTime() 79 | { 80 | return $this->_time; 81 | } 82 | 83 | 84 | /** 85 | * Getter for transaction 86 | * 87 | * @return string 88 | */ 89 | public function getTransactionId() 90 | { 91 | return $this->_transactionId; 92 | } 93 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Paycode.php: -------------------------------------------------------------------------------- 1 | _parameters['project_id'] = $this->_projectId; 53 | parent::sendRequest(); 54 | } 55 | 56 | 57 | /** 58 | * Wrapper to get the Paycode from the response 59 | * 60 | * @return string 61 | */ 62 | public function getPaycode() 63 | { 64 | return parent::getCode(); 65 | } 66 | 67 | 68 | /** 69 | * Wrapper to get the Paycode URL 70 | * 71 | * @return string 72 | */ 73 | public function getPaycodeUrl() 74 | { 75 | return parent::getCodeUrl(); 76 | } 77 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/PaycodeAbstract.php: -------------------------------------------------------------------------------- 1 | _code = isset($this->_response['new_' . $this->_codetype . 'code'][$this->_codetype . 'code']['@data']) 53 | ? $this->_response['new_' . $this->_codetype . 'code'][$this->_codetype . 'code']['@data'] 54 | : false; 55 | 56 | return $this->_code; 57 | } 58 | 59 | 60 | /** 61 | * Getter for the Bill/Paycode URL in the response 62 | * 63 | * @return string 64 | */ 65 | public function getCodeUrl() 66 | { 67 | $this->_codeUrl = isset($this->_response['new_' . $this->_codetype . 'code'][$this->_codetype . 'code_url']['@data']) 68 | ? $this->_response['new_' . $this->_codetype . 'code'][$this->_codetype . 'code_url']['@data'] 69 | : false; 70 | 71 | return $this->_codeUrl; 72 | } 73 | 74 | 75 | /** 76 | * Setter for the end date (Bill/Paycode ist valid until that date) 77 | * 78 | * @param string $date YYYY-MM-DD hh:mm:ss 79 | * @return PaycodeAbstract 80 | */ 81 | public function setEndDate($date) 82 | { 83 | $this->_parameters['end_date'] = $date; 84 | 85 | return $this; 86 | } 87 | 88 | 89 | /** 90 | * Setter for the senders bank code 91 | * 92 | * @param string $bank_code 93 | * @return PaycodeAbstract 94 | */ 95 | public function setSenderBankCode($bank_code) 96 | { 97 | $this->_parameters['sender']['bank_code'] = $bank_code; 98 | 99 | return $this; 100 | } 101 | 102 | 103 | /** 104 | * Setter for the start date (Bill/Paycode ist valid from that date) 105 | * 106 | * @param string $date YYYY-MM-DD hh:mm:ss 107 | * @return PaycodeAbstract 108 | */ 109 | public function setStartDate($date) 110 | { 111 | $this->_parameters['start_date'] = $date; 112 | 113 | return $this; 114 | } 115 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/PaycodeDetails.php: -------------------------------------------------------------------------------- 1 | _extractValue('paycode'); 39 | } 40 | 41 | 42 | /** 43 | * Setter for the paycode of the request 44 | * 45 | * @param string $paycode 46 | * @return PaycodeDetails 47 | */ 48 | public function setPaycode($paycode) 49 | { 50 | $this->_parameters['paycode'] = $paycode; 51 | 52 | return $this; 53 | } 54 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/PaycodeDetailsAbstract.php: -------------------------------------------------------------------------------- 1 | _extractValue('amount'); 39 | } 40 | 41 | 42 | /** 43 | * Getter for the Bill/Paycodes currency code (EUR|...) 44 | * 45 | * @return string 46 | */ 47 | public function getCurrencyCode() 48 | { 49 | return $this->_extractValue('currency_code'); 50 | } 51 | 52 | 53 | /** 54 | * Getter for the end date of the Bill/Paycode 55 | * 56 | * @return string 57 | */ 58 | public function getEndDate() 59 | { 60 | return $this->_extractValue('end_date'); 61 | } 62 | 63 | 64 | /** 65 | * Getter for the Bill/Paycodes language code (de|...) 66 | * 67 | * @return string 68 | */ 69 | public function getLanguageCode() 70 | { 71 | return $this->_extractValue('language_code'); 72 | } 73 | 74 | 75 | /** 76 | * Getter for the project-ID the Bill/Paycode belongs to 77 | * 78 | * @return string|bool 79 | */ 80 | public function getProjectId() 81 | { 82 | return $this->_extractValue('project_id'); 83 | } 84 | 85 | 86 | /** 87 | * Getter for the Bill/Paycodes reason (0 => reason line 1, 1 => reason line 2) 88 | * 89 | * @param int $n (default 0) 90 | * @return mixed|bool 91 | */ 92 | public function getReason($n = 0) 93 | { 94 | return $this->_extractValue('reason', 'reasons', $n); 95 | } 96 | 97 | 98 | /** 99 | * Getter for the senders bank code 100 | * 101 | * @return string 102 | */ 103 | public function getSenderBankCode() 104 | { 105 | return $this->_extractValue('bank_code', 'sender'); 106 | } 107 | 108 | 109 | /** 110 | * Getter for the senders BIC 111 | * 112 | * @return string 113 | */ 114 | public function getSenderBic() 115 | { 116 | return $this->_extractValue('bic', 'sender'); 117 | } 118 | 119 | 120 | /** 121 | * Getter for the senders country code 122 | * 123 | * @return string 124 | */ 125 | public function getSenderCountryCode() 126 | { 127 | return $this->_extractValue('country_code', 'sender'); 128 | } 129 | 130 | 131 | /** 132 | * Getter for the Bill/Paycodes start date 133 | * 134 | * @return string 135 | */ 136 | public function getStartDate() 137 | { 138 | return $this->_extractValue('start_date'); 139 | } 140 | 141 | 142 | /** 143 | * Getter for the Bill/Paycodes status 144 | * 145 | * @return string (open|used|expired) 146 | */ 147 | public function getStatus() 148 | { 149 | return $this->_extractValue('status'); 150 | } 151 | 152 | 153 | /** 154 | * Getter for the time Bill/Paycode was created 155 | * 156 | * @return string 157 | */ 158 | public function getTimeCreated() 159 | { 160 | return $this->_extractValue('time_created'); 161 | } 162 | 163 | 164 | /** 165 | * Getter for the time Bill/Paycode was used 166 | * 167 | * @return string 168 | */ 169 | public function getTimeUsed() 170 | { 171 | return $this->_extractValue('time_used'); 172 | } 173 | 174 | 175 | /** 176 | * Getter for the transaction-ID the Bill/Paycode belongs to 177 | * 178 | * @return string|bool 179 | */ 180 | public function getTransaction() 181 | { 182 | return $this->_extractValue('transaction'); 183 | } 184 | 185 | 186 | /** 187 | * Returns the user variable of a transaction 188 | * 189 | * @param int $n number of the variable (which row; default 0) 190 | * @return string the content of this variable 191 | */ 192 | public function getUserVariable($n = 0) 193 | { 194 | return $this->_extractValue('variable', 'user_variables', $n); 195 | } 196 | 197 | 198 | /** 199 | * Sets the root tag and calls the parent method 200 | * 201 | * @see SofortLibAbstract::sendRequest() 202 | */ 203 | public function sendRequest() 204 | { 205 | $this->_rootTag = $this->_root . '_request'; 206 | 207 | parent::sendRequest(); 208 | } 209 | 210 | 211 | /** 212 | * Returns data from the response array. 213 | * 214 | * @param string $tag 215 | * @param string $parentTag 216 | * @param int|bool $n 217 | * @return bool|number|string 218 | */ 219 | protected function _extractValue($tag, $parentTag = '', $n = false) 220 | { 221 | if (!count($this->_response)) { 222 | return false; 223 | } 224 | 225 | if ($parentTag === '') { 226 | return isset($this->_response[$tag]['@data']) ? $this->_response[$tag]['@data'] : false; 227 | } else { 228 | if ($n !== false && isset($this->_response[$parentTag][$tag][$n])) { 229 | //Special cases: reason both can have $n elements 230 | return isset($this->_response[$parentTag][$tag][$n]['@data']) ? $this->_response[$parentTag][$tag][$n]['@data'] : false; 231 | } else { 232 | //Some Data is nested (holder and sender data) 233 | //If $n was given but not found within the requested structure 234 | if ($n > 0) { 235 | return false; 236 | } 237 | 238 | return isset($this->_response[$parentTag][$tag]['@data']) ? $this->_response[$parentTag][$tag]['@data'] : false; 239 | } 240 | } 241 | } 242 | 243 | 244 | /** 245 | * Parse the XML (override) 246 | * 247 | * @see SofortLibAbstract::_parse() 248 | * @return void 249 | */ 250 | protected function _parse() 251 | { 252 | if (isset($this->_response[$this->_root . '_details'])) { 253 | $this->_response = $this->_response[$this->_root . '_details']; 254 | } 255 | } 256 | 257 | 258 | /** 259 | * Setter for the root-container 260 | * 261 | * @param string $root 262 | * @return PaycodeDetailsAbstract 263 | */ 264 | protected function _setRoot($root) 265 | { 266 | $this->_root = $root; 267 | 268 | return $this; 269 | } 270 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Sofortueberweisung.php: -------------------------------------------------------------------------------- 1 | _parameters['su'] = array(); 24 | return $this; 25 | } 26 | 27 | 28 | /** 29 | * Setter for customer protection if possible for customers 30 | * 31 | * @param bool $customerProtection (default true) 32 | * @return Sofortueberweisung $this 33 | */ 34 | public function setCustomerprotection($customerProtection = true) 35 | { 36 | if (!array_key_exists('su', $this->_parameters) || !is_array($this->_parameters['su'])) { 37 | $this->_parameters['su'] = array(); 38 | } 39 | 40 | $this->_parameters['su']['customer_protection'] = $customerProtection ? 1 : 0; 41 | 42 | return $this; 43 | } 44 | 45 | 46 | /** 47 | * Handle errors occurred 48 | * 49 | * @return void 50 | */ 51 | protected function _handleErrors() 52 | { 53 | parent::_handleErrors(); 54 | 55 | //handle errors 56 | if (isset($this->_response['errors']['su'])) { 57 | if (!isset($this->_response['errors']['su']['errors']['error'][0])) { 58 | $tmp = $this->_response['errors']['su']['errors']['error']; 59 | unset($this->_response['errors']['su']['errors']['error']); 60 | $this->_response['errors']['su']['errors']['error'][0] = $tmp; 61 | } 62 | 63 | foreach ($this->_response['errors']['su']['errors']['error'] as $error) { 64 | $this->errors['su'][] = $this->_getErrorBlock($error); 65 | } 66 | } 67 | 68 | //handle warnings 69 | if (isset($this->_response['new_transaction']['warnings']['su'])) { 70 | if (!isset($this->_response['new_transaction']['warnings']['su']['warnings']['warning'][0])) { 71 | $tmp = $this->_response['new_transaction']['warnings']['su']['warnings']['warning']; 72 | unset($this->_response['new_transaction']['warnings']['su']['warnings']['warning']); 73 | $this->_response['new_transaction']['warnings']['su']['warnings']['warning'][0] = $tmp; 74 | } 75 | 76 | foreach ($this->_response['new_transaction']['warnings']['su']['warnings']['warning'] as $warning) { 77 | $this->warnings['su'][] = $this->_getErrorBlock($warning); 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Xml/ArrayToXml.php: -------------------------------------------------------------------------------- 1 | 50) { 45 | throw new ArrayToXmlException('Max depth too high.'); 46 | } 47 | 48 | $this->_maxDepth = $maxDepth; 49 | 50 | if (count($input) == 1) { 51 | $tagName = key($input); 52 | $Tag = new Tag( 53 | $tagName, 54 | $this->_extractAttributesSection($input[$tagName]), 55 | $this->_extractDataSection($input[$tagName], $trim) 56 | ); 57 | $this->_render($input[$tagName], $Tag, 1, $trim); 58 | $this->_parsedData = $Tag->render(); 59 | } elseif (!$input) { 60 | $this->_parsedData = ''; 61 | } else { 62 | throw new ArrayToXmlException('No valid input.'); 63 | } 64 | } 65 | 66 | 67 | /** 68 | * Static entry point. Options are: 69 | * - version: (default 1.0) version string to put in xml prolog 70 | * - encoding: (default UTF-8) use the specified encoding 71 | * - trim: (default true) Trim values 72 | * - depth: (default 10) Maximum depth to parse the given array, throws exception when exceeded 73 | * 74 | * @param array $input the input array 75 | * @param array $options set additional options to pass to XmlToArray 76 | * @throws ArrayToXmlException 77 | * @return string 78 | */ 79 | public static function render(array $input, array $options = array()) 80 | { 81 | $options = array_merge(array( 82 | 'version' => '1.0', 83 | 'encoding' => 'UTF-8', 84 | 'trim' => true, 85 | 'depth' => 10, 86 | ), 87 | $options 88 | ); 89 | $Instance = new ArrayToXml($input, $options['depth'], $options['trim']); 90 | 91 | return $Instance->toXml($options['version'], $options['encoding']); 92 | } 93 | 94 | 95 | /** 96 | * Returns parsed array as XML structure 97 | * Pass both params as null to exclude prologue 98 | * 99 | * @param string $version (default 1.0) 100 | * @param string $encoding (default UTF-8) 101 | * @return string 102 | */ 103 | public function toXml($version = '1.0', $encoding = 'UTF-8') 104 | { 105 | return !$version && !$encoding 106 | ? $this->_parsedData 107 | : "\n{$this->_parsedData}"; 108 | } 109 | 110 | 111 | /** 112 | * Checks if current depth is exceeded 113 | * 114 | * @param int $currentDepth 115 | * @throws ArrayToXmlException if depth is exceeded 116 | * @return void 117 | */ 118 | private function _checkDepth($currentDepth) 119 | { 120 | if ($this->_maxDepth && $currentDepth > $this->_maxDepth) { 121 | throw new ArrayToXmlException("Max depth ({$this->_maxDepth}) exceeded"); 122 | } 123 | } 124 | 125 | 126 | /** 127 | * Creates a new XML node 128 | * 129 | * @param string $name 130 | * @param array $attributes 131 | * @param array $children 132 | * @return Tag 133 | */ 134 | private function _createNode($name, array $attributes, array $children) 135 | { 136 | return new Tag($name, $attributes, $children); 137 | } 138 | 139 | 140 | /** 141 | * Creates a new text node 142 | * 143 | * @param string $text 144 | * @param bool $trim 145 | * @return Text 146 | */ 147 | private function _createTextNode($text, $trim) 148 | { 149 | return new Text($text, true, $trim); 150 | } 151 | 152 | 153 | /** 154 | * Extracts the attributes section from a XmlToArray'd structure 155 | * 156 | * @param mixed $node (reference) 157 | * @return array 158 | */ 159 | private function _extractAttributesSection(&$node) 160 | { 161 | $attributes = array(); 162 | 163 | if (is_array($node) && isset($node['@attributes']) && $node['@attributes']) { 164 | $attributes = is_array($node['@attributes']) ? $node['@attributes'] : array($node['@attributes']); 165 | unset($node['@attributes']); 166 | } elseif (is_array($node) && isset($node['@attributes'])) { 167 | unset($node['@attributes']); 168 | } 169 | 170 | return $attributes; 171 | } 172 | 173 | 174 | /** 175 | * Extracts the data section from a XmlToArray'd structure 176 | * 177 | * @param mixed $node (reference) 178 | * @param bool $trim 179 | * @return array 180 | */ 181 | private function _extractDataSection(&$node, $trim) 182 | { 183 | $children = array(); 184 | 185 | if (is_array($node) && isset($node['@data']) && $node['@data']) { 186 | $children = array($this->_createTextNode($node['@data'], $trim)); 187 | unset($node['@data']); 188 | } elseif (is_array($node) && isset($node['@data'])) { 189 | unset($node['@data']); 190 | } 191 | 192 | return $children; 193 | } 194 | 195 | 196 | /** 197 | * Recursively renders a XmlToArray'd structure into an object notation 198 | * 199 | * @param mixed $input 200 | * @param Tag $ParentTag 201 | * @param int $currentDepth 202 | * @param bool $trim 203 | * @return void 204 | */ 205 | private function _render($input, Tag $ParentTag, $currentDepth, $trim) 206 | { 207 | $this->_checkDepth($currentDepth); 208 | 209 | if (is_array($input)) { 210 | foreach ($input as $tagName => $data) { 211 | $dataIsArray = is_array($data); 212 | $dataIsArrayKeyDataIsInt = $dataIsArray && is_int(key($data)); 213 | 214 | if ($dataIsArrayKeyDataIsInt) { 215 | $this->_checkDepth($currentDepth + 1); 216 | 217 | foreach ($data as $line) { 218 | $currentDepth = $this->_renderNode($tagName, $line, $ParentTag, $trim, $currentDepth); 219 | } 220 | } else { 221 | $currentDepth = $this->_renderNode($tagName, $data, $ParentTag, $trim, $currentDepth); 222 | } 223 | } 224 | 225 | return; 226 | } 227 | 228 | $ParentTag->children[] = $this->_createTextNode($input, $trim); 229 | } 230 | 231 | 232 | /** 233 | * Renders a single Node of the structure 234 | * 235 | * @param string $tagName 236 | * @param string $data 237 | * @param Tag $ParentTag 238 | * @param int $trim 239 | * @param int $currentDepth 240 | * @return int 241 | */ 242 | private function _renderNode($tagName, $data, Tag $ParentTag, $trim, $currentDepth) 243 | { 244 | $attributes = $this->_extractAttributesSection($data); 245 | 246 | if (is_array($data)) { 247 | $Tag = $this->_createNode($tagName, $attributes, $this->_extractDataSection($data, $trim)); 248 | $ParentTag->children[] = $Tag; 249 | $this->_render($data, $Tag, $currentDepth + 1, $trim); 250 | } elseif (is_numeric($tagName)) { 251 | $ParentTag->children[] = $this->_createTextNode($data, $trim); 252 | } else { 253 | $ParentTag->children[] = $this->_createNode($tagName, $attributes, 254 | array($this->_createTextNode($data, $trim))); 255 | } 256 | 257 | return $currentDepth; 258 | } 259 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Xml/ArrayToXmlException.php: -------------------------------------------------------------------------------- 1 | tagname = $tagname; 36 | $this->attributes = $attributes; 37 | $this->children = is_array($children) ? $children : array($children); 38 | } 39 | 40 | 41 | /** 42 | * Renders the element (override) 43 | * 44 | * @see SofortElement::render() 45 | * @return string 46 | */ 47 | public function render() 48 | { 49 | $output = ''; 50 | $attributes = ''; 51 | 52 | /** @var XmlToArrayNode $child */ 53 | foreach ($this->children as $child) { 54 | $output .= is_object($child) ? $child->render(false) : $child; 55 | } 56 | 57 | foreach ($this->attributes as $key => $value) { 58 | $attributes .= " $key=\"$value\""; 59 | } 60 | 61 | return $this->_render($output, $attributes); 62 | } 63 | 64 | 65 | /** 66 | * Render the output 67 | * 68 | * @param string $output 69 | * @param string $attributes 70 | * @return string 71 | */ 72 | protected function _render($output, $attributes) 73 | { 74 | return $output !== '' 75 | ? "<{$this->tagname}{$attributes}>{$output}tagname}>" 76 | : "<{$this->tagname}{$attributes} />"; 77 | } 78 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Xml/Element/Text.php: -------------------------------------------------------------------------------- 1 | text = $trim ? trim($text) : $text; 32 | $this->escape = $escape; 33 | } 34 | 35 | 36 | /** 37 | * Renders the element (override) 38 | * 39 | * @see SofortElement::render() 40 | * @return string 41 | */ 42 | public function render() 43 | { 44 | return $this->escape ? htmlspecialchars($this->text) : $this->text; 45 | } 46 | } -------------------------------------------------------------------------------- /src/Sofort/SofortLib/Xml/XmlToArray.php: -------------------------------------------------------------------------------- 1 | '€', 30 | ); 31 | 32 | /** 33 | * stop parsing when maxDepth is exceeded, defaults to no maximum (=0). 34 | * 35 | * @var int $_maxDepth 36 | */ 37 | private $_maxDepth = 0; 38 | 39 | /** 40 | * Object reference for logging purposes 41 | * 42 | * @var SofortObject $_Object 43 | */ 44 | private $_Object = null; 45 | 46 | /** 47 | * Holds start tags in a row. 48 | * Used for error reporting and counting the current depth 49 | * 50 | * @var array $_tagStack 51 | */ 52 | private $_tagStack = array(); 53 | 54 | 55 | /** 56 | * Loads XML into array representation. 57 | * 58 | * @param string $input 59 | * @param int $maxDepth (default 20) 60 | * @throws XmlToArrayException 61 | */ 62 | public function __construct($input, $maxDepth = 20) 63 | { 64 | if (!is_string($input)) { 65 | throw new XmlToArrayException('No valid input.'); 66 | } 67 | $this->_maxDepth = $maxDepth; 68 | 69 | $XMLParser = xml_parser_create(); 70 | xml_parser_set_option($XMLParser, XML_OPTION_SKIP_WHITE, false); 71 | xml_parser_set_option($XMLParser, XML_OPTION_CASE_FOLDING, false); 72 | xml_parser_set_option($XMLParser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); 73 | xml_set_character_data_handler($XMLParser, array($this, '_contents')); 74 | xml_set_default_handler($XMLParser, array($this, '_default')); 75 | xml_set_element_handler($XMLParser, array($this, '_start'), array($this, '_end')); 76 | 77 | if (!xml_parse($XMLParser, $input, true)) { 78 | $errorCode = xml_get_error_code($XMLParser); 79 | $message = sprintf('%s. line: %d, char: %d' . ($this->_tagStack ? ', tag: %s' : ''), 80 | xml_error_string($errorCode), 81 | xml_get_current_line_number($XMLParser), 82 | xml_get_current_column_number($XMLParser) + 1, 83 | implode('->', $this->_tagStack)); 84 | xml_parser_free($XMLParser); 85 | throw new XmlToArrayException($message, $errorCode); 86 | } 87 | 88 | xml_parser_free($XMLParser); 89 | } 90 | 91 | 92 | /** 93 | * Log messages (debugging purpose) 94 | * 95 | * @param string $msg 96 | * @param int $type (default 2) 97 | * @return array|bool 98 | */ 99 | public function log($msg, $type = 2) 100 | { 101 | if (class_exists('\SofortObject')) { 102 | !($this->_Object instanceof \SofortObject) && $this->_Object = new \SofortObject(); 103 | 104 | return $this->_Object->log($msg, $type); 105 | } 106 | 107 | return false; 108 | } 109 | 110 | 111 | /** 112 | * Static entry point 113 | * 114 | * @param string $input 115 | * @param bool $simpleStructure (default false) 116 | * @param int $maxDepth only parse XML to the provided depth (default 20) 117 | * @throws XmlToArrayException 118 | * @return array 119 | */ 120 | public static function render($input, $simpleStructure = false, $maxDepth = 20) 121 | { 122 | $Instance = new XmlToArray($input, $maxDepth); 123 | 124 | return $Instance->toArray($simpleStructure); 125 | } 126 | 127 | 128 | /** 129 | * Returns parsed XML as array structure 130 | * 131 | * @param bool $simpleStructure (default false) 132 | * @return array 133 | */ 134 | public function toArray($simpleStructure = false) 135 | { 136 | return $this->_CurrentXmlToArrayNode->render($simpleStructure); 137 | } 138 | 139 | 140 | /** 141 | * Handles cdata of the XML (user data between the tags) 142 | * 143 | * @param resource $parser a resource handle of the XML parser 144 | * @param string $data 145 | * @return void 146 | */ 147 | private function _contents($parser, $data) 148 | { 149 | if (trim($data) !== '' && $this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) { 150 | $this->_CurrentXmlToArrayNode->setData($data); 151 | } 152 | } 153 | 154 | 155 | /** 156 | * Default handler for all other XML sections not implemented as callback 157 | * 158 | * @param resource $parser a resource handle of the XML parser 159 | * @param mixed $data 160 | * @throws XmlToArrayException 161 | * @return void 162 | */ 163 | private function _default($parser, $data) 164 | { 165 | $data = trim($data); 166 | 167 | if (in_array($data, get_html_translation_table(HTML_ENTITIES))) { 168 | if ($this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) { 169 | $this->_CurrentXmlToArrayNode->setData(html_entity_decode($data)); 170 | } 171 | } elseif ($data && isset(self::$_htmlEntityExceptions[$data])) { 172 | if ($this->_CurrentXmlToArrayNode instanceof XmlToArrayNode) { 173 | $this->_CurrentXmlToArrayNode->setData(self::$_htmlEntityExceptions[$data]); 174 | } 175 | } elseif ($data && is_string($data) && strpos($data, '