├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── composer.json
├── doc
└── usage.md
└── src
└── Payline
├── Cache
├── Apc.php
├── CacheInterface.php
├── CacheTrait.php
└── File.php
├── Objects
├── Address.php
├── AddressOwner.php
├── Authentication3DSecure.php
├── Authorization.php
├── BankAccountData.php
├── BillingRecordForUpdate.php
├── Buyer.php
├── Buyer
│ ├── BillingAddress.php
│ ├── MerchantAuthentication.php
│ └── ShippingAdress.php
├── Card.php
├── Card
│ └── PaymentData.php
├── Cheque.php
├── Creditor.php
├── Order.php
├── OrderDetail.php
├── Owner.php
├── Owner
│ └── BillingAddress.php
├── Payment.php
├── PrivateData.php
├── PrivateDataList.php
├── Reattempt.php
├── Recurring.php
├── SelectedContractList.php
├── SubMerchant.php
├── ThreeDSInfo.php
├── ThreeDSInfo
│ ├── Browser.php
│ └── Sdk.php
├── Wallet.php
├── Wallet
│ └── ShippingAddress.php
├── WalletIdList.php
└── contractNumberWalletList.php
├── PaylineSDK.php
├── SoapVarFactory.php
├── WebserviceClient.php
└── wsdl
├── DirectPaymentAPI.wsdl
├── ExtendedAPI.wsdl
└── WebPaymentAPI.wsdl
/.gitignore:
--------------------------------------------------------------------------------
1 | phpunit.xml
2 | /vendor/
3 | /logs/
4 | /composer.phar
5 | /composer.lock
6 | /phpunit.xml.dist
7 | /.settings/
8 | /.buildpath
9 | /.project
10 | /.idea
11 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | * 4.77 (2024-02-06)
3 | * Update WSDL from 4.76 to 4.77
4 |
5 |
6 | ----------------------------------------
7 |
8 | * 4.76 (2023-09-25)
9 | * Update WSDL from 4.75 to 4.76
10 | * Add reattempt to authorization
11 | * Move doAuthorizationRedirect from WebPaymentAPI to DirectPaymentAPI
12 |
13 | ----------------------------------------
14 |
15 | * 4.75 (2023-07-04)
16 | * Update WSDL from 4.74 to 4.75
17 | * Add miscData to doCredit
18 | * Add miscData to doDebit
19 | * Allow to pass 0 amount on payment in doWebPayment
20 | * Prevent permission error on log directory
21 | * Fix php warning (Creation of dynamic property) on PHP8.2
22 | * Add Missing Payline\Objects\WalletIdList
23 |
24 | ----------------------------------------
25 |
26 | * 4.74 (2023-03-31)
27 | * Update WSDL from 4.73 to 4.74
28 | * Add service prepareSession
29 | * Add par, tokenRequestorCryptogram, tokenRequestorId, last4, panType on card object
30 | * Allow to use monolog/monolog:3.*
31 |
32 | ----------------------------------------
33 |
34 | * 4.73 (2023-01-20)
35 | * Update WSDL from 4.72 to 4.73
36 | * Fix proxy usage
37 | * Fix exception log
38 |
39 | ----------------------------------------
40 |
41 | * 4.72.1 (2023-01-09)
42 | * fix missing namespace on address for buyer and wallet
43 |
44 | ----------------------------------------
45 |
46 | * 4.72 (2022-09-09)
47 | * Update WSDL from 4.71 to 4.72
48 | * add miscData in doCapture
49 | * add miscData in doRefund
50 | * fix error on strlen in hideChar method
51 |
52 | ----------------------------------------
53 |
54 | * 4.71 (2022-06-16)
55 | * Update WSDL from 4.70 to 4.71
56 | * changer parameter type for sdk/maxTimeout
57 |
58 | ----------------------------------------
59 |
60 | * 4.70 (2022-05-23)
61 | * wsdl upgrade
62 | * expose parameters by method ( getDefaultWSRequest )
63 | * fix doAuthorizationRedirect call
64 | * fix custom soap_client option in WebserviceClient
65 | * support php 8 fix : "strcmp(): Passing null to parameter #2" in isChildFromList
66 |
67 | ----------------------------------------
68 |
69 | * 4.69 (2022-01-18)
70 | * wsdl upgrade
71 | * add threeDSInfo and travelFileNumber in doAuthorization
72 | * add threeDSInfo and travelFileNumber in doImmediateWalletPayment
73 | * remove duplicate code on sub object creation
74 | * remove CRLF ending files
75 | * add reset methode to reuse SDK instance
76 |
77 | ----------------------------------------
78 |
79 | * 4.68 (2021-09-27)
80 | * wsdl upgrade
81 | * add merchantURL and merchantCountryCode in verifyEnrollment
82 | * ADD FAILOVER mechanism
83 | * add method setSoapOptions to change SoapClient options
84 | * add method setFailoverOptions to change failover behavior and cache usage
85 | * add getSoapLastContent to retrieve last SOAP context
86 | * fix warnings on undefined array keys in SDK
87 |
88 | ----------------------------------------
89 |
90 | * 4.66 (2021-01-06)
91 | * wsdl upgrade
92 | * remove createMerchant
93 | * add transactionID in createWallet
94 | * add amount and currency in doReset
95 | * add linkedTransactionId and recurring in doAuthorization
96 | * add miscData in doRefund
97 | * add amount, currency, privateDataList and sequenceNumber in doReset
98 | * add recurring in verifyEnrollment
99 | * add recurring, merchantScore and skipSmartDisplay in doWebPayment
100 |
101 | ----------------------------------------
102 |
103 | * 4.64.1 (2021-01-06)
104 | * wsdl upgrade and split wsdl in three files
105 | * new properties authorizedCurrency, authorizedAmount in Authorization
106 | * new property challengeWindowSize in threeDSInfo
107 | * new property challengeWindowSize in threeDSInfo
108 | * support php 7.4 replace array_key_exists by property_exists on object
109 | * allow to customize waiting time when connecting to Payline servers
110 | * format request for UpdateWallet call
111 | * fix phpdoc for logger
112 |
113 | ----------------------------------------
114 |
115 | * 4.59 (2019-07-28)
116 | * wsdl upgrade
117 | * new threeDSInfo parameter for manageWebWallet and doWebPayment
118 | * new browser in threeDSInfo
119 | * new sdk in threeDSInfo
120 | * new streetNumber, addressCreateDate and email in address
121 | * new resultContainer and authenticationResult in Authentication3DSecure
122 | * new buyerExtended, merchantAuthentication and loyaltyMemberType in buyer
123 | * new discountAmount, otaPackageType, otaDestinationCountry, bookingReference, orderDetail, orderExtended and orderOTA in order
124 | * new seller and sellerType in OrderDetail
125 | * new cumulatedAmount in payment
126 | * new billingBank in recurring
127 |
128 | ----------------------------------------
129 |
130 | * 4.54 & 4.55 (2018-06-27)
131 | * new asynchronousRetryTimeout parameter for doAuthorization and doWebPayment (4.55)
132 | * new miscData parameter for isRegistered (4.54)
133 |
134 | ----------------------------------------
135 |
136 | * 4.53 (2018-01-10)
137 | * new deliveryCharge attribute in order object
138 | * new registrationToken attribute in payment object
139 | * new object subMerchant
140 | * new method isRegistered
141 | * new subMerchant parameter for doAuthorization, doWebPayment, doCredit, doDebit, doImmediateWalletPayment, doScheduledWalletPayment
142 | * new miscData parameter for doWebPayment
143 | * new returnUrl parameter for verifyEnrollment
144 |
145 | ----------------------------------------
146 |
147 | * 4.52 (2017-10-16)
148 | * new avs child node in transaction object
149 |
150 | ----------------------------------------
151 |
152 | * 4.51 (2017-08-11)
153 | * no structural changes
154 |
155 | ----------------------------------------
156 |
157 | * 4.50.2 (2017-06-30)
158 | * new details child node in doRefundRequest object
159 |
160 | ----------------------------------------
161 |
162 | * 4.50.1 (2017-05-09)
163 | * add of certificate-based authentication endpoints
164 |
165 | ----------------------------------------
166 |
167 | * 4.50 (2017-04-13)
168 | * new merchantName parameter for doWebPayment, manageWebWallet and verifyEnrollment (name displayed on ACS)
169 | * new attribute paymentData for object Card (used by Apple Pay only)
170 |
171 | ----------------------------------------
172 |
173 | * 4.49 (2017-01-05)
174 | * removal of autoload inclusion in main PaylineSDK.php file
175 | * fix of `SOAP_DOCUMENT` and `SOAP_LITERAL` constants use in main PaylineSDK.php file
176 | * new optional parameters defaultTimezone and externalLogger for PaylineSDK class constructor
177 |
178 | ----------------------------------------
179 |
180 | * 4.48 (2016-09-13)
181 | * new properties version and TransactionDate for getAlertDetailsRequest
182 |
183 | ----------------------------------------
184 |
185 | * 4.47.1 (2016-08-04)
186 | * new property generateVirtualCvx for verifyEnrollmentRequest
187 |
188 | ----------------------------------------
189 |
190 | * 4.47 (2016-06-16)
191 | * new buyer properties :
192 | - deviceFingerprint
193 | - isBot
194 | - isIncognito
195 | - isBehindProxy
196 | - isFromTor
197 | - isEmulator
198 | - isRooted
199 | - hasTimezoneMismatch
200 | * new property cardBrand for payment and wallet objets
201 | * new property version for getCardsRequest
202 |
203 | ----------------------------------------
204 |
205 | * 4.46.1 (2016-06-06)
206 | * contractNumberWalletList can have 99 contractNumberWallet elements
207 |
208 | ----------------------------------------
209 |
210 | * 4.46 (2016-05-10)
211 | * add of PaResStatus and VeResStatus (Authentication3DSecure class)
212 | * response format : child nodes of cardinality higher to 1 are sent in an integer-indexed array, in any cases (1 element of index 0 if node has only 1 child).
213 | This applies to nodes :
214 | - cards (son of cardsList)
215 | - billingRecord (son of billingRecordList)
216 | - walletId (son of walletIdList)
217 | - transaction (son of transactionList)
218 | - pointOfSell (son of listPointOfSell)
219 | - contract (son of contracts)
220 | - customPaymentPageCode (son of customPaymentPageCodeList)
221 | - function (son of functions)
222 | - details (son of details)
223 | - privateData (son of privateDataList)
224 | - associatedTransactions (son of associatedTransactionsList)
225 | - statusHistory (son of statusHistoryList)
226 | - paymentAdditional (son of paymentAdditionalList)
227 | - CustomerTrans (son of CustomerTransHist)
228 | - PaymentMeansTrans (son of PaymentMeansTransHist)
229 | - AlertsTrans (son of AlertsTransHist)
230 |
231 | ----------------------------------------
232 |
233 | * 4.45.1 (2016-03-10)
234 | * add of Recurring class
235 | * require any 1.* monolog/monolog version
236 | * date_default_timezone_set("Europe/Paris") in PaylineSDK class constructor
237 | * add widget related constants (js and css url path)
238 |
239 | ----------------------------------------
240 |
241 | * 4.45 (2016-01-22)
242 | * add of softDescriptor payment attribute (Payment class)
243 |
244 | ----------------------------------------
245 |
246 | * 4.44.1 (2016-01-20)
247 | * Fisrt Payline release deployed on Composer
248 |
249 | ----------------------------------------
250 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://packagist.org/packages/monext/payline-sdk)
2 | [](https://packagist.org/packages/monext/payline-sdk)
3 | [](https://packagist.org/packages/monext/payline-sdk)
4 |
5 | PaylineSDK - Payline library for PHP
6 | ====================================
7 |
8 | We are excited to announce that our GitHub repository has been rebranded from Payline to Monext. This change reflects the broader range of payment solutions and services we now offer under the Monext name.
9 |
10 | Monext continues to provide innovative and secure payment solutions for businesses of all sizes. Through this repository, you'll find our latest tools, plugins, and API documentation, enabling seamless integration with our platforms.
11 |
12 | Feel free to explore, contribute, and stay updated on our latest developments. Thank you for being part of the journey!
13 |
14 | Follow : https://github.com/Monext/monext-php-sdk
15 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "monext/payline-sdk",
3 | "description": "Payline library for PHP",
4 | "keywords": [
5 | "Monext",
6 | "Payline",
7 | "payment"
8 | ],
9 | "type": "library",
10 | "license": "LGPL-3.0",
11 | "authors": [
12 | {
13 | "name": "Fabien SUAREZ",
14 | "email": "fabien.suarez@payline.com",
15 | "homepage": "http://www.payline.com"
16 | },
17 | {
18 | "name": "Vincent Pietri",
19 | "email": "vincent.pietri@tbdgroup.com",
20 | "homepage": "https://www.tbdgroup.com/"
21 | }
22 | ],
23 | "require": {
24 | "php": ">=5.6",
25 | "ext-soap": "*",
26 | "ext-curl": "*",
27 | "ext-openssl": "*",
28 | "ext-mbstring": "*",
29 | "monolog/monolog": "1.* || ~2.0 || ~3.0",
30 | "symfony/cache": ">=3.4"
31 | },
32 | "support": {
33 | "email": "support@payline.com",
34 | "docs": "http://support.payline.com"
35 | },
36 | "autoload": {
37 | "psr-4": {
38 | "Payline\\": "src/Payline"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/doc/usage.md:
--------------------------------------------------------------------------------
1 | Using Payline
2 | =============
3 |
4 | Installation
5 | ------------
6 |
7 | To install PaylineSDK, simply get the code (from github or through Composer) and
8 | configure an autoloader for the Payline namespace.
9 |
10 |
11 | Create a PaylineSDK instance
12 | ----------------------------
13 |
14 | Here is a basic setup to create a PaylineSDK instance
15 |
16 | ```php
17 | use Payline\PaylineSDK;
18 |
19 | // create an instance
20 | $paylineSDK = new PaylineSDK($merchant_id, $access_key, $proxy_host, $proxy_port, $proxy_login, $proxy_password, $environment[, $pathLog= null[, $logLevel = Logger::INFO]]);
21 | /*
22 | $environment determines in which Payline environment your request are targeted.
23 | It should be filled with either PaylineSDK::ENV_HOMO (for testing purpose) or PaylineSDK::ENV_PROD (real life)
24 | If $pathLog is null, log files will be written under default logs directory. Fill with your custom log files path
25 | */
26 | ```
27 |
28 | Call a Payline web service
29 | --------------------------
30 |
31 | All Payline web services are available through a PaylineSDK instance. Here are two dummy examples :
32 |
33 | ### doWebPayment
34 |
35 | This web service returns a secure URL to which the customer has to be redirected in order to enter his payment information.
36 |
37 | ```php
38 | doWebPayment($doWebPaymentRequest);
73 |
74 | // $doWebPaymentResponse['result']['code'] contains the call result code.
75 | // in case of success (code 00000) :
76 | // - $doWebPaymentResponse['redirectURL'] contains the secure payment page URL
77 | // - $doWebPaymentResponse['token'] contains the web payment session unique identifier
78 |
79 | ```
80 |
81 | ### getWebPaymentDetails
82 |
83 | This web service returns the result of a web payment session, given its token.
84 |
85 | ```php
86 | getWebPaymentDetails($getWebPaymentDetailsRequest);
91 |
92 | ```
93 |
--------------------------------------------------------------------------------
/src/Payline/Cache/Apc.php:
--------------------------------------------------------------------------------
1 | hasItem(self::CACHE_KEY) ? $this->getItem(self::CACHE_KEY)->get() : false;
10 | }
11 |
12 | public function saveServicesEndpoints(array $endpoints, $ttl)
13 | {
14 | $cachedItem = $this->getItem(self::CACHE_KEY);
15 | if (!$cachedItem->isHit())
16 | {
17 | $cachedItem->set($endpoints);
18 | $cachedItem->expiresAfter($ttl);
19 | $this->save($cachedItem);
20 | }
21 | return true;
22 | }
23 |
24 | public function hasServicesEndpoints()
25 | {
26 | return $this->hasItem(self::CACHE_KEY);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/Payline/Cache/File.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Address
13 | {
14 |
15 | public $title;
16 |
17 | public $firstName;
18 |
19 | public $lastName;
20 |
21 | public $name;
22 |
23 | public $street1;
24 |
25 | public $street2;
26 |
27 | public $cityName;
28 |
29 | public $zipCode;
30 |
31 | public $country;
32 |
33 | public $county;
34 |
35 | public $state;
36 |
37 | public $phoneType;
38 |
39 | public $phone;
40 |
41 | public $streetNumber;
42 |
43 | public $addressCreateDate;
44 |
45 | public $email;
46 | }
47 |
--------------------------------------------------------------------------------
/src/Payline/Objects/AddressOwner.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class AddressOwner
13 | {
14 |
15 | public $street;
16 |
17 | public $cityName;
18 |
19 | public $zipCode;
20 |
21 | public $country;
22 |
23 | public $phone;
24 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Authentication3DSecure.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Authentication3DSecure
13 | {
14 |
15 | public $md;
16 |
17 | public $pares;
18 |
19 | public $xid;
20 |
21 | public $eci;
22 |
23 | public $cavv;
24 |
25 | public $cavvAlgorithm;
26 |
27 | public $vadsResult;
28 |
29 | public $typeSecurisation;
30 |
31 | public $PaResStatus;
32 |
33 | public $VeResStatus;
34 |
35 | public $resultContainer;
36 |
37 | public $authenticationResult;
38 | }
39 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Authorization.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Authorization
13 | {
14 | public $number;
15 |
16 | public $date;
17 |
18 | public $authorizedAmount;
19 |
20 | public $authorizedCurrency;
21 |
22 | public $reattempt;
23 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/BankAccountData.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class BankAccountData
13 | {
14 |
15 | public $countryCode;
16 |
17 | public $bankCode;
18 |
19 | public $accountNumber;
20 |
21 | public $key;
22 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/BillingRecordForUpdate.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class BillingRecordForUpdate
13 | {
14 |
15 | public $date;
16 |
17 | public $amount;
18 |
19 | public $status;
20 |
21 | public $executionDate;
22 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Buyer.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Buyer
13 | {
14 |
15 | public $title;
16 |
17 | public $lastName;
18 |
19 | public $firstName;
20 |
21 | public $email;
22 |
23 | public $customerId;
24 |
25 | public $walletId;
26 |
27 | public $walletDisplayed;
28 |
29 | public $walletSecured;
30 |
31 | public $walletCardInd;
32 |
33 | public $shippingAdress;
34 |
35 | public $billingAddress;
36 |
37 | public $accountCreateDate;
38 |
39 | public $accountAverageAmount;
40 |
41 | public $accountOrderCount;
42 |
43 | public $ip;
44 |
45 | public $mobilePhone;
46 |
47 | public $legalStatus;
48 |
49 | public $legalDocumentType;
50 |
51 | public $legalDocument;
52 |
53 | public $birthDate;
54 |
55 | public $fingerprintID;
56 |
57 | public $deviceFingerprint;
58 |
59 | public $isBot;
60 |
61 | public $isIncognito;
62 |
63 | public $isBehindProxy;
64 |
65 | public $isFromTor;
66 |
67 | public $isEmulator;
68 |
69 | public $isRooted;
70 |
71 | public $hasTimezoneMismatch;
72 |
73 | public $buyerExtended;
74 |
75 | public $merchantAuthentication;
76 |
77 | public $loyaltyMemberType;
78 | }
79 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Buyer/BillingAddress.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\Buyer;
11 |
12 | class BillingAddress extends \Payline\Objects\Address
13 | {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Buyer/MerchantAuthentication.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 | namespace Payline\Objects\Buyer;
12 |
13 | class MerchantAuthentication
14 | {
15 | public $method;
16 |
17 | public $date;
18 | }
19 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Buyer/ShippingAdress.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\Buyer;
11 |
12 | class ShippingAdress extends \Payline\Objects\Address
13 | {
14 |
15 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Card.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Card
13 | {
14 | public $encryptionKeyId;
15 |
16 | public $encryptedData;
17 |
18 | public $number;
19 |
20 | public $type;
21 |
22 | public $expirationDate;
23 |
24 | public $cvx;
25 |
26 | public $ownerBirthdayDate;
27 |
28 | public $password;
29 |
30 | public $cardPresent;
31 |
32 | public $cardholder;
33 |
34 | public $token;
35 |
36 | public $paymentData;
37 |
38 | public $par;
39 |
40 | public $tokenRequestorCryptogram;
41 |
42 | public $tokenRequestorId;
43 |
44 | public $last4;
45 |
46 | public $panType;
47 |
48 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Card/PaymentData.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\Card;
11 |
12 | class PaymentData
13 | {
14 | public $transactionID;
15 |
16 | public $network;
17 |
18 | public $tokenData;
19 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Cheque.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Cheque
13 | {
14 |
15 | public $number;
16 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Creditor.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Creditor
13 | {
14 |
15 | public $bic;
16 |
17 | public $iban;
18 |
19 | public $name;
20 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Order.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Order
13 | {
14 | public $ref;
15 |
16 | public $origin;
17 |
18 | public $country;
19 |
20 | public $taxes;
21 |
22 | public $amount;
23 |
24 | public $currency;
25 |
26 | public $date;
27 |
28 | public $quantity;
29 |
30 | public $comment;
31 |
32 | public $details = [];
33 |
34 | public $deliveryTime;
35 |
36 | public $deliveryMode;
37 |
38 | public $deliveryExpectedDate;
39 |
40 | public $deliveryExpectedDelay;
41 |
42 | public $deliveryCharge;
43 |
44 | public $discountAmount;
45 |
46 | public $otaPackageType;
47 |
48 | public $otaDestinationCountry;
49 |
50 | public $bookingReference;
51 |
52 | public $orderDetail;
53 |
54 | public $orderExtended;
55 |
56 | public $orderOTA;
57 | }
58 |
--------------------------------------------------------------------------------
/src/Payline/Objects/OrderDetail.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class OrderDetail
13 | {
14 |
15 | public $ref;
16 |
17 | public $price;
18 |
19 | public $quantity;
20 |
21 | public $comment;
22 |
23 | public $category;
24 |
25 | public $subcategory1;
26 |
27 | public $subcategory2;
28 |
29 | public $brand;
30 |
31 | public $additionalData;
32 |
33 | public $taxRate;
34 |
35 | public $seller;
36 |
37 | public $sellerType;
38 | }
39 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Owner.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Owner
13 | {
14 |
15 | public $lastName;
16 |
17 | public $firstName;
18 |
19 | public $billingAddress;
20 |
21 | public $issueCardDate;
22 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Owner/BillingAddress.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\Owner;
11 |
12 |
13 | /**
14 | * Type addressOwner
15 | * @see https://docs.payline.com/display/DT/Object+-+owner
16 | */
17 | class BillingAddress
18 | {
19 | public $street;
20 |
21 | public $cityName;
22 |
23 | public $zipCode;
24 |
25 | public $country;
26 |
27 | public $phone;
28 | }
29 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Payment.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Payment
13 | {
14 |
15 | public $amount;
16 |
17 | public $currency;
18 |
19 | public $action;
20 |
21 | public $mode;
22 |
23 | public $method;
24 |
25 | public $contractNumber;
26 |
27 | public $differedActionDate;
28 |
29 | public $softDescriptor;
30 |
31 | public $cardBrand;
32 |
33 | public $registrationToken;
34 |
35 | public $cumulatedAmount;
36 | }
37 |
--------------------------------------------------------------------------------
/src/Payline/Objects/PrivateData.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class PrivateData
13 | {
14 | public $key;
15 |
16 | public $value;
17 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/PrivateDataList.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class PrivateDataList
13 | {
14 | public $privateData=[];
15 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Reattempt.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Reattempt
13 | {
14 | public $indicator;
15 |
16 | public $frozenPeriod;
17 |
18 | public $allowedDuration;
19 |
20 | public $maxAllowed;
21 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Recurring.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Recurring
13 | {
14 |
15 | public $firstAmount;
16 |
17 | public $amount;
18 |
19 | public $billingCycle;
20 |
21 | public $billingLeft;
22 |
23 | public $billingDay;
24 |
25 | public $startDate;
26 |
27 | public $endDate;
28 |
29 | public $newAmount;
30 |
31 | public $amountModificationDate;
32 |
33 | public $billingRank;
34 | }
35 |
--------------------------------------------------------------------------------
/src/Payline/Objects/SelectedContractList.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class SelectedContractList
13 | {
14 |
15 | public $selectedContract = [];
16 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/SubMerchant.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class SubMerchant
13 | {
14 |
15 | public $subMerchantId;
16 |
17 | public $subMerchantName;
18 |
19 | public $subMerchantMCC;
20 |
21 | public $subMerchantSIRET;
22 |
23 | public $subMerchantTaxCode;
24 |
25 | public $subMerchantStreet;
26 |
27 | public $subMerchantCity;
28 |
29 | public $subMerchantZipCode;
30 |
31 | public $subMerchantCountry;
32 |
33 | public $subMerchantState;
34 |
35 | public $subMerchantEmailAddress;
36 |
37 | public $subMerchantPhoneNumber;
38 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/ThreeDSInfo.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class ThreeDSInfo
13 | {
14 | public $challengeInd;
15 |
16 | public $threeDSReqPriorAuthData;
17 |
18 | public $threeDSReqPriorAuthMethod;
19 |
20 | public $threeDSReqPriorAuthTimestamp;
21 |
22 | public $browser;
23 |
24 | public $sdk;
25 |
26 | public $threeDSMethodNotificationURL;
27 |
28 | public $threeDSMethodResult;
29 |
30 | public $challengeWindowSize;
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/Payline/Objects/ThreeDSInfo/Browser.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\ThreeDSInfo;
11 |
12 | class Browser
13 | {
14 | public $acceptHeader;
15 |
16 | public $javaEnabled;
17 |
18 | public $javascriptEnabled;
19 |
20 | public $language;
21 |
22 | public $colorDepth;
23 |
24 | public $screenHeight;
25 |
26 | public $screenWidth;
27 |
28 | public $timeZoneOffset;
29 |
30 | public $userAgent;
31 | }
32 |
--------------------------------------------------------------------------------
/src/Payline/Objects/ThreeDSInfo/Sdk.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 | namespace Payline\Objects\ThreeDSInfo;
12 |
13 | class Sdk
14 | {
15 | public $deviceRenderingOptionsIF;
16 |
17 | public $deviceRenderOptionsUI;
18 |
19 | public $appID;
20 |
21 | public $ephemPubKey;
22 |
23 | public $maxTimeout;
24 |
25 | public $referenceNumber;
26 |
27 | public $transID;
28 |
29 | public $encData;
30 | }
31 |
--------------------------------------------------------------------------------
/src/Payline/Objects/Wallet.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class Wallet
13 | {
14 |
15 | public $walletId;
16 |
17 | public $lastName;
18 |
19 | public $firstName;
20 |
21 | public $email;
22 |
23 | public $shippingAddress;
24 |
25 | public $card;
26 |
27 | public $comment;
28 |
29 | public $default;
30 |
31 | public $cardStatus;
32 |
33 | public $cardBrand;
34 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/Wallet/ShippingAddress.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects\Wallet;
11 |
12 | class ShippingAddress extends \Payline\Objects\Address
13 | {
14 |
15 | }
--------------------------------------------------------------------------------
/src/Payline/Objects/WalletIdList.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class WalletIdList
13 | {
14 |
15 | public $walletId = [];
16 | }
17 |
--------------------------------------------------------------------------------
/src/Payline/Objects/contractNumberWalletList.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline\Objects;
11 |
12 | class contractNumberWalletList
13 | {
14 |
15 | public $contractNumberWallet = [];
16 | }
--------------------------------------------------------------------------------
/src/Payline/PaylineSDK.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 | namespace Payline;
11 |
12 |
13 | use Monolog\Logger;
14 | use Monolog\Handler\StreamHandler;
15 | use SoapClient;
16 | use SoapVar;
17 |
18 | use Payline\Objects\Buyer;
19 | use Payline\Objects\Buyer\BillingAddress;
20 | use Payline\Objects\Buyer\MerchantAuthentication;
21 | use Payline\Objects\Buyer\ShippingAdress;
22 | use Payline\Objects\Card;
23 | use Payline\Objects\Card\PaymentData;
24 | use Payline\Objects\Owner;
25 | use Payline\Objects\Owner\BillingAddress as AddressOwner;
26 | use Payline\Objects\ThreeDSInfo;
27 | use Payline\Objects\ThreeDSInfo\Browser;
28 | use Payline\Objects\ThreeDSInfo\Sdk;
29 | use Payline\Objects\Authentication3DSecure;
30 | use Payline\Objects\Authorization;
31 | use Payline\Objects\BankAccountData;
32 | use Payline\Objects\BillingRecordForUpdate;
33 | use Payline\Objects\Cheque;
34 | use Payline\Objects\Creditor;
35 | use Payline\Objects\Order;
36 | use Payline\Objects\OrderDetail;
37 | use Payline\Objects\Payment;
38 | use Payline\Objects\PrivateData;
39 | use Payline\Objects\Recurring;
40 | use Payline\Objects\SubMerchant;
41 | use Payline\Objects\Wallet;
42 |
43 | class PaylineSDK
44 | {
45 |
46 | /**
47 | * Payline release corresponding to this version of the package
48 | * @see https://docs.payline.com/display/DT/API+version+history
49 | */
50 | const SDK_RELEASE = 'PHP SDK 4.77';
51 |
52 | /**
53 | * development environment flag
54 | */
55 | const ENV_DEV = "DEV";
56 |
57 | /**
58 | * integration environment flag
59 | */
60 | const ENV_INT = "INT";
61 |
62 | /**
63 | * homologation environment flag
64 | */
65 | const ENV_HOMO = "HOMO";
66 |
67 | /**
68 | * homologation environment flag - uses certificate-based authentication
69 | */
70 | const ENV_HOMO_CC = "HOMO_CC";
71 |
72 | /**
73 | * production environment flag
74 | */
75 | const ENV_PROD = "PROD";
76 |
77 | /**
78 | * production environment flag - uses certificate-based authentication
79 | */
80 | const ENV_PROD_CC = "PROD_CC";
81 |
82 | /**
83 | * name of Payline DirectPaymentAPI
84 | */
85 | const DIRECT_API = 'DirectPaymentAPI';
86 |
87 | /**
88 | * name of Payline ExtendedAPI
89 | */
90 | const EXTENDED_API = 'ExtendedAPI';
91 |
92 | /**
93 | * name of Payline WebPaymentAPI
94 | */
95 | const WEB_API = 'WebPaymentAPI';
96 |
97 | /**
98 | * SOAP name of authorization object
99 | */
100 | const SOAP_AUTHORIZATION = 'authorization';
101 |
102 | /**
103 | * SOAP name of card object
104 | */
105 | const SOAP_CARD = 'card';
106 |
107 | /**
108 | * SOAP name of orderDetail object
109 | */
110 | const SOAP_ORDERDETAIL = 'orderDetail';
111 |
112 | /**
113 | * SOAP name of paymentData object
114 | */
115 | const SOAP_PAYMENT_DATA = 'paymentData';
116 |
117 | /**
118 | * SOAP name of privateData object
119 | */
120 | const SOAP_PRIVATE_DATA = 'privateData';
121 |
122 | /**
123 | * SOAP name of address object
124 | */
125 | const SOAP_ADDRESS = 'address';
126 |
127 | /**
128 | * SOAP name of cheque object
129 | */
130 | const SOAP_CHEQUE = 'cheque';
131 |
132 | /**
133 | * SOAP name of creditor object
134 | */
135 | const SOAP_CREDITOR = 'creditor';
136 |
137 | /**
138 | * SOAP name of billingRecordForUpdate object
139 | */
140 | const SOAP_BILLING_RECORD_FOR_UPDATE = 'billingRecordForUpdate';
141 |
142 | /**
143 | * SOAP name of recurring object
144 | */
145 | const SOAP_RECURRING = 'recurring';
146 |
147 | /**
148 | * SOAP name of merchantAuthentication object
149 | */
150 | const SOAP_MERCHANT_AUTHENTICATION = 'merchantAuthentication';
151 |
152 | /**
153 | * SOAP name of wallet object
154 | */
155 | const SOAP_WALLET = 'wallet';
156 |
157 | /**
158 | * directory services endpoint in production environment
159 | */
160 | const HOMO_SERVICES_ENDPOINT = 'https://homologation-payment.payline.com/services/servicesendpoints/SOAP';
161 |
162 | /**
163 | * directory services endpoint in development environment
164 | */
165 | const PROD_SERVICES_ENDPOINT = 'https://payment.payline.com/services/servicesendpoints/SOAP';
166 |
167 | /**
168 | * web services endpoint in development environment
169 | */
170 | const DEV_ENDPOINT = 'https://ws.dev.payline.com/V4/services/';
171 |
172 | /**
173 | * web services endpoint in integration environment
174 | */
175 | const INT_ENDPOINT = 'https://ws.int.payline.com/V4/services/';
176 |
177 | /**
178 | * standard web services endpoint in homologation environment
179 | */
180 | const HOMO_ENDPOINT = 'https://homologation.payline.com/V4/services/';
181 |
182 | /**
183 | * certificate-based authentication web services endpoint in homologation environment
184 | */
185 | const HOMO_CC_ENDPOINT = 'https://homologation-cc.payline.com/V4/services/';
186 |
187 | /**
188 | * standard web services endpoint in production environment
189 | */
190 | const PROD_ENDPOINT = 'https://services.payline.com/V4/services/';
191 |
192 | /**
193 | * certificate-based authentication web services endpoint in production environment
194 | */
195 | const PROD_CC_ENDPOINT = 'https://services-cc.payline.com/V4/services/';
196 |
197 | /**
198 | * URL of getToken servlet, used by AJAX API, in development environment
199 | */
200 | const DEV_GET_TOKEN_SERVLET = "https://webpayment.dev.payline.com/webpayment/getToken";
201 |
202 | /**
203 | * URL of getToken servlet, used by AJAX API, in integration environment
204 | */
205 | const INT_GET_TOKEN_SERVLET = "https://webpayment.int.payline.com/webpayment/getToken";
206 |
207 | /**
208 | * URL of getToken servlet, used by AJAX API, in homologation environment
209 | */
210 | const HOMO_GET_TOKEN_SERVLET = "https://homologation-webpayment.payline.com/webpayment/getToken";
211 |
212 | /**
213 | * URL of getToken servlet, used by AJAX API, in production environment
214 | */
215 | const PROD_GET_TOKEN_SERVLET = "https://webpayment.payline.com/webpayment/getToken";
216 |
217 | /**
218 | * Widget JavaScript in development environment
219 | */
220 | const DEV_WDGT_JS = "https://webpayment.dev.payline.com/payline-widget/scripts/widget-min.js";
221 |
222 | /**
223 | * Widget JavaScript in homologation environment
224 | */
225 | const HOMO_WDGT_JS = "https://homologation-payment.payline.com/scripts/widget-min.js";
226 |
227 | /**
228 | * Widget JavaScript in production environment
229 | */
230 | const PROD_WDGT_JS = "https://payment.payline.com/scripts/widget-min.js";
231 |
232 | /**
233 | * Widget css in development environment
234 | */
235 | const DEV_WDGT_CSS = "https://webpayment.dev.payline.com/payline-widget/styles/widget-min.css";
236 |
237 | /**
238 | * Widget css in homologation environment
239 | */
240 | const HOMO_WDGT_CSS = "https://homologation-payment.payline.com/styles/widget-min.css";
241 |
242 | /**
243 | * Widget css in production environment
244 | */
245 | const PROD_WDGT_CSS = "https://payment.payline.com/styles/widget-min.css";
246 |
247 | /**
248 | * homologation administration center URL
249 | */
250 | const HOMO_CA = 'https://homologation-admin.payline.com';
251 |
252 | /**
253 | * administration center URL
254 | */
255 | const PROD_CA = 'https://admin.payline.com';
256 |
257 | /**
258 | * error code/shortMessage returned when Payline can't be reached
259 | */
260 | const ERR_CODE = 'XXXXX';
261 |
262 | const ERR_SHORT_MESSAGE = 'ERROR';
263 |
264 |
265 | /**
266 | * monext endpoint webservice url
267 | * @var string
268 | */
269 | protected $webServicesEndpoint;
270 |
271 | /**
272 | * @var Logger
273 | */
274 | protected $logger;
275 |
276 | /**
277 | * @var $loggerPath
278 | */
279 | protected $loggerPath;
280 |
281 |
282 | /**
283 | * tool / e-commerce module using this library
284 | */
285 | protected $usedBy = null;
286 |
287 | /**
288 | * array containing order details
289 | */
290 | protected $orderDetails;
291 |
292 | /**
293 | * array containing private data
294 | */
295 | protected $privateData;
296 |
297 |
298 | /**
299 | * array containing parent-child nodes associations
300 | */
301 | protected $parentNode = array(
302 | 'cards' => 'cardsList',
303 | 'billingRecord' => 'billingRecordList',
304 | 'walletId' => 'walletIdList',
305 | 'transaction' => 'transactionList',
306 | 'pointOfSell' => 'listPointOfSell',
307 | 'contract' => 'contracts',
308 | 'customPaymentPageCode' => 'customPaymentPageCodeList',
309 | 'function' => 'functions',
310 | 'details' => 'details',
311 | 'privateData' => 'privateDataList',
312 | 'associatedTransactions' => 'associatedTransactionsList',
313 | 'statusHistory' => 'statusHistoryList',
314 | 'paymentAdditional' => 'paymentAdditionalList',
315 | 'CustomerTrans' => 'CustomerTransHist',
316 | 'PaymentMeansTrans' => 'PaymentMeansTransHist',
317 | 'AlertsTrans' => 'AlertsTransHist'
318 | );
319 |
320 | protected $apiByMethod = array(
321 | 'doAuthorization'=>self::DIRECT_API,
322 | 'doCapture'=>self::DIRECT_API,
323 | 'doReAuthorization'=>self::DIRECT_API,
324 | 'doDebit'=>self::DIRECT_API,
325 | 'doRefund'=>self::DIRECT_API,
326 | 'doReset'=>self::DIRECT_API,
327 | 'doCredit'=>self::DIRECT_API,
328 | 'createWallet'=>self::DIRECT_API,
329 | 'updateWallet'=>self::DIRECT_API,
330 | 'getWallet'=>self::DIRECT_API,
331 | 'getCards'=>self::DIRECT_API,
332 | 'disableWallet'=>self::DIRECT_API,
333 | 'enableWallet'=>self::DIRECT_API,
334 | 'doImmediateWalletPayment'=>self::DIRECT_API,
335 | 'doScheduledWalletPayment'=>self::DIRECT_API,
336 | 'doRecurrentWalletPayment'=>self::DIRECT_API,
337 | 'getPaymentRecord'=>self::DIRECT_API,
338 | 'disablePaymentRecord'=>self::DIRECT_API,
339 | 'verifyEnrollment'=>self::DIRECT_API,
340 | 'verifyAuthentication'=>self::DIRECT_API,
341 | 'doScoringCheque'=>self::DIRECT_API,
342 | 'getEncryptionKey'=>self::DIRECT_API,
343 | 'getMerchantSettings'=>self::DIRECT_API,
344 | 'getBalance'=>self::DIRECT_API,
345 | 'getToken'=>self::DIRECT_API,
346 | 'unBlock'=>self::DIRECT_API,
347 | 'updatePaymentRecord'=>self::DIRECT_API,
348 | 'getBillingRecord'=>self::DIRECT_API,
349 | 'updateBillingRecord'=>self::DIRECT_API,
350 | 'doBankTransfer'=>self::DIRECT_API,
351 | 'isRegistered'=>self::DIRECT_API,
352 | 'doWebPayment'=>self::WEB_API,
353 | 'doAuthorizationRedirect'=>self::DIRECT_API,
354 | 'getWebPaymentDetails'=>self::WEB_API,
355 | 'manageWebWallet'=>self::WEB_API,
356 | 'createWebWallet'=>self::WEB_API,
357 | 'updateWebWallet'=>self::WEB_API,
358 | 'getWebWallet'=>self::WEB_API,
359 | 'getTransactionDetails'=>self::EXTENDED_API,
360 | 'transactionsSearch'=>self::EXTENDED_API,
361 | 'getAlertDetails'=>self::EXTENDED_API
362 | );
363 |
364 | protected $servicesEndpoint;
365 |
366 | protected $soapclientOptions = array();
367 |
368 | protected $failoverOptions = array();
369 |
370 | protected $lastSoapCallData = array();
371 |
372 | protected $logLevel = \Monolog\Logger::INFO;
373 |
374 | /**
375 | * PaylineSDK class constructor
376 | *
377 | * @param string $merchant_id
378 | * the merchant identifier
379 | * @param string $access_key
380 | * the access key generated in Payline Administration Center
381 | * @param string $proxy_host
382 | * host of your proxy (set null if no proxy)
383 | * @param string $proxy_port
384 | * port used by your proxy (set null if no proxy)
385 | * @param string $proxy_login
386 | * login required by your proxy (set null if no proxy)
387 | * @param string $proxy_password
388 | * password required by your proxy (set null if no proxy)
389 | * @param string $environment
390 | * target Payline environment : set PaylineSDK::ENV_HOMO for homologation, PaylineSDK::ENV_PROD for production
391 | * @param string $pathLog
392 | * path to your custom log folder, must end by directory separator. If null, default logs folder is used. Default : null
393 | * @param int $logLevel
394 | * \Monolog\Logger log level. Default : Logger::INFO
395 | * @param Logger $externalLogger
396 | * \Monolog\Logger instance, used by PaylineSDK but external to it
397 | */
398 | public function __construct($merchant_id, $access_key, $proxy_host, $proxy_port, $proxy_login, $proxy_password, $environment, $pathLog = null, $logLevel = Logger::INFO, $externalLogger = null, $defaultTimezone = "Europe/Paris")
399 | {
400 |
401 | $this->logLevel = $logLevel;
402 |
403 | if (is_int($merchant_id)) {
404 | $merchant_id = (string) $merchant_id;
405 | }
406 |
407 | $logfileDate = (new \DateTime('now', new \DateTimeZone($defaultTimezone)))->format('Y-m-d');
408 | if (empty($pathLog) || !is_dir($pathLog)) {
409 | $pathLog = realpath(dirname(dirname(__DIR__))) . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR;
410 | }
411 |
412 |
413 | if ($externalLogger) {
414 | $this->logger = $externalLogger;
415 | } else {
416 | $this->logger = new Logger('PaylineSDK');
417 | }
418 |
419 | $this->loggerPath = $pathLog . $logfileDate . '.log';
420 | try {
421 | if(is_writable($pathLog) || is_writable(dirname($pathLog))) {
422 | $this->logger->pushHandler(new StreamHandler($this->loggerPath, $logLevel)); // set default log folder
423 | }
424 | } catch (\Exception $e) {
425 | $this->loggerPath = null;
426 | //No logger can be used
427 | }
428 |
429 | $this->logger->info('__construct', array(
430 | 'merchant_id' => $this->hideChars($merchant_id, 6, 1),
431 | 'access_key' => $this->hideChars($access_key, 1, 3),
432 | 'proxy_host' => $proxy_host,
433 | 'proxy_port' => $proxy_port,
434 | 'proxy_login' => $proxy_login,
435 | 'proxy_password' => $this->hideChars($proxy_password, 1, 1),
436 | 'environment' => $environment
437 | ));
438 | $this->soapclientOptions = array();
439 | $this->soapclientOptions['login'] = $merchant_id;
440 | $this->soapclientOptions['password'] = $access_key;
441 | if ($proxy_host != '') {
442 | $this->soapclientOptions['proxy_host'] = $proxy_host;
443 | $this->soapclientOptions['proxy_port'] = $proxy_port;
444 | $this->soapclientOptions['proxy_login'] = $proxy_login;
445 | $this->soapclientOptions['proxy_password'] = $proxy_password;
446 | }
447 | $plnInternal = false;
448 | if (strcmp($environment, self::ENV_HOMO) == 0) {
449 | $this->webServicesEndpoint = self::HOMO_ENDPOINT;
450 | $this->servicesEndpoint = self::HOMO_SERVICES_ENDPOINT . '/' . $merchant_id;
451 | } elseif (strcmp($environment, self::ENV_HOMO_CC) == 0) {
452 | $this->webServicesEndpoint = self::HOMO_CC_ENDPOINT;
453 | } elseif (strcmp($environment, self::ENV_PROD) == 0) {
454 | $this->webServicesEndpoint = self::PROD_ENDPOINT;
455 | $this->servicesEndpoint = self::PROD_SERVICES_ENDPOINT . '/' . $merchant_id;
456 | } elseif (strcmp($environment, self::ENV_PROD_CC) == 0) {
457 | $this->webServicesEndpoint = self::PROD_CC_ENDPOINT;
458 | } elseif (strcmp($environment, self::ENV_DEV) == 0) {
459 | $this->webServicesEndpoint = self::DEV_ENDPOINT;
460 | $plnInternal = true;
461 | } elseif (strcmp($environment, self::ENV_INT) == 0) {
462 | $this->webServicesEndpoint = self::INT_ENDPOINT;
463 | $plnInternal = true;
464 | } else {
465 | $this->webServicesEndpoint = false; // Exception is raised in PaylineSDK::webServiceRequest
466 | $this->servicesEndpoint = false;
467 | }
468 | $this->soapclientOptions['trace'] = true;
469 | $this->soapclientOptions['stream_context_to_create'] = array();
470 |
471 | if ($plnInternal) {
472 | $this->soapclientOptions['stream_context_to_create']['ssl'] = array(
473 | 'verify_peer' => false,
474 | 'verify_peer_name' => false
475 | );
476 | }
477 |
478 | $this->orderDetails = array();
479 | $this->privateData = array();
480 | }
481 |
482 |
483 | /**
484 | * Set option passed to SoapClient
485 | *
486 | * @param $key
487 | * - style
488 | * - use
489 | * - connection_timeout
490 | * - trace
491 | * - soap_client (use of custom Soap client will disable failover mechanism)
492 | *
493 | *
494 | * @param null $value
495 | * @return $this
496 | * @throws \Exception
497 | */
498 | public function setSoapOptions($key, $value = null)
499 | {
500 | if(is_string($key)) {
501 | $this->soapclientOptions[$key] = $value;
502 | } else {
503 | throw new \Exception('Cannot set Soap option');
504 | }
505 | return $this;
506 | }
507 |
508 | public function getSoapOptions($key = null)
509 | {
510 | if($key) {
511 | return isset($this->soapclientOptions[$key]) ? $this->soapclientOptions[$key] : null;
512 | }
513 | return $this->soapclientOptions;
514 | }
515 |
516 | /**
517 | * @param $key
518 | * - disabled => true, false
519 | * - cache_pool => file (default), apc
520 | * - cache_file_path => directory path to store file cache
521 | * - cache_namespace
522 | * - cache_default_ttl *
523 | *
524 | * @param null $value
525 | * @return $this
526 | * @throws \Exception
527 | */
528 | public function setFailoverOptions($key, $value = null)
529 | {
530 | if(is_string($key)) {
531 | $this->failoverOptions[$key] = $value;
532 | } else {
533 | throw new \Exception('Cannot set Failover option');
534 | }
535 | return $this;
536 | }
537 |
538 | /**
539 | * @param $key
540 | * @return array|mixed|null
541 | */
542 | public function getFailoverOptions($key = null)
543 | {
544 | if($key) {
545 | return isset($this->failoverOptions[$key]) ? $this->failoverOptions[$key] : null;
546 | }
547 | return $this->failoverOptions;
548 | }
549 |
550 | /**
551 | * @return $this
552 | */
553 | public function reset()
554 | {
555 | $this->lastSoapCallData = array();
556 | $this->resetOrderDetails();
557 | $this->resetPrivateData();
558 | return $this;
559 | }
560 |
561 |
562 | public function resetFailoverOptions()
563 | {
564 | $this->failoverOptions = array();
565 | return $this;
566 | }
567 |
568 | /**
569 | * reset OrderDetails
570 | */
571 | public function resetOrderDetails()
572 | {
573 | $this->orderDetails = array();
574 | return $this;
575 | }
576 |
577 | /**
578 | * reset Private Data
579 | */
580 | public function resetPrivateData()
581 | {
582 | $this->privateData = array();
583 | return $this;
584 | }
585 |
586 | /**
587 | * get Private Data
588 | */
589 | public function privateDataList()
590 | {
591 | return $this->privateData;
592 | }
593 |
594 | /**
595 | * build PaymentData instance from $array and make SoapVar object for payment
596 | * @deprecated
597 | *
598 | * @param array $array
599 | * the array keys are listed in PaymentData class
600 | * @return SoapVar representation of PaymentData instance
601 | */
602 | protected function paymentData(array $array)
603 | {
604 | return $this->buildSoapObject($array, new PaymentData(), self::SOAP_PAYMENT_DATA);
605 | }
606 |
607 |
608 | /**
609 | * build Card instance from $array and make SoapVar object for card
610 | * @deprecated
611 | *
612 | * @param array $array
613 | * the array keys are listed in Card CLASS.
614 | * @return SoapVar representation of Card instance
615 | */
616 | protected function card(array $array)
617 | {
618 | $card = $this->fillObject($array, new Card());
619 | $card->paymentData = null;
620 |
621 | if (isset($array['paymentData'])) {
622 | $card->paymentData = $this->paymentData($array['paymentData']);
623 | }
624 | return new \SoapVar($card, SOAP_ENC_OBJECT, self::SOAP_CARD, SoapVarFactory::PAYLINE_NAMESPACE);
625 | }
626 |
627 |
628 | /**
629 | * build Address instance from $array and make SoapVar object for address.
630 | * @deprecated
631 | *
632 | * @param array $array
633 | * the array keys are listed in Address CLASS.
634 | * @return SoapVar representation of Address instance
635 | */
636 | protected function address(array $array)
637 | {
638 | return $this->buildSoapObject($array, new Address(), self::SOAP_ADDRESS);
639 | }
640 |
641 |
642 |
643 | /**
644 | * build BillingRecordForUpdate instance from $array and make SoapVar object for billingRecordForUpdate
645 | * @deprecated
646 | *
647 | * @param array $array
648 | * the array keys are listed in BillingRecordForUpdate CLASS.
649 | * @return SoapVar representation of BillingRecordForUpdate instance
650 | */
651 | protected function billingRecordForUpdate(array $array)
652 | {
653 | return $this->buildSoapObject($array, new BillingRecordForUpdate(), self::SOAP_BILLING_RECORD_FOR_UPDATE);
654 | }
655 |
656 | /**
657 | * build Wallet instance from $array and make SoapVar object for wallet
658 | * @deprecated
659 | *
660 | * @param array $array
661 | * the array keys are listed in Wallet CLASS.
662 | * @param array $shippingAddress
663 | * the array keys are listed in Address CLASS.
664 | * @param array $card
665 | * the array keys are listed in Card CLASS.
666 | * @return SoapVar representation of Wallet instance
667 | */
668 | protected function wallet(array $array, array $shippingAddress = array(), array $card = array())
669 | {
670 | $card = !empty($array['card']) ? $array['card'] : $card;
671 |
672 | $wallet = $this->fillObject($array, new Wallet());
673 | $wallet->card = $this->card($card);
674 | return new \SoapVar($wallet, SOAP_ENC_OBJECT, self::SOAP_WALLET, SoapVarFactory::PAYLINE_NAMESPACE);
675 | }
676 |
677 | /**
678 | * build Authorization instance from $array and make SoapVar object for authorization
679 | * @deprecated
680 | *
681 | * @param array $array
682 | * the array keys are listed in Authorization CLASS.
683 | * @return SoapVar representation of Authorization instance
684 | *
685 | */
686 | protected function authorization(array $array)
687 | {
688 | return $this->buildSoapObject($array, new Authorization(), self::SOAP_AUTHORIZATION);
689 |
690 | }
691 |
692 | /**
693 | * build Creditor instance from $array and make SoapVar object for creditor
694 | * @deprecated
695 | *
696 | * @param array $array
697 | * the array keys are listed in Creditor CLASS.
698 | * @return SoapVar representation of Creditor instance
699 | */
700 | protected function creditor(array $array)
701 | {
702 | return $this->buildSoapObject($array, new Creditor(), self::SOAP_CREDITOR);
703 | }
704 |
705 | /**
706 | * build Cheque instance from $array and make SoapVar object for cheque
707 | * @deprecated
708 | *
709 | * @param array $array
710 | * the array keys are listed in Cheque CLASS.
711 | * @return SoapVar representation of Cheque instance
712 | */
713 | protected function cheque(array $array)
714 | {
715 | return $this->buildSoapObject($array, new Cheque(), self::SOAP_CHEQUE);
716 | }
717 |
718 | /**
719 | * build Recurring instance from $array and make SoapVar object for recurring
720 | * @deprecated
721 | *
722 | * @param array $array
723 | * the array keys are listed in Recurring CLASS.
724 | * @return SoapVar representation of Recurring instance
725 | */
726 | protected function recurring(array $array)
727 | {
728 | return $this->buildSoapObject($array, new Recurring(), self::SOAP_RECURRING);
729 | }
730 |
731 | /**
732 | * build MerchantAuthentication instance from $array and make SoapVar object for merchantAuthentication
733 | * @deprecated
734 | *
735 | * @param array $array
736 | * the array keys list in MerchantAuthentication CLASS.
737 | * @return SoapVar representation of MerchantAuthentication instance
738 | */
739 | protected function merchantAuthentication(array $array) {
740 | return $this->buildSoapObject($array, new MerchantAuthentication(), self::SOAP_MERCHANT_AUTHENTICATION);
741 | }
742 |
743 |
744 | /**
745 | * Hide characters in a string
746 | *
747 | * @param String $inString
748 | * the string to hide
749 | * @param int $n1
750 | * number of characters shown at the begining of the string
751 | * @param int $n2
752 | * number of characters shown at end begining of the string
753 | */
754 | protected function hideChars($inString, $n1, $n2)
755 | {
756 | if(empty($inString)) {
757 | return '';
758 | }
759 |
760 | $inStringLength = strlen($inString);
761 | if ($inStringLength < ($n1 + $n2)) {
762 | return $inString;
763 | }
764 | $outString = substr($inString, 0, $n1);
765 | $outString .= substr("********************", 0, $inStringLength - ($n1 + $n2));
766 | $outString .= substr($inString, - ($n2));
767 | return $outString;
768 | }
769 |
770 | /**
771 | *
772 | * @param String $nodeName name of a node in a web service response
773 | * @param String $parentName name of its parent
774 | * @return boolean whether $nodeName is child from a list or not
775 | */
776 | protected function isChildFromList($nodeName,$parentName){
777 |
778 | if(array_key_exists($nodeName, $this->parentNode)){
779 | if(is_null($parentName)) {
780 | return is_null($this->parentNode[$nodeName]);
781 | }
782 | if(strcmp($this->parentNode[$nodeName],$parentName) == 0){
783 | return true;
784 | }
785 | }
786 | return false;
787 | }
788 |
789 | /**
790 | * make an array from a payline server response object.
791 | *
792 | * @param object $node
793 | * response node from payline web service
794 | * @param string $parent
795 | * name of the node's parent
796 | * @return array representation of the object
797 | */
798 | protected function responseToArray($node, $parent = null)
799 | {
800 | $array = array();
801 | foreach ($node as $k => $v) {
802 | if ($this->isChildFromList($k, $parent)) { // current value is a list
803 | if ($v instanceof \Countable && count($v) == 1 && $k != '0') { // a list with 1 element. It's returned with a 0-index
804 | $array[$k][0] = PaylineSDK::responseToArray($v, $k);
805 | } elseif (is_object($v) || is_array($v)) { // a list with more than 1 element
806 | $array[$k] = PaylineSDK::responseToArray($v, $k);
807 | } else {
808 | $array[$k] = $v;
809 | }
810 | } else {
811 | if (is_object($v) || is_array($v)) {
812 | $array[$k] = PaylineSDK::responseToArray($v, $k);
813 | } else {
814 | $array[$k] = $v;
815 | }
816 | }
817 | }
818 | return $array;
819 | }
820 |
821 | /**
822 | * Adds indexes with empty values to the web services request array, in order to prevent SOAP format exception
823 | *
824 | * @param array $array
825 | * associative array containing web services parameters
826 | */
827 | private function formatRequest(&$array)
828 | {
829 | //Key renaming
830 | $mappingKeys = array(
831 | '3DSecure' => 'authentication3DSecure',
832 | 'contracts' => 'selectedContractList',
833 | 'secondContracts' => 'secondSelectedContractList',
834 | 'walletContracts' => 'contractNumberWalletList',
835 | 'walletIds' => 'walletIdList',
836 | );
837 | foreach ($mappingKeys as $enterKey => $exitKey) {
838 | if(isset($array[$enterKey]) && !isset($array[$exitKey])) {
839 | $array[$exitKey] = $array[$enterKey];
840 | unset($array[$enterKey]);
841 | }
842 | }
843 |
844 | if (!isset($array['authentication3DSecure'])) {
845 | $array['authentication3DSecure'] = array();
846 | }
847 | if (!isset($array['bankAccountData'])) {
848 | $array['bankAccountData'] = array();
849 | }
850 | if (empty($array['cancelURL'])) {
851 | $array['cancelURL'] = null;
852 | }
853 | if (empty($array['notificationURL'])) {
854 | $array['notificationURL'] = null;
855 | }
856 | if (empty($array['returnURL'])) {
857 | $array['returnURL'] = null;
858 | }
859 | if (empty($array['languageCode'])) {
860 | $array['languageCode'] = null;
861 | }
862 | if (empty($array['securityMode'])) {
863 | $array['securityMode'] = null;
864 | }
865 |
866 | if (!isset($array['billingAddress'])) {
867 | $array['billingAddress'] = array();
868 | }
869 | if (!isset($array['shippingAddress'])) {
870 | $array['shippingAddress'] = array();
871 | }
872 |
873 | if (!isset($array['merchantAuthentication'])) {
874 | $array['merchantAuthentication'] = array();
875 | }
876 |
877 | if (!isset($array['buyer'])) {
878 | $array['buyer'] = array();
879 | }
880 |
881 | if (!isset($array['buyer']['billingAddress'])) {
882 | $array['buyer']['billingAddress'] = $array['billingAddress'];
883 | }
884 |
885 | //Backward Compatibility, take account of misspelling. "shippingAdress" versus "shippingAddress"
886 | if (!isset($array['buyer']['shippingAdress']) && isset($array['buyer']['shippingAddress'])) {
887 | $array['buyer']['shippingAdress'] = $array['buyer']['shippingAddress'];
888 | }
889 |
890 | if (!isset($array['buyer']['shippingAdress'])) {
891 | $array['buyer']['shippingAdress'] = $array['shippingAddress'];
892 | }
893 |
894 | if (!isset($array['buyer']['merchantAuthentication'])) {
895 | $array['buyer']['merchantAuthentication'] = $array['merchantAuthentication'];
896 | }
897 |
898 |
899 | if (!isset($array['ownerAddress'])) {
900 | $array['ownerAddress'] = array();
901 | }
902 |
903 | if (!isset($array['owner'])) {
904 | $array['owner'] = array();
905 | }
906 |
907 | if (!isset($array['owner']['ownerAddress'])) {
908 | $array['owner']['ownerAddress'] = $array['ownerAddress'];
909 | }
910 |
911 | //ownerAddress do not exist in wsdl
912 | if (!isset($array['owner']['billingAddress'])) {
913 | $array['owner']['billingAddress'] = $array['ownerAddress'];
914 | }
915 |
916 | if (empty($array['selectedContractList'][0])) {
917 | $array['selectedContractList'] = null;
918 | }
919 | if (empty($array['secondSelectedContractList'][0]) || !is_array($array['secondSelectedContractList'])) {
920 | $array['secondSelectedContractList'] = null;
921 | }
922 | if (empty($array['contractNumberWalletList'][0]) || !is_array($array['contractNumberWalletList'])) {
923 | $array['contractNumberWalletList'] = null;
924 | }
925 | if (empty($array['customPaymentPageCode'])) {
926 | $array['customPaymentPageCode'] = null;
927 | }
928 | if (empty($array['customPaymentTemplateURL'])) {
929 | $array['customPaymentTemplateURL'] = null;
930 | }
931 | if (!isset($array['recurring'])) {
932 | $array['recurring'] = null;
933 | }
934 | if (empty($array['orderRef'])) {
935 | $array['orderRef'] = null;
936 | }
937 | if (empty($array['orderDate'])) {
938 | $array['orderDate'] = null;
939 | }
940 | if (empty($array['walletIdList'][0])) {
941 | $array['walletIdList'] = null;
942 | }
943 | if (!isset($array['merchantName'])) {
944 | $array['merchantName'] = null;
945 | }
946 | if (!isset($array['miscData'])) {
947 | $array['miscData'] = null;
948 | }
949 | if (!isset($array['subMerchant'])) {
950 | $array['subMerchant'] = array();
951 | }
952 | if (!isset($array['asynchronousRetryTimeout'])) {
953 | $array['asynchronousRetryTimeout'] = null;
954 | }
955 |
956 | if (!isset($array['browser'])) {
957 | $array['browser'] = array();
958 | }
959 | if (!isset($array['sdk'])) {
960 | $array['sdk'] = array();
961 | }
962 | if (!isset($array['threeDSInfo']['sdk'])) {
963 | $array['threeDSInfo']['sdk'] = $array['sdk'];
964 | }
965 | if (!isset($array['threeDSInfo']['browser'])) {
966 | $array['threeDSInfo']['browser'] = $array['browser'];
967 | }
968 |
969 | if (!isset($array['updatePersonalDetails'])) {
970 | $array['updatePersonalDetails'] = null;
971 | }
972 | if (!isset($array['linkedTransactionId'])) {
973 | $array['linkedTransactionId'] = null;
974 | }
975 | if (!isset($array['transactionID'])) {
976 | $array['transactionID'] = null;
977 | }
978 | if (!isset($array['currency'])) {
979 | $array['currency'] = null;
980 | }
981 | if (!isset($array['amount'])) {
982 | $array['amount'] = null;
983 | }
984 | if (!isset($array['sequenceNumber'])) {
985 | $array['sequenceNumber'] = null;
986 | }
987 | if (!isset($array['merchantScore'])) {
988 | $array['merchantScore'] = null;
989 | }
990 | if (!isset($array['skipSmartDisplay'])) {
991 | $array['skipSmartDisplay'] = null;
992 | }
993 |
994 | if (!isset($array['walletId'])) {
995 | $array['walletId'] = null;
996 | }
997 |
998 | if (!isset($array['travelFileNumber'])) {
999 | $array['travelFileNumber'] = null;
1000 | }
1001 |
1002 | if (empty($array['version'])) {
1003 | $array['version'] = '';
1004 | }
1005 |
1006 | if (empty($array['media'])) {
1007 | $array['media'] = '';
1008 | }
1009 |
1010 | $array['order']['details'] = $this->orderDetails;
1011 | $array['privateDataList'] = $this->privateData;
1012 | }
1013 |
1014 |
1015 | protected function createSoapVarObject($elementKey, $array) {
1016 |
1017 | try {
1018 | $objectFactory = new SoapVarFactory();
1019 | $object = $objectFactory->create($elementKey, $array);
1020 | } catch (\Exception $e) {
1021 | $this->logger->error('Exception occured while createSoapVarObject for elementKey: ' . $elementKey, array(
1022 | 'code' => $e->getCode(),
1023 | 'message' => $e->getMessage()
1024 | ));
1025 | return null;
1026 | }
1027 |
1028 | return $object;
1029 | }
1030 |
1031 | /**
1032 | * Complete $WSRequest according wsdl definition
1033 | * (much more efficient than parsing with xpath)
1034 | *
1035 | * @param array $array
1036 | * @param $WSRequest
1037 | * @param $PaylineAPI
1038 | * @param $Method
1039 | * @return mixed
1040 | */
1041 | protected function completeWSRequest(array $array, $WSRequest, $PaylineAPI, $Method)
1042 | {
1043 | try {
1044 | $client = new SoapClient(__DIR__ . '/wsdl/' . $PaylineAPI . '.wsdl');
1045 | $types = $client->__getTypes();
1046 | foreach ($types as $type) {
1047 | if (strpos($type, 'struct ' . $Method . 'Request') === 0) {
1048 | if (preg_match_all('/ (\w+) (\w+)/', $type, $match)) {
1049 | foreach ($match[2] as $elementIndex => $elementKey) {
1050 | if (isset($WSRequest[$elementKey])) {
1051 | continue;
1052 | }
1053 | if ($match[1][$elementIndex] == "string") {
1054 | $elementValue = isset($array[$elementKey]) ? $array[$elementKey] : null;
1055 | $WSRequest[$elementKey] = $elementValue;
1056 | } else {
1057 | $WSRequest[$elementKey] = $this->createSoapVarObject($elementKey, $array);
1058 | }
1059 | }
1060 | }
1061 | }
1062 | }
1063 |
1064 | } catch (\SoapFault $fault) {
1065 | $this->logger->error('SoapFault occured while completeWSRequest for ' . $Method, array(
1066 | 'code' => $fault->getCode(),
1067 | 'message' => $fault->getMessage()
1068 | ));
1069 | } catch (\Exception $e) {
1070 | $this->logger->error('Exception occured while completeWSRequest for ' . $Method, array(
1071 | 'code' => $e->getCode(),
1072 | 'message' => $e->getMessage()
1073 | ));
1074 | }
1075 |
1076 | return $WSRequest;
1077 | }
1078 |
1079 |
1080 | public function getDefaultWSRequest($Method)
1081 | {
1082 | if( $PaylineAPI = $this->getApiForMethod($Method) ) {
1083 | return $this->completeWSRequest(array(), array(), $PaylineAPI, $Method);
1084 | }
1085 | return array();
1086 | }
1087 |
1088 |
1089 | /**
1090 | * @param $Method
1091 | * @return false|string
1092 | */
1093 | protected function getApiForMethod($Method)
1094 | {
1095 | if(array_key_exists($Method, $this->apiByMethod)) {
1096 | return $this->apiByMethod[$Method];
1097 | }
1098 | return false;
1099 | }
1100 |
1101 |
1102 | /**
1103 | * Create the SoapClient instance and make the web service call
1104 | *
1105 | * @param array $array
1106 | * the associative array passed to the public function
1107 | * @param array $WSRequest
1108 | * the SOAP-formated request
1109 | * @param string $PaylineAPI
1110 | * the Payline API to be called
1111 | * @param string $Method
1112 | * the name of the web service
1113 | */
1114 | protected function webServiceRequest(array $array, array $WSRequest, $PaylineAPI, $Method)
1115 | {
1116 |
1117 | $WSRequest = $this->completeWSRequest($array, $WSRequest, $PaylineAPI, $Method);
1118 |
1119 | $client = false;
1120 | $logRequest = array();
1121 |
1122 | try {
1123 | if(!$this->webServicesEndpoint){
1124 | throw new \Exception('Endpoint error (check `environment` parameter of PaylineSDK constructor)');
1125 | }
1126 |
1127 | $this->soapclientOptions['stream_context_to_create']['http'] = array(
1128 | 'user_agent' => "PHP",
1129 | 'header' => array('version' => $this->usedBy . ' - ' . self::SDK_RELEASE)
1130 | );
1131 |
1132 | $client = new WebserviceClient($PaylineAPI,
1133 | $this->webServicesEndpoint,
1134 | $this->servicesEndpoint,
1135 | $this->soapclientOptions,
1136 | array('logger_path'=>$this->loggerPath,
1137 | 'log_level'=>$this->logLevel,
1138 | 'wsdl' => __DIR__ . '/wsdl/' . $PaylineAPI . '.wsdl'
1139 | )
1140 | );
1141 |
1142 | $client->setFailoverOptions($this->failoverOptions);
1143 |
1144 | $logRequest = array(
1145 | 'transactionID' => isset($array['transactionID']) ? $array['transactionID'] : null,
1146 | 'order.ref' => isset($array['order']['ref']) ? $array['order']['ref'] : null,
1147 | 'payment.contractNumber' => isset($array['payment']['contractNumber']) ? $array['payment']['contractNumber'] : null,
1148 | 'payment.amount' => isset($array['payment']['amount']) ? $array['payment']['amount'] : null,
1149 | 'contractNumber' => isset($array['contractNumber']) ? $array['contractNumber'] : null,
1150 | 'walletId' => isset($array['wallet']['walletId']) ? $array['wallet']['walletId'] : null,
1151 | 'walletIdList' => isset($array['walletIdList']) ? implode(';', $array['walletIdList']) : null,
1152 | 'card.number' => isset($array['card']['number']) ? $this->hideChars($array['card']['number'], 4, 4) : null,
1153 | 'paymentRecordId ' => isset($array['paymentRecordId']) ? $array['transactionID'] : null,
1154 | 'billingRecordId' => isset($array['billingRecordId']) ? $array['transactionID'] : null,
1155 | 'alertId' => isset($array['AlertId']) ? $array['AlertId'] : null,
1156 | 'token' => isset($array['token']) ? $array['token'] : null,
1157 | 'orderID' => isset($array['orderID']) ? $array['orderID'] : null,
1158 | 'creditor.bic' => isset($array['creditor']['bic']) ? $this->hideChars($array['creditor']['bic'], 4, 1) : null ,
1159 | 'creditor.iban' => isset($array['creditor']['iban']) ? $this->hideChars($array['creditor']['iban'], 8, 1) : null
1160 | );
1161 | $logRequest = array_filter($logRequest);
1162 |
1163 |
1164 | $response = self::responseToArray($client->$Method($WSRequest));
1165 |
1166 | $logResponse = array(
1167 | 'result.code' => $response['result']['code']
1168 | );
1169 |
1170 | if ($response['result']['code'] == '00000' && isset($response['token'])) {
1171 | $logResponse['token'] = $response['token'];
1172 | } elseif ($response['result']['code'] == '02500' && isset($response['paymentRecordId'])) {
1173 | $logResponse['paymentRecordId'] = $response['paymentRecordId'];
1174 | }
1175 |
1176 | if (isset($response['transaction']['id'])) {
1177 | $logResponse['transaction.id'] = $response['transaction']['id'];
1178 | }
1179 |
1180 | if (isset($response['wallet']['card'])) {
1181 | $logResponse['wallet.card.number'] = $this->hideChars($response['wallet']['card']['number'], 4, 4);
1182 | }
1183 |
1184 | $this->logger->info($Method . 'Request', $logRequest);
1185 | $this->logger->info($Method . 'Response', $logResponse);
1186 |
1187 | if ($this->logLevel == \Monolog\Logger::DEBUG && $this->soapclientOptions['trace'] === true) {
1188 | foreach ($this->getSoapLastContent(null, false) as $callNum=>$callData) {
1189 | foreach ($callData as $callKey => $callValue) {
1190 | $this->logger->debug($Method . ', Last' . $callKey . ': ' . $callValue);
1191 | }
1192 | }
1193 | }
1194 | return $response;
1195 | } catch (\Exception $e) {
1196 | if($logRequest) {
1197 | $this->logger->info($Method . 'Request', $logRequest);
1198 | }
1199 | $this->logger->error('Exception occured at ' . $Method . ' call', array(
1200 | 'code' => $e->getCode(),
1201 | 'message' => $e->getMessage(),
1202 | 'endpoint' => $this->webServicesEndpoint . $PaylineAPI
1203 | ));
1204 | $ERROR = array();
1205 | $ERROR['result']['code'] = self::ERR_CODE;
1206 | $ERROR['result']['longMessage'] = $e->getMessage();
1207 | $ERROR['result']['shortMessage'] = self::ERR_SHORT_MESSAGE;
1208 | $ERROR['result']['partnerCode'] = null;
1209 | $ERROR['result']['partnerCodeLabel'] = null;
1210 |
1211 | return $ERROR;
1212 | } finally {
1213 | if($client) {
1214 | $this->lastSoapCallData = $client->retrieveSoapLastContent();
1215 | }
1216 | }
1217 | }
1218 |
1219 | /**
1220 | * Sets the name of the tool using this library (Magento for example...)
1221 | * Info is sent in HTTP header, an retrieved in "Technical monitoring of web services" screen of administration center
1222 | *
1223 | * @param string $toolName
1224 | * name of the tool using this library
1225 | */
1226 | public function usedBy($toolName)
1227 | {
1228 | $this->usedBy = $toolName;
1229 | }
1230 |
1231 | /**
1232 | * @return Logger \Monolog\Logger instance
1233 | */
1234 | public function getLogger()
1235 | {
1236 | return $this->logger;
1237 | }
1238 |
1239 | /**
1240 | * Adds details about an order item
1241 | *
1242 | * @param array $newOrderDetail
1243 | * associative array containing details about an order item
1244 | */
1245 | public function addOrderDetail(array $newOrderDetail)
1246 | {
1247 | $this->orderDetails[] = $this->buildSoapObject($newOrderDetail, new OrderDetail(), self::SOAP_ORDERDETAIL);
1248 | }
1249 |
1250 | /**
1251 | * Adds a privateData element
1252 | *
1253 | * @param array $array
1254 | * an array containing two indexes : key and value
1255 | *
1256 | */
1257 | public function addPrivateData(array $array)
1258 | {
1259 | $this->privateData[] = $this->buildSoapObject($array, new PrivateData(), self::SOAP_PRIVATE_DATA);
1260 | }
1261 |
1262 |
1263 | /*
1264 | * *************************************************************************
1265 | * DirectPaymentAPI
1266 | * *************************************************************************
1267 | */
1268 |
1269 | /**
1270 | * calls doAuthorization web service
1271 | *
1272 | * @param array $array
1273 | * associative array containing doAuthorization parameters
1274 | */
1275 | public function doAuthorization(array $array)
1276 | {
1277 | $this->formatRequest($array);
1278 | $WSRequest = array();
1279 |
1280 | if (isset($array['payment']['mode'])) {
1281 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1282 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1283 | }
1284 | }
1285 |
1286 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doAuthorization');
1287 | }
1288 |
1289 |
1290 | /**
1291 | * calls doCapture web service
1292 | *
1293 | * @param array $array
1294 | * associative array containing doCapture parameters
1295 | */
1296 | public function doCapture(array $array)
1297 | {
1298 | $this->formatRequest($array);
1299 | $WSRequest = array();
1300 |
1301 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doCapture');
1302 | }
1303 |
1304 | /**
1305 | * calls doReAuthorization web service
1306 | *
1307 | * @param array $array
1308 | * associative array containing doReAuthorization parameters
1309 | */
1310 | public function doReAuthorization(array $array)
1311 | {
1312 | $this->formatRequest($array);
1313 | $WSRequest = array();
1314 |
1315 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doReAuthorization');
1316 | }
1317 |
1318 | /**
1319 | * calls doDebit web service
1320 | *
1321 | * @param array $array
1322 | * associative array containing doDebit parameters
1323 | */
1324 | public function doDebit(array $array)
1325 | {
1326 | $this->formatRequest($array);
1327 |
1328 | $WSRequest = array(
1329 | 'privateDataList' => $this->privateData,
1330 | 'authorization' => $this->authorization($array['authorization']),
1331 | );
1332 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doDebit');
1333 | }
1334 |
1335 | /**
1336 | * calls doRefund web service
1337 | *
1338 | * @param array $array
1339 | * associative array containing doRefund parameters
1340 | */
1341 | public function doRefund($array)
1342 | {
1343 | $this->formatRequest($array);
1344 | $WSRequest = array();
1345 |
1346 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doRefund');
1347 | }
1348 |
1349 | /**
1350 | * calls doReset web service
1351 | *
1352 | * @param array $array
1353 | * associative array containing doReset parameters
1354 | */
1355 | public function doReset(array $array)
1356 | {
1357 | $this->formatRequest($array);
1358 | $WSRequest = array();
1359 |
1360 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doReset');
1361 | }
1362 |
1363 | /**
1364 | * calls doCredit web service
1365 | *
1366 | * @param array $array
1367 | * associative array containing doCredit parameters
1368 | */
1369 | public function doCredit(array $array)
1370 | {
1371 | $this->formatRequest($array);
1372 | $WSRequest = array();
1373 |
1374 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doCredit');
1375 | }
1376 |
1377 | /**
1378 | * calls createWallet web service
1379 | *
1380 | * @param array $array
1381 | * associative array containing createWallet parameters
1382 | */
1383 | public function createWallet(array $array)
1384 | {
1385 | $this->formatRequest($array);
1386 |
1387 | $WSRequest = array(
1388 | 'wallet' => $this->wallet($array['wallet'], $array['address'], $array['card']),
1389 | 'contractNumberWalletList' => $array['contractNumberWalletList']
1390 | );
1391 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'createWallet');
1392 | }
1393 |
1394 | /**
1395 | * calls updateWallet web service
1396 | *
1397 | * @param array $array
1398 | * associative array containing updateWallet parameters
1399 | */
1400 | public function updateWallet(array $array)
1401 | {
1402 | $this->formatRequest($array);
1403 |
1404 | $WSRequest = array(
1405 | 'wallet' => $this->wallet($array['wallet'], $array['address'], $array['card']),
1406 | 'contractNumberWalletList' => $array['contractNumberWalletList']
1407 | );
1408 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updateWallet');
1409 | }
1410 |
1411 | /**
1412 | * calls getWallet web service
1413 | *
1414 | * @param array $array
1415 | * associative array containing getWallet parameters
1416 | */
1417 | public function getWallet(array $array)
1418 | {
1419 | $this->formatRequest($array);
1420 | $WSRequest = array();
1421 |
1422 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getWallet');
1423 | }
1424 |
1425 | /**
1426 | * calls getCards web service
1427 | *
1428 | * @param array $array
1429 | * associative array containing getCards parameters
1430 | */
1431 | public function getCards(array $array)
1432 | {
1433 | $this->formatRequest($array);
1434 | $WSRequest = array();
1435 |
1436 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getCards');
1437 | }
1438 |
1439 | /**
1440 | * calls disableWallet web service
1441 | *
1442 | * @param array $array
1443 | * associative array containing disableWallet parameters
1444 | */
1445 | public function disableWallet(array $array)
1446 | {
1447 | $this->formatRequest($array);
1448 | $WSRequest = array();
1449 |
1450 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'disableWallet');
1451 | }
1452 |
1453 | /**
1454 | * calls enableWallet web service
1455 | *
1456 | * @param array $array
1457 | * associative array containing enableWallet parameters
1458 | */
1459 | public function enableWallet(array $array)
1460 | {
1461 | $this->formatRequest($array);
1462 | $WSRequest = array();
1463 |
1464 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'enableWallet');
1465 | }
1466 |
1467 | /**
1468 | * calls doImmediateWalletPayment web service
1469 | *
1470 | * @param array $array
1471 | * associative array containing doImmediateWalletPayment parameters
1472 | */
1473 | public function doImmediateWalletPayment(array $array)
1474 | {
1475 | $this->formatRequest($array);
1476 | $WSRequest = array();
1477 |
1478 | if (isset($array['payment']['mode'])) {
1479 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1480 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1481 | }
1482 | }
1483 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doImmediateWalletPayment');
1484 | }
1485 |
1486 | /**
1487 | * calls doScheduledWalletPayment web service
1488 | *
1489 | * @param array $array
1490 | * associative array containing doScheduledWalletPayment parameters
1491 | */
1492 | public function doScheduledWalletPayment(array $array)
1493 | {
1494 | $this->formatRequest($array);
1495 |
1496 | $WSRequest = array(
1497 | 'orderRef' => $array['orderRef'],
1498 | 'orderDate' => $array['orderDate'],
1499 | 'scheduledDate' => $array['scheduledDate']
1500 | );
1501 | if (isset($array['payment']['mode'])) {
1502 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1503 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1504 | }
1505 | }
1506 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doScheduledWalletPayment');
1507 | }
1508 |
1509 | /**
1510 | * calls doRecurrentWalletPayment web service
1511 | *
1512 | * @param array $array
1513 | * associative array containing doRecurrentWalletPayment parameters
1514 | */
1515 | public function doRecurrentWalletPayment(array $array)
1516 | {
1517 | $this->formatRequest($array);
1518 |
1519 | $WSRequest = array(
1520 | 'orderRef' => $array['orderRef'],
1521 | 'orderDate' => $array['orderDate'],
1522 | 'scheduledDate' => $array['scheduledDate']
1523 | );
1524 | if (isset($array['payment']['mode'])) {
1525 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1526 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1527 | }
1528 | }
1529 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doRecurrentWalletPayment');
1530 | }
1531 |
1532 | /**
1533 | * calls getPaymentRecord web service
1534 | *
1535 | * @param array $array
1536 | * associative array containing getPaymentRecord parameters
1537 | */
1538 | public function getPaymentRecord(array $array)
1539 | {
1540 | $this->formatRequest($array);
1541 | $WSRequest = array();
1542 |
1543 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getPaymentRecord');
1544 | }
1545 |
1546 | /**
1547 | * calls disablePaymentRecord web service
1548 | *
1549 | * @param array $array
1550 | * associative array containing disablePaymentRecord parameters
1551 | */
1552 | public function disablePaymentRecord(array $array)
1553 | {
1554 | $this->formatRequest($array);
1555 | $WSRequest = array();
1556 |
1557 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'disablePaymentRecord');
1558 | }
1559 |
1560 | /**
1561 | * calls verifyEnrollment web service
1562 | *
1563 | * @param array $array
1564 | * associative array containing verifyEnrollment parameters
1565 | */
1566 | public function verifyEnrollment(array $array)
1567 | {
1568 | $this->formatRequest($array);
1569 | $WSRequest = array();
1570 |
1571 | if (isset($array['payment']['mode'])) {
1572 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1573 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1574 | }
1575 | }
1576 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'verifyEnrollment');
1577 | }
1578 |
1579 | /**
1580 | * calls verifyAuthentication web service
1581 | *
1582 | * @param array $array
1583 | * associative array containing verifyAuthentication parameters
1584 | */
1585 | public function verifyAuthentication(array $array)
1586 | {
1587 | $this->formatRequest($array);
1588 | $WSRequest = array();
1589 |
1590 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'verifyAuthentication');
1591 | }
1592 |
1593 | /**
1594 | * calls doScoringCheque web service
1595 | *
1596 | * @param array $array
1597 | * associative array containing doScoringCheque parameters
1598 | */
1599 | public function doScoringCheque(array $array)
1600 | {
1601 | $this->formatRequest($array);
1602 |
1603 | $WSRequest = array(
1604 | 'cheque' => $this->cheque($array['cheque']),
1605 |
1606 | );
1607 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doScoringCheque');
1608 | }
1609 |
1610 | /**
1611 | * calls getEncryptionKey web service
1612 | *
1613 | * @param array $array
1614 | * associative array containing getEncryptionKey parameters
1615 | */
1616 | public function getEncryptionKey(array $array)
1617 | {
1618 | $this->formatRequest($array);
1619 | $WSRequest = array();
1620 |
1621 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getEncryptionKey');
1622 | }
1623 |
1624 | /**
1625 | * calls getMerchantSettings web service
1626 | *
1627 | * @param array $array
1628 | * associative array containing getMerchantSettings parameters
1629 | */
1630 | public function getMerchantSettings(array $array)
1631 | {
1632 | $this->formatRequest($array);
1633 | $WSRequest = array();
1634 |
1635 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getMerchantSettings');
1636 | }
1637 |
1638 | /**
1639 | * calls getBalance web service
1640 | *
1641 | * @param array $array
1642 | * associative array containing getBalance parameters
1643 | */
1644 | public function getBalance(array $array)
1645 | {
1646 | $this->formatRequest($array);
1647 | $WSRequest = array();
1648 |
1649 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getBalance');
1650 | }
1651 |
1652 | /**
1653 | * calls getToken web service
1654 | *
1655 | * @param array $array
1656 | * associative array containing getToken parameters
1657 | */
1658 | public function getToken(array $array)
1659 | {
1660 | $this->formatRequest($array);
1661 | $WSRequest = array();
1662 |
1663 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getToken');
1664 | }
1665 |
1666 | /**
1667 | * calls unBlock web service
1668 | *
1669 | * @param array $array
1670 | * associative array containing getBalance parameters
1671 | */
1672 | public function unBlock(array $array)
1673 | {
1674 | $this->formatRequest($array);
1675 | $WSRequest = array();
1676 |
1677 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'unBlock');
1678 | }
1679 |
1680 | /**
1681 | * calls updatePaymentRecord web service
1682 | *
1683 | * @param array $array
1684 | * associative array containing updatePaymentRecord parameters
1685 | */
1686 | public function updatePaymentRecord(array $array)
1687 | {
1688 | $this->formatRequest($array);
1689 |
1690 | $WSRequest = array(
1691 | 'recurring' => $this->recurring($array['recurring'])
1692 | );
1693 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updatePaymentRecord');
1694 | }
1695 |
1696 | /**
1697 | * calls getBillingRecord web service
1698 | *
1699 | * @param array $array
1700 | * associative array containing getBillingRecord parameters
1701 | */
1702 | public function getBillingRecord(array $array)
1703 | {
1704 | $this->formatRequest($array);
1705 | $WSRequest = array();
1706 |
1707 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'getBillingRecord');
1708 | }
1709 |
1710 | /**
1711 | * calls updateBillingRecord web service
1712 | *
1713 | * @param array $array
1714 | * associative array containing updateBillingRecord parameters
1715 | */
1716 | public function updateBillingRecord(array $array)
1717 | {
1718 | $this->formatRequest($array);
1719 |
1720 | $WSRequest = array(
1721 | 'billingRecordForUpdate' => $this->billingRecordForUpdate($array['billingRecordForUpdate'])
1722 | );
1723 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'updateBillingRecord');
1724 | }
1725 |
1726 | /**
1727 | * calls doBankTransfer web service
1728 | *
1729 | * @param array $array
1730 | * associative array containing doBankTransfer parameters
1731 | */
1732 | public function doBankTransfer(array $array)
1733 | {
1734 | $this->formatRequest($array);
1735 |
1736 | $WSRequest = array(
1737 | 'creditor' => $this->creditor($array['creditor']),
1738 | );
1739 |
1740 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doBankTransfer');
1741 | }
1742 |
1743 | /**
1744 | * calls isRegistered web service
1745 | *
1746 | * @param array $array
1747 | * associative array containing isRegistered parameters
1748 | */
1749 | public function isRegistered(array $array)
1750 | {
1751 | $this->formatRequest($array);
1752 | $WSRequest = array();
1753 |
1754 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'isRegistered');
1755 | }
1756 |
1757 | /**
1758 | * calls prepareSession web service
1759 | *
1760 | * @param array $array
1761 | * associative array containing prepareSession parameters
1762 | */
1763 | public function prepareSession(array $array)
1764 | {
1765 | $this->formatRequest($array);
1766 | $WSRequest = array();
1767 |
1768 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'prepareSession');
1769 | }
1770 |
1771 | /*
1772 | * *************************************************************************
1773 | * WebPaymentAPI
1774 | * *************************************************************************
1775 | */
1776 |
1777 | /**
1778 | * calls doWebPayment web service
1779 | *
1780 | * @param array $array
1781 | * associative array containing doWebPayment parameters
1782 | */
1783 | public function doWebPayment(array $array)
1784 | {
1785 | $this->formatRequest($array);
1786 | $WSRequest = array();
1787 |
1788 | if (isset($array['payment']['mode'])) {
1789 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1790 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1791 | }
1792 | }
1793 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'doWebPayment');
1794 | }
1795 |
1796 | /**
1797 | * calls doAuthorizationRedirect web service
1798 | *
1799 | * @param array $array
1800 | * associative array containing doAuthorizationRedirectRequest parameters
1801 | */
1802 | public function doAuthorizationRedirect(array $array)
1803 | {
1804 | $this->formatRequest($array);
1805 | $WSRequest = array();
1806 |
1807 | if (isset($array['payment']['mode'])) {
1808 | if (($array['payment']['mode'] == "REC") || ($array['payment']['mode'] == "NX")) {
1809 | $WSRequest['recurring'] = $this->recurring($array['recurring']);
1810 | }
1811 | }
1812 | return $this->webServiceRequest($array, $WSRequest, self::DIRECT_API, 'doAuthorizationRedirect');
1813 | }
1814 |
1815 | /**
1816 | * calls doWebPayment web service
1817 | *
1818 | * @param array $array
1819 | * associative array containing getWebPaymentDetails parameters
1820 | */
1821 | public function getWebPaymentDetails(array $array)
1822 | {
1823 | $this->formatRequest($array);
1824 | $WSRequest = array();
1825 |
1826 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'getWebPaymentDetails');
1827 | }
1828 |
1829 | /**
1830 | * calls manageWebWallet web service
1831 | *
1832 | * @param array $array
1833 | * associative array containing manageWebWallet parameters
1834 | */
1835 | public function manageWebWallet(array $array)
1836 | {
1837 | $this->formatRequest($array);
1838 | $WSRequest = array();
1839 |
1840 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'manageWebWallet');
1841 | }
1842 |
1843 | /**
1844 | * calls createWebWallet web service
1845 | *
1846 | * @param array $array
1847 | * associative array containing createWebWallet parameters
1848 | */
1849 | public function createWebWallet(array $array)
1850 | {
1851 | $this->formatRequest($array);
1852 | $WSRequest = array();
1853 |
1854 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'createWebWallet');
1855 | }
1856 |
1857 | /**
1858 | * calls updateWebWallet web service
1859 | *
1860 | * @param array $array
1861 | * associative array containing updateWebWallet parameters
1862 | */
1863 | public function updateWebWallet(array $array)
1864 | {
1865 | $this->formatRequest($array);
1866 | $WSRequest = array();
1867 |
1868 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'updateWebWallet');
1869 | }
1870 |
1871 | /**
1872 | * calls getWebWallet web service
1873 | *
1874 | * @param array $array
1875 | * associative array containing getWebWallet parameters
1876 | */
1877 | public function getWebWallet(array $array)
1878 | {
1879 | $this->formatRequest($array);
1880 | $WSRequest = array();
1881 |
1882 | return $this->webServiceRequest($array, $WSRequest, self::WEB_API, 'getWebWallet');
1883 | }
1884 |
1885 | /*
1886 | * *************************************************************************
1887 | * ExtendedAPI
1888 | * *************************************************************************
1889 | */
1890 |
1891 | /**
1892 | * calls getTransactionDetails web service
1893 | *
1894 | * @param array $array
1895 | * associative array containing getWebWallet parameters
1896 | */
1897 | public function getTransactionDetails(array $array)
1898 | {
1899 | $this->formatRequest($array);
1900 | $WSRequest = array();
1901 |
1902 | return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'getTransactionDetails');
1903 | }
1904 |
1905 | /**
1906 | * calls transactionsSearch web service
1907 | *
1908 | * @param array $array
1909 | * associative array containing getWebWallet parameters
1910 | */
1911 | public function transactionsSearch(array $array)
1912 | {
1913 | $this->formatRequest($array);
1914 | $WSRequest = array();
1915 |
1916 | return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'transactionsSearch');
1917 | }
1918 |
1919 | /**
1920 | * calls getAlertDetails web service
1921 | *
1922 | * @param array $array
1923 | * associative array containing getAlertDetails parameters
1924 | */
1925 | public function getAlertDetails(array $array)
1926 | {
1927 | $this->formatRequest($array);
1928 | $WSRequest = array();
1929 |
1930 | return $this->webServiceRequest($array, $WSRequest, self::EXTENDED_API, 'getAlertDetails');
1931 | }
1932 |
1933 |
1934 |
1935 |
1936 |
1937 | /**
1938 | * ************************************************************************
1939 | * End API methods
1940 | * ************************************************************************
1941 | */
1942 |
1943 |
1944 | /*
1945 | * ************************************************************************
1946 | * Ad hoc functions for AJAX API (getToken servlet)
1947 | * ************************************************************************
1948 | */
1949 |
1950 | /**
1951 | * Custom base64 url encoding.
1952 | * Replace unsafe url chars
1953 | *
1954 | * @param string $input
1955 | * message to encode
1956 | * @return string
1957 | */
1958 | public function base64_url_encode($input)
1959 | {
1960 | return strtr(base64_encode($input), '+/=', '-_,');
1961 | }
1962 |
1963 | /**
1964 | * Custom base64 url decode.
1965 | * Replace custom url safe values with normal
1966 | * base64 characters before decoding.
1967 | *
1968 | * @param string $input
1969 | * message to decode
1970 | * @return string
1971 | */
1972 | public function base64_url_decode($input)
1973 | {
1974 | return base64_decode(strtr($input, '-_,', '+/='));
1975 | }
1976 |
1977 | /**
1978 | * AES compliant encryption (uses MCRYPT_RIJNDAEL_128).
1979 | * This function is used to build authentication data for getToken servlet
1980 | *
1981 | * @param string $message
1982 | * message to encrypt
1983 | * @param string $accessKey
1984 | * merchant access key (SHA256 encrypted)
1985 | * @return string encrypted message
1986 | */
1987 | public function getEncrypt($message, $accessKey)
1988 | {
1989 | $cipher = "AES-256-ECB";
1990 | $opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
1991 |
1992 | $pad = 16;
1993 | $len = strlen($message);
1994 |
1995 | $padlen = $len + $pad - $len % $pad;
1996 | $message = str_pad(
1997 | $message,
1998 | $padlen,
1999 | chr($padlen - $len)
2000 | );
2001 |
2002 | $encrypted = openssl_encrypt($message, $cipher, $accessKey, $opts);
2003 |
2004 | return $this->base64_url_encode($encrypted);
2005 | }
2006 |
2007 | /**
2008 | * Decrypts message sent by getToken servlet
2009 | *
2010 | * @param string $message
2011 | * message to decrypt
2012 | * @param string $accessKey
2013 | * merchant access key (SHA256 encrypted)
2014 | */
2015 | public function getDecrypt($message, $accessKey)
2016 | {
2017 | $cipher = "AES-256-ECB";
2018 | $opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
2019 |
2020 | $message = $this->base64_url_decode($message);
2021 | $decrypted = openssl_decrypt($message, $cipher, $accessKey, $opts);
2022 | $len = strlen($decrypted);
2023 | $pad = ord($decrypted[$len - 1]);
2024 |
2025 | return substr($decrypted, 0, strlen($decrypted) - $pad);
2026 | }
2027 |
2028 | /**
2029 | * Unzip data
2030 | *
2031 | * @param string $data
2032 | * decrypted message sent by getToken servlet
2033 | * @param string $filename
2034 | * @param string $error
2035 | * @param int $maxlength
2036 | * @return NULL|boolean|string
2037 | */
2038 | public function gzdecode($data, &$filename = '', &$error = '', $maxlength = null)
2039 | {
2040 | $len = strlen($data);
2041 | if ($len < 18 || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
2042 | $error = "Not in GZIP format.";
2043 | return null; // Not GZIP format (See RFC 1952)
2044 | }
2045 | $method = ord(substr($data, 2, 1)); // Compression method
2046 | $flags = ord(substr($data, 3, 1)); // Flags
2047 | if ($flags & 31 != $flags) {
2048 | $error = "Reserved bits not allowed.";
2049 | return null;
2050 | }
2051 | // NOTE: $mtime may be negative (PHP integer limitations)
2052 | $mtime = unpack("V", substr($data, 4, 4));
2053 | $mtime = $mtime[1];
2054 | $headerlen = 10;
2055 | $extralen = 0;
2056 | if ($flags & 4) {
2057 | // 2-byte length prefixed EXTRA data in header
2058 | if ($len - $headerlen - 2 < 8) {
2059 | return false; // invalid
2060 | }
2061 | $extralen = unpack("v", substr($data, 8, 2));
2062 | $extralen = $extralen[1];
2063 | if ($len - $headerlen - 2 - $extralen < 8) {
2064 | return false; // invalid
2065 | }
2066 | $headerlen += 2 + $extralen;
2067 | }
2068 | $filenamelen = 0;
2069 | $filename = "";
2070 | if ($flags & 8) {
2071 | // C-style string
2072 | if ($len - $headerlen - 1 < 8) {
2073 | return false; // invalid
2074 | }
2075 | $filenamelen = strpos(substr($data, $headerlen), chr(0));
2076 | if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
2077 | return false; // invalid
2078 | }
2079 | $filename = substr($data, $headerlen, $filenamelen);
2080 | $headerlen += $filenamelen + 1;
2081 | }
2082 | $commentlen = 0;
2083 | if ($flags & 16) {
2084 | // C-style string COMMENT data in header
2085 | if ($len - $headerlen - 1 < 8) {
2086 | return false; // invalid
2087 | }
2088 | $commentlen = strpos(substr($data, $headerlen), chr(0));
2089 | if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
2090 | return false; // Invalid header format
2091 | }
2092 | $headerlen += $commentlen + 1;
2093 | }
2094 | $headercrc = "";
2095 | if ($flags & 2) {
2096 | // 2-bytes (lowest order) of CRC32 on header present
2097 | if ($len - $headerlen - 2 < 8) {
2098 | return false; // invalid
2099 | }
2100 | $calccrc = crc32(substr($data, 0, $headerlen)) & 0xffff;
2101 | $headercrc = unpack("v", substr($data, $headerlen, 2));
2102 | $headercrc = $headercrc[1];
2103 | if ($headercrc != $calccrc) {
2104 | $error = "Header checksum failed.";
2105 | return false; // Bad header CRC
2106 | }
2107 | $headerlen += 2;
2108 | }
2109 | // GZIP FOOTER
2110 | $datacrc = unpack("V", substr($data, - 8, 4));
2111 | $datacrc = sprintf('%u', $datacrc[1] & 0xFFFFFFFF);
2112 | $isize = unpack("V", substr($data, - 4));
2113 | $isize = $isize[1];
2114 | // decompression:
2115 | $bodylen = $len - $headerlen - 8;
2116 | if ($bodylen < 1) {
2117 | // IMPLEMENTATION BUG!
2118 | return null;
2119 | }
2120 | $body = substr($data, $headerlen, $bodylen);
2121 | $data = "";
2122 | if ($bodylen > 0) {
2123 | switch ($method) {
2124 | case 8:
2125 | // Currently the only supported compression method:
2126 | $data = gzinflate($body, $maxlength);
2127 | break;
2128 | default:
2129 | $error = "Unknown compression method.";
2130 | return false;
2131 | }
2132 | } // zero-byte body content is allowed
2133 | // Verifiy CRC32Date;Type;Value;ResulCode;ResultMessage
2134 | $crc = sprintf("%u", crc32($data));
2135 | $crcOK = $crc == $datacrc;
2136 | $lenOK = $isize == strlen($data);
2137 | if (! $lenOK || ! $crcOK) {
2138 | $error = ($lenOK ? '' : 'LengthsetSoapOptions check FAILED. ') . ($crcOK ? '' : 'Checksum FAILED.');
2139 | return false;
2140 | }
2141 | return $data;
2142 | }
2143 |
2144 | /**
2145 | * ************************************************************************
2146 | * Building Soap Objects
2147 | * @deprecated, should use SoapVarFactory
2148 | * ************************************************************************
2149 | */
2150 |
2151 | /**
2152 | * @deprecated
2153 | *
2154 | * @param array $array
2155 | * @param $object
2156 | * @param $typeName
2157 | * @return SoapVar
2158 | */
2159 | protected function buildSoapObject(array $array, $object, $typeName)
2160 | {
2161 | $object = $this->fillObject($array, $object);
2162 | return new \SoapVar($object, SOAP_ENC_OBJECT, $typeName, SoapVarFactory::PAYLINE_NAMESPACE);
2163 | }
2164 |
2165 | /**
2166 | * @deprecated
2167 | *
2168 | * @param array $array
2169 | * @param $object
2170 | * @return mixed
2171 | */
2172 | protected function fillObject(array $array, $object)
2173 | {
2174 | if ($array) {
2175 | foreach ($array as $k => $v) {
2176 | if (property_exists($object, $k) && $this->userDataIsNotEmpty($v)) {
2177 | $object->$k = $v;
2178 | }
2179 | }
2180 | }
2181 | return $object;
2182 | }
2183 |
2184 | /**
2185 | * Test user data
2186 | * @deprecated
2187 | *
2188 | * @param $data
2189 | * @return bool
2190 | */
2191 | protected function userDataIsNotEmpty($data) {
2192 |
2193 | if($data instanceof \Countable ) {
2194 | return (count($data)>0);
2195 | }
2196 | return !empty($data);
2197 | }
2198 |
2199 |
2200 | /**
2201 | * ************************************************************************
2202 | * Other tools
2203 | * ************************************************************************
2204 | */
2205 |
2206 |
2207 | /**
2208 | * Pretty print XML
2209 | *
2210 | * @param $xml
2211 | * @param $key
2212 | * @return void
2213 | */
2214 | protected function beautifulerXML(&$xml, $key) {
2215 | if(in_array($key, array('Request', 'Response')) && $xml) {
2216 | $dom = new \DOMDocument('1.0');
2217 | $dom->preserveWhiteSpace = false;
2218 | $dom->formatOutput = true;
2219 | $dom->loadXML($xml);
2220 | $xml = $dom->saveXML();
2221 | }
2222 | }
2223 |
2224 | /**
2225 | * @param string $key
2226 | * - Request
2227 | * - RequestHeaders
2228 | * - Response
2229 | * - ResponseHeaders
2230 | * - HttpHeaders
2231 | * @param false $beautifuler
2232 | * @return array
2233 | */
2234 | public function getSoapLastContent($key = '', $beautifuler = true)
2235 | {
2236 | $returnCall = array();
2237 | if($key) {
2238 | foreach ($this->lastSoapCallData as $callNum=>$callData) {
2239 | if(isset($callData[$key])) {
2240 | $returnCall[$callNum][$key] = $callData[$key];
2241 | }
2242 | }
2243 | } else {
2244 | $returnCall = $this->lastSoapCallData;
2245 | }
2246 |
2247 | if($beautifuler) {
2248 | foreach ($returnCall as $callNum=>$callData) {
2249 | array_walk($returnCall[$callNum], array($this, 'beautifulerXML'));
2250 | }
2251 | }
2252 |
2253 | return $returnCall;
2254 | }
2255 | }
--------------------------------------------------------------------------------
/src/Payline/SoapVarFactory.php:
--------------------------------------------------------------------------------
1 | createObject($elementKey, !empty($data[$elementKey]) ? $data[$elementKey] : null);
30 |
31 | return $paylineObject;
32 | }
33 |
34 |
35 | /**
36 | * @param $elementKey
37 | * @param $data
38 | * @param $default
39 | * @return \Payline\Objects\AbstractObject|null
40 | */
41 | public function createObject($elementKey, $data=null, $baseClassname=null) {
42 | $newObject = null;
43 | if ($newClassName = $this->getPaylineClassname($elementKey, $baseClassname)) {
44 | $newObject = new $newClassName();
45 |
46 | $soapVarType = $this->getSoapVarType($elementKey, $baseClassname);
47 |
48 | if($data && is_array($data)) {
49 | //TODO: Move list test in fillObject method
50 | if(preg_match('/(.*)List$/', $elementKey,$matchClassList)) {
51 | $pseudoListObject = [];
52 | $itemElementKey = $matchClassList[1];
53 | $itemClassName = $this->getPaylineClassname($itemElementKey, $baseClassname);
54 | if($itemClassName) {
55 | foreach ($data as $itemData) {
56 | if(is_array($itemData)) {
57 | $pseudoListObject[] = $this->getSoapVar($this->fillObject($itemData, new $itemClassName()), $soapVarType);
58 | } else {
59 | $pseudoListObject[] = $itemData;
60 | }
61 | }
62 | } elseif(property_exists($newObject, lcfirst($itemElementKey))) {
63 | $pseudoListObject = $newObject->{lcfirst($itemElementKey)} = $data;
64 | }
65 | return $pseudoListObject;
66 | }
67 |
68 | $this->fillObject($data, $newObject);
69 | }
70 |
71 |
72 | return $this->getSoapVar($newObject, $soapVarType);
73 | }
74 |
75 | return $newObject;
76 | }
77 |
78 | /**
79 | * Get SOAP var type
80 | * Should be same type as base classname
81 | * Manage exceptions: Buyer/BillingAddress, Buyer/ShippingAdress and Wallet/ShippingAddress
82 | *
83 | * @param $elementKey
84 | * @param $baseClassname
85 | * @return mixed|string
86 | */
87 | protected function getSoapVarType($elementKey, $baseClassname) {
88 | $soapVarType = $elementKey;
89 | if($className = $this->getPaylineClassname($elementKey, $baseClassname) ) {
90 |
91 | if(is_subclass_of($className, '\Payline\Objects\Address')) {
92 | $soapVarType = self::SOAP_ADDRESS;
93 | }
94 | }
95 |
96 | return $soapVarType;
97 | }
98 |
99 | /**
100 | * @param $newObject
101 | * @param $elementKey
102 | * @return \SoapVar
103 | */
104 | protected function getSoapVar($newObject, $varType) {
105 | return new \SoapVar($newObject, SOAP_ENC_OBJECT, $varType, self::PAYLINE_NAMESPACE);
106 | }
107 |
108 | /**
109 | * @param array $array
110 | * @param \Payline\Objects\AbstractObject $object
111 | * @return \Payline\Objects\AbstractObject
112 | */
113 | protected function fillObject(array $array, $object) {
114 | if ($array) {
115 | foreach ($array as $propertyKey => $propertyData) {
116 | $objectClassName = get_class($object);
117 | if (property_exists($object, $propertyKey)) {
118 | if($this->needCreateObjectProperty($object, $propertyKey, $objectClassName)) {
119 | $object->$propertyKey = $this->createObject($propertyKey, $propertyData, $objectClassName);
120 | } elseif($this->userDataIsNotEmpty($propertyData)) {
121 | $object->$propertyKey = $propertyData;
122 | }
123 | }
124 | }
125 | }
126 | return $object;
127 | }
128 |
129 | /**
130 | * @param \Payline\Objects\AbstractObject $object
131 | * @param $property
132 | * @return bool
133 | */
134 | protected function needCreateObjectProperty($object, $property, $baseClassname = null) {
135 | return $this->getPaylineClassname($property, $baseClassname);
136 | }
137 |
138 | /**
139 | * @param $elementKey
140 | * @return false|string
141 | */
142 | protected function getPaylineClassname($elementKey, $baseClassname = null) {
143 | $newClassName = "\\" . self::ROOT_CLASSNAME .
144 | ( $baseClassname ? str_replace(self::ROOT_CLASSNAME, "", $baseClassname) . "\\" : '' ) .
145 | ucfirst($elementKey);
146 |
147 | return class_exists($newClassName) ? $newClassName : false;
148 | }
149 |
150 | /**
151 | * Test user data
152 | *
153 | * @param $data
154 | * @return bool
155 | */
156 | protected function userDataIsNotEmpty($data) {
157 |
158 | if($data instanceof \Countable ) {
159 | return (count($data)>0);
160 | }
161 |
162 | //@see https://github.com/PaylineByMonext/payline-php-sdk/issues/101
163 | if($data===0 || $data==='0') {
164 | return true;
165 | }
166 |
167 | return !empty($data);
168 | }
169 | }
--------------------------------------------------------------------------------
/src/Payline/WebserviceClient.php:
--------------------------------------------------------------------------------
1 | setSdkAPI($paylineAPI);
130 | $this->setSdkDefaultLocation($sdkDefaultLocation);
131 | $this->setEndpointsDirectoryLocation($endpointsDirectoryLocation);
132 |
133 | $this->sdkWsdl = __DIR__ . '/wsdl/' . $paylineAPI . '.wsdl';
134 | if(!empty($params['wsdl'])) {
135 | $this->sdkWsdl = $params['wsdl'];
136 | }
137 |
138 | $this->soapOptions = $soapOptions;
139 |
140 | if(!empty($params['logger_path'])) {
141 | $logLevel = !empty($params['log_level']) ? $params['log_level'] : \Monolog\Logger::INFO;
142 | $this->logger = new Logger('PaylineSDK:WSClient');
143 | $this->logger->pushHandler(new StreamHandler($params['logger_path'], $logLevel)); // set default log folder
144 | }
145 |
146 | if(!empty($this->soapOptions['soap_client'])) {
147 | if ($this->soapOptions['soap_client'] instanceof SoapClient) {
148 | $this->setUseFailover(false);
149 | } else {
150 | throw new \Exception('soap_client is not an instance of SoapClient');
151 | }
152 | }
153 | }
154 |
155 | /**
156 | * Adds a log record at an arbitrary level.
157 | *
158 | * This method allows for compatibility with common interfaces.
159 | *
160 | * @param mixed $level The log level
161 | * @param string|Stringable $message The log message
162 | * @param mixed[] $context The log context
163 | *
164 | * @phpstan-param Level|LevelName|LogLevel::* $level
165 | */
166 | public function log($level, $message, array $context = []) {
167 | if($this->logger) {
168 | $this->logger->log($level, $message, $context);
169 | }
170 | }
171 |
172 |
173 | /**
174 | *
175 | * Basic params
176 | * - disabled => true, false
177 | * - cache_pool => file (default), apc
178 | * - cache_file_path => directory path to store file cache
179 | * - cache_namespace
180 | * - cache_default_ttl
181 | * Class properties
182 | * - services_with_failover => servicesWithFailover
183 | * - payline_error_list => paylineErrorList
184 | * - http_error_list => httpErrorList
185 | * - timeout_error_list => timeoutErrorList
186 | *
187 | *
188 | * @param array $options
189 | * @return $this
190 | */
191 | public function setFailoverOptions(array $options)
192 | {
193 | //Search for class properties
194 | foreach ($options as $optionKey => $optionValue) {
195 | if(in_array($optionKey, array('services_with_failover', 'payline_error_list', 'http_error_list', 'timeout_error_list'))) {
196 | if($this->setWebserviceProperty($optionKey, $optionValue)) {
197 | unset($options[$optionKey]);
198 | } else {
199 | throw new \Exception(sprintf('Cannot set property "%s" via setFailoverOptions', $optionKey));
200 | }
201 | }
202 | }
203 |
204 | if( isset($options['disabled']) && !empty($options['disabled']) ) {
205 | $this->setUseFailover(false);
206 | }
207 |
208 | $this->failoverOptions = $options;
209 | return $this;
210 | }
211 |
212 | /**
213 | * @param $property
214 | * @param $value
215 | * @return bool
216 | */
217 | protected function setWebserviceProperty($property, $value)
218 | {
219 | $classProperty = lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $property))));
220 | if(property_exists($this, $classProperty)) {
221 | $this->$classProperty = $value;
222 | return true;
223 | }
224 | return false;
225 | }
226 |
227 |
228 | /**
229 | * @param bool $use
230 | * @return $this
231 | */
232 | public function setUseFailover($use = true)
233 | {
234 | $this->useFailvover = (bool)$use;
235 | return $this;
236 | }
237 |
238 | /**
239 | * @param $location
240 | * @return $this
241 | */
242 | public function setSdkDefaultLocation($location)
243 | {
244 | $this->sdkDefaultLocation = $location;
245 | return $this;
246 | }
247 |
248 | /**
249 | * @param $api
250 | * @return $this
251 | */
252 | public function setSdkAPI($api)
253 | {
254 | $this->sdkAPI = $api;
255 | return $this;
256 | }
257 |
258 | /**
259 | * @param $location
260 | * @return $this
261 | */
262 | public function setEndpointsDirectoryLocation($location)
263 | {
264 | $this->endpointsDirectoryLocation = $location;
265 | return $this;
266 | }
267 |
268 |
269 | /**
270 | * @return int
271 | */
272 | public function getMinSoapTimeout()
273 | {
274 | $systemTimeout = defined('SOAP_CONNECTION_TIMEOUT') ? (int)SOAP_CONNECTION_TIMEOUT : 5;
275 | if(ini_get('default_socket_timeout')>0) {
276 | $systemTimeout = min($systemTimeout, (int)ini_get('default_socket_timeout'));
277 | }
278 |
279 | if(ini_get('max_execution_time')>0) {
280 | $systemTimeout = min($systemTimeout, (int)ini_get('max_execution_time'));
281 | }
282 |
283 | if(!empty($this->soapOptions['connection_timeout'])) {
284 | $systemTimeout = min($systemTimeout, (int)$this->soapOptions['connection_timeout']);
285 | }
286 |
287 | return (int)$systemTimeout;
288 | }
289 |
290 | /**
291 | * @param $method
292 | * @param $tryNum
293 | * @return SoapClient
294 | * @throws \SoapFault
295 | */
296 | protected function getClientSDK($method, $tryNum)
297 | {
298 | if(!$tryNum) {
299 | $this->lastCallData = [];
300 | }
301 | $sdkClient = false;
302 | if($this->useSercicesEndpointsFailover($method)) {
303 | if($location = $this->getFailoverServicesEndpoint($tryNum)) {
304 | $extraOptions = array();
305 | if($this->sdkFailoverCurrentHeaders) {
306 | $extraOptions = array('stream_context_to_create' => array(
307 | 'http' => array(
308 | 'header' => $this->sdkFailoverCurrentHeaders)));
309 |
310 | }
311 | $extraOptions['exceptions'] = true;
312 | $extraOptions['trace'] = true;
313 |
314 | $this->sdkFailoverCurrentLocation = $location;
315 | $sdkClient = $this->buildClientSdk($location . $this->sdkAPI, $extraOptions);
316 | }
317 |
318 | } else {
319 | $sdkClient = $this->buildClientSdk($this->sdkDefaultLocation . $this->sdkAPI);
320 | }
321 |
322 | if(!$sdkClient) {
323 | throw new \Exception('Cannot build SDK Soap client');
324 | }
325 |
326 | return $sdkClient;
327 | }
328 |
329 | /**
330 | * @param $location
331 | * @param array $extraOptions
332 | * @return SoapClient
333 | * @throws \SoapFault
334 | */
335 | protected function buildClientSdk($location, $extraOptions = array())
336 | {
337 | $defaultOptions = array();
338 | $defaultOptions['style'] = defined('SOAP_DOCUMENT') ? SOAP_DOCUMENT : 2;
339 | $defaultOptions['use'] = defined('SOAP_LITERAL') ? SOAP_LITERAL : 2;
340 | $defaultOptions['connection_timeout'] = $this->getMinSoapTimeout();
341 | $defaultOptions['trace'] = false;
342 |
343 | $options = array_merge($defaultOptions, $this->soapOptions);
344 | if(empty($options['proxy_login'])) {
345 | unset($options['proxy_login']);
346 | unset($options['proxy_password']);
347 | }
348 |
349 | if(!empty($extraOptions)) {
350 | $options = $this->array_merge_recursive_distinct($options, $extraOptions);
351 | }
352 |
353 | if(isset($options['stream_context_to_create'])) {
354 | if(!empty($options['stream_context_to_create'])) {
355 |
356 | if(!empty($options['stream_context_to_create']['http']['header']) && is_array($options['stream_context_to_create']['http']['header'])) {
357 | $httpHeader = array();
358 | foreach ($options['stream_context_to_create']['http']['header'] as $headerKey =>$headerValue) {
359 | $httpHeader[] = $headerKey . ': ' . $headerValue;
360 | }
361 | $options['stream_context_to_create']['http']['header'] = implode("\r\n", $httpHeader);
362 | }
363 |
364 | $options['stream_context'] = stream_context_create($options['stream_context_to_create']);
365 | }
366 | unset($options['stream_context_to_create']);
367 | }
368 |
369 | $sdkClient = new SoapClient($this->sdkWsdl, $options);
370 | if(!empty($options['soap_client']) && $options['soap_client'] instanceof SoapClient) {
371 | $sdkClient = $options['soap_client'];
372 | }
373 |
374 | $sdkClient->__setLocation($location);
375 |
376 | unset($options['proxy_login']);
377 | unset($options['proxy_password']);
378 |
379 | return $sdkClient;
380 | }
381 |
382 |
383 | /**
384 | * @return \Payline\Cache\CacheInterface
385 | */
386 | protected function getCachePool()
387 | {
388 | if(is_null($this->cachePool)) {
389 | $namespace = !empty($this->failoverOptions['cache_namespace']) ? $this->failoverOptions['cache_namespace'] : '';
390 | $ttl = !empty($this->failoverOptions['cache_default_ttl']) ? (int)$this->failoverOptions['cache_default_ttl'] : 0;
391 |
392 | $cachePool = !empty($this->failoverOptions['cache_pool']) ? $this->failoverOptions['cache_pool'] : 'file';
393 | switch ($cachePool) {
394 | case 'apc':
395 | $version = !empty($this->failoverOptions['cache_apc_version']) ? $this->failoverOptions['cache_apc_version'] : null;
396 | $this->cachePool = new \Payline\Cache\Apc($namespace, $ttl, $version);
397 | break;
398 | default:
399 | $directory = !empty($this->failoverOptions['cache_file_path']) ? $this->failoverOptions['cache_file_path'] : 'cache';
400 | $this->cachePool = new \Payline\Cache\File($namespace, $ttl, $directory);
401 | break;
402 | }
403 | }
404 |
405 | return $this->cachePool;
406 | }
407 |
408 | /**
409 | * @return bool
410 | */
411 | protected function getUseEndpointsDirectory()
412 | {
413 | return $this->useFailvover && !empty($this->endpointsDirectoryLocation) && $this->getCallEndpointsDirectoryMethod();
414 | }
415 |
416 |
417 | /**
418 | * @return false|string
419 | */
420 | protected function getCallEndpointsDirectoryMethod()
421 | {
422 | if(ini_get('allow_url_fopen') ) {
423 | return self::CALL_WITH_FILE_CONTENT;
424 | } elseif (extension_loaded('curl')) {
425 | return self::CALL_WITH_CURL;
426 | }
427 | return false;
428 | }
429 |
430 |
431 | /**
432 | * @return false|array
433 | */
434 | protected function getAllFailoverServicesEndpoint()
435 | {
436 | $endpointsUrls = array();
437 | $endpointsTTL = 60;
438 |
439 | if($this->getCachePool()->hasServicesEndpoints()) {
440 | $endpointsUrls = $this->getCachePool()->loadServicesEndpoints();
441 | } else {
442 | $method = $this->getCallEndpointsDirectoryMethod();
443 | $jsonContent = false;
444 |
445 | try {
446 | switch ($method) {
447 | case self::CALL_WITH_CURL:
448 | $ch = curl_init();
449 | curl_setopt($ch, CURLOPT_URL, $this->endpointsDirectoryLocation);
450 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
451 |
452 | // Use proxy parameters (from soap options in webclient)
453 | if (!empty($this->soapOptions['proxy_host'])) {
454 | $proxy = $this->soapOptions['proxy_host'].':'.$this->soapOptions['proxy_port'];
455 | curl_setopt($ch, CURLOPT_PROXY, $proxy);
456 |
457 | if(!empty($this->soapOptions['proxy_login']) && !empty($this->soapOptions['proxy_password'])) {
458 | $proxyAuth = $this->soapOptions['proxy_login'] . ':' . $this->soapOptions['proxy_password'];
459 | curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxyAuth);
460 | }
461 | }
462 |
463 | $jsonContent = curl_exec($ch);
464 | curl_close($ch);
465 | break;
466 | case self::CALL_WITH_FILE_CONTENT:
467 | $opts = array(
468 | 'http'=>array(
469 | 'method'=>"GET"
470 | )
471 | );
472 | // Use proxy parameters (from soap options in webclient)
473 | if (!empty($this->soapOptions['proxy_host'])) {
474 | $opts['http']['proxy'] = $this->soapOptions['proxy_host'].':'.$this->soapOptions['proxy_port'];
475 | $opts['http']['request_fulluri'] = true;
476 | if(!empty($this->soapOptions['proxy_login']) && !empty($this->soapOptions['proxy_password'])) {
477 | $proxyAuth = base64_encode($this->soapOptions['proxy_login'] . ':' . $this->soapOptions['proxy_password']);
478 | $opts['http']['header'] = "Proxy-Authorization: Basic " . $proxyAuth;
479 | }
480 | }
481 | $context = stream_context_create($opts);
482 | $jsonContent = file_get_contents($this->endpointsDirectoryLocation, false, $context);
483 | break;
484 | default:
485 | break;
486 | }
487 |
488 | if(!empty($jsonContent)) {
489 | $endpointData = json_decode($jsonContent, true);
490 | if (!empty($endpointData['urls']) && is_array($endpointData['urls'])) {
491 | $endpointsUrls = $endpointData['urls'];
492 | foreach ($endpointsUrls as $endpointKey => $endpointUrl) {
493 | $endpointsUrls[$endpointKey] = $endpointUrl . '/services/';
494 | }
495 | $endpointsTTL = $endpointData['ttl'];
496 | }
497 | }
498 |
499 | } catch ( \Exception $e) {
500 |
501 | }
502 |
503 | if(!empty($endpointsUrls)) {
504 | $this->getCachePool()->saveServicesEndpoints($endpointsUrls, $endpointsTTL);
505 | } else {
506 | $endpointsUrls = array($this->sdkDefaultLocation);
507 | }
508 |
509 | }
510 |
511 | return $endpointsUrls;
512 | }
513 |
514 |
515 | /**
516 | * @return false|string
517 | */
518 | protected function getFailoverServicesEndpoint($tryNumber)
519 | {
520 | if(is_null($this->endpointsUrls)) {
521 | $this->endpointsUrls = $this->getAllFailoverServicesEndpoint();
522 | }
523 | $serviceIndex = $tryNumber -1;
524 |
525 | return !empty($this->endpointsUrls[$serviceIndex]) ? $this->endpointsUrls[$serviceIndex] : false;
526 | }
527 |
528 | /**
529 | * @param string $error
530 | * @param int $tryNumber
531 | * @param int $callDuration
532 | * @return bool
533 | */
534 | protected function switchSoapContext($error = '', $nextTryNum=0, $callDuration = 0)
535 | {
536 | $location = $this->getFailoverServicesEndpoint($nextTryNum);
537 | if($location) {
538 | if ($nextTryNum>0) {
539 | $headers = array();
540 | $headers['x-failover-cause'] = $error;
541 | $headers['x-failover-duration'] = $callDuration;
542 | $headers['x-failover-origin'] = $this->sdkFailoverCurrentLocation;
543 | $headers['x-failover-index'] = $nextTryNum -1;
544 | }
545 |
546 | $this->sdkFailoverCurrentHeaders = $headers;
547 | return true;
548 | }
549 |
550 | return false;
551 | }
552 |
553 |
554 | /**
555 | * @param string $name
556 | * @param array $args
557 | * @return mixed
558 | * @throws \Exception
559 | */
560 | public function __call($method, $args = null)
561 | {
562 | $this->tryNum++;
563 | $callStart = microtime(true);
564 | $WSRequest = isset($args[0]) ? $args[0] : null;
565 |
566 | try {
567 | $sdkClient = $this->getClientSDK($method, $this->tryNum);
568 | $response = $sdkClient->$method($WSRequest);
569 | $this->saveCallData($sdkClient);
570 | if($this->switchSoapContextFailoverOnPaylineError($method, $this->tryNum+1, $callStart, $response)) {
571 | return $this->__call($method, $args);
572 | }
573 | return $response;
574 | } catch ( \SoapFault $fault) {
575 | $identifiedSoapError = false;
576 | $lastResponseHeader = '';
577 |
578 | if($sdkClient instanceof SoapClient) {
579 | $this->saveCallData($sdkClient);
580 | $lastResponseHeader = $sdkClient->__getLastResponseHeaders();
581 | }
582 |
583 | if(empty($lastResponseHeader)
584 | && in_array($fault->faultstring, $this->timeoutErrorList)
585 | ) {
586 | $identifiedSoapError = self::ERROR_CODE_TIMEOUT;
587 | } elseif (preg_match("/HTTP\/\d\.\d\s*\K[\d]+/", $lastResponseHeader,$match)) {
588 | $identifiedSoapError = $match[0];
589 | }
590 |
591 | if($identifiedSoapError && $this->switchSoapContextFailoverOnFault($method, $this->tryNum+1, $callStart, $identifiedSoapError)) {
592 | return $this->__call($method, $args);
593 | }
594 |
595 | throw $fault;
596 | } catch ( \Exception $e) {
597 | throw $e;
598 | }
599 | }
600 |
601 |
602 | /**
603 | * @param SoapClient $sdkClient
604 | * @return void
605 | */
606 | protected function saveCallData($sdkClient) {
607 | if(!$sdkClient instanceof SoapClient) {
608 | return;
609 | }
610 |
611 | $this->lastCallData[$this->tryNum] = array(
612 | 'Request' => $sdkClient->__getLastRequest(),
613 | 'RequestHeaders' => $sdkClient->__getLastRequestHeaders(),
614 | 'HttpHeaders' => $this->sdkFailoverCurrentHeaders,
615 | 'Response' => $sdkClient->__getLastResponse(),
616 | 'ResponseHeaders' => $sdkClient->__getLastResponseHeaders()
617 |
618 | );
619 | }
620 |
621 |
622 |
623 | /**
624 | * @param $method
625 | * @return bool
626 | */
627 | protected function useSercicesEndpointsFailover($method) {
628 | return $this->getUseEndpointsDirectory() && in_array($method, $this->servicesWithFailover);
629 | }
630 |
631 |
632 | /**
633 | * @param $method
634 | * @param $nextTryNum
635 | * @param $callStart
636 | * @param $response
637 | * @return bool
638 | */
639 | protected function switchSoapContextFailoverOnPaylineError($method, $nextTryNum, $callStart, $response) {
640 | $callDuration = round(1000 * (microtime(true) - $callStart));
641 |
642 | if( $this->useSercicesEndpointsFailover($method) &&
643 | in_array($response->result->code, $this->paylineErrorList)) {
644 |
645 | $error = 'APP_' . $response->result->code;
646 |
647 | return $this->switchSoapContext($error, $nextTryNum, $callDuration);
648 | }
649 | return false;
650 | }
651 |
652 |
653 | /**
654 | * @param $method
655 | * @param $nextTryNum
656 | * @param $callStart
657 | * @param \SoapFault $fault
658 | * @return bool
659 | */
660 | //protected function switchSoapContextFailoverOnFault($method, $nextTryNum, $callStart, \SoapFault $fault) {
661 | protected function switchSoapContextFailoverOnFault($method, $nextTryNum, $callStart, $errorCode) {
662 | $callDuration = round(1000 * (microtime(true) - $callStart));
663 | if($this->useSercicesEndpointsFailover($method) &&
664 | in_array($errorCode, $this->httpErrorList)) {
665 |
666 | if(self::ERROR_CODE_TIMEOUT == $errorCode) {
667 | $error = $errorCode;
668 | } else {
669 | $error = 'HTTP_' . $errorCode;
670 | }
671 | return $this->switchSoapContext($error, $nextTryNum, $callDuration);
672 | }
673 | return false;
674 | }
675 |
676 |
677 |
678 | /**
679 | * @deprecated Not used
680 | *
681 | * @param $method
682 | * @param $nextTryNum
683 | * @param $callStart
684 | * @param \SoapFault $fault
685 | * @return bool
686 | */
687 | protected function switchSoapContextFailoverOnException($method, $nextTryNum, $callStart, \Exception $e) {
688 | $callDuration = round(1000 * (microtime(true) - $callStart));
689 | if($this->useSercicesEndpointsFailover($method) &&
690 | in_array($e->getCode(), $this->exeptionErrorList)) {
691 |
692 | $error = 'EXCEPTION';
693 |
694 | return $this->switchSoapContext($error, $nextTryNum, $callDuration);
695 | }
696 | return false;
697 | }
698 |
699 |
700 |
701 | /**
702 | *
703 | * @see https://www.php.net/manual/en/function.array-merge-recursive.php#92195
704 | *
705 | *
706 | * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
707 | * keys to arrays rather than overwriting the value in the first array with the duplicate
708 | * value in the second array, as array_merge does. I.e., with array_merge_recursive,
709 | * this happens (documented behavior):
710 | *
711 | * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
712 | * => array('key' => array('org value', 'new value'));
713 | *
714 | * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
715 | * Matching keys' values in the second array overwrite those in the first array, as is the
716 | * case with array_merge, i.e.:
717 | *
718 | * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
719 | * => array('key' => array('new value'));
720 | *
721 | * Parameters are passed by reference, though only for performance reasons. They're not
722 | * altered by this function.
723 | *
724 | * @param array $array1
725 | * @param array $array2
726 | * @return array
727 | * @author Daniel
728 | * @author Gabriel Sobrinho
729 | */
730 | protected function array_merge_recursive_distinct ( array &$array1, array &$array2 )
731 | {
732 | $merged = $array1;
733 |
734 | foreach ( $array2 as $key => &$value )
735 | {
736 | if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
737 | {
738 | $merged [$key] = $this->array_merge_recursive_distinct ( $merged [$key], $value );
739 | }
740 | else
741 | {
742 | $merged [$key] = $value;
743 | }
744 | }
745 |
746 | return $merged;
747 | }
748 |
749 | /**
750 | * @param string $key
751 | * @return array|false|mixed
752 | */
753 | public function retrieveSoapLastContent()
754 | {
755 | return $this->lastCallData;
756 | }
757 |
758 | }
--------------------------------------------------------------------------------