1
|
|
|
<?php if (! defined('EVENT_ESPRESSO_VERSION')) { |
2
|
|
|
exit('NO direct script access allowed'); |
3
|
|
|
} |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* ---------------------------------------------- |
9
|
|
|
* Class EEG_Paypal_Express |
10
|
|
|
* |
11
|
|
|
* @package Event Espresso |
12
|
|
|
* @subpackage eea-paypal-express |
13
|
|
|
* @author Event Espresso |
14
|
|
|
* @version $VID:$ |
15
|
|
|
* ---------------------------------------------- |
16
|
|
|
*/ |
17
|
|
|
//Quickfix to address https://events.codebasehq.com/projects/event-espresso/tickets/11089 ASAP |
18
|
|
|
if (! function_exists('mb_strcut')) { |
19
|
|
|
/** |
20
|
|
|
* Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr |
21
|
|
|
* (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks) |
22
|
|
|
* @param $string |
23
|
|
|
* @param $start |
24
|
|
|
* @param $length |
25
|
|
|
* @return bool|string |
26
|
|
|
*/ |
27
|
|
|
function mb_strcut($string, $start, $length = null) |
28
|
|
|
{ |
29
|
|
|
return mb_substr($string, $start, $length); |
30
|
|
|
} |
31
|
|
|
} |
32
|
|
|
class EEG_Paypal_Express extends EE_Offsite_Gateway |
33
|
|
|
{ |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Merchant API Username. |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
protected $_api_username; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Merchant API Password. |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
protected $_api_password; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* API Signature. |
51
|
|
|
* |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
protected $_api_signature; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Request Shipping address on PP checkout page. |
58
|
|
|
* |
59
|
|
|
* @var string |
60
|
|
|
*/ |
61
|
|
|
protected $_request_shipping_addr; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Business/personal logo. |
65
|
|
|
* |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
protected $_image_url; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* gateway URL variable |
72
|
|
|
* |
73
|
|
|
* @var string |
74
|
|
|
*/ |
75
|
|
|
protected $_base_gateway_url = ''; |
76
|
|
|
|
77
|
|
|
|
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* EEG_Paypal_Express constructor. |
81
|
|
|
*/ |
82
|
|
|
public function __construct() |
83
|
|
|
{ |
84
|
|
|
$this->_currencies_supported = array( |
85
|
|
|
'USD', |
86
|
|
|
'AUD', |
87
|
|
|
'BRL', |
88
|
|
|
'CAD', |
89
|
|
|
'CZK', |
90
|
|
|
'DKK', |
91
|
|
|
'EUR', |
92
|
|
|
'HKD', |
93
|
|
|
'HUF', |
94
|
|
|
'ILS', |
95
|
|
|
'JPY', |
96
|
|
|
'MYR', |
97
|
|
|
'MXN', |
98
|
|
|
'NOK', |
99
|
|
|
'NZD', |
100
|
|
|
'PHP', |
101
|
|
|
'PLN', |
102
|
|
|
'GBP', |
103
|
|
|
'RUB', |
104
|
|
|
'SGD', |
105
|
|
|
'SEK', |
106
|
|
|
'CHF', |
107
|
|
|
'TWD', |
108
|
|
|
'THB', |
109
|
|
|
'TRY', |
110
|
|
|
); |
111
|
|
|
parent::__construct(); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
|
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Sets the gateway URL variable based on whether debug mode is enabled or not. |
118
|
|
|
* |
119
|
|
|
* @param array $settings_array |
120
|
|
|
*/ |
121
|
|
|
public function set_settings($settings_array) |
122
|
|
|
{ |
123
|
|
|
parent::set_settings($settings_array); |
124
|
|
|
// Redirect URL. |
125
|
|
|
$this->_base_gateway_url = $this->_debug_mode |
126
|
|
|
? 'https://api-3t.sandbox.paypal.com/nvp' |
127
|
|
|
: 'https://api-3t.paypal.com/nvp'; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
|
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param EEI_Payment $payment |
134
|
|
|
* @param array $billing_info |
135
|
|
|
* @param string $return_url |
136
|
|
|
* @param string $notify_url |
137
|
|
|
* @param string $cancel_url |
138
|
|
|
* @return \EE_Payment|\EEI_Payment |
139
|
|
|
* @throws \EE_Error |
140
|
|
|
*/ |
141
|
|
|
public function set_redirection_info( |
142
|
|
|
$payment, |
143
|
|
|
$billing_info = array(), |
144
|
|
|
$return_url = null, |
145
|
|
|
$notify_url = null, |
146
|
|
|
$cancel_url = null |
147
|
|
|
) { |
148
|
|
View Code Duplication |
if (! $payment instanceof EEI_Payment) { |
149
|
|
|
$payment->set_gateway_response( |
150
|
|
|
esc_html__( |
151
|
|
|
'Error. No associated payment was found.', |
152
|
|
|
'event_espresso' |
153
|
|
|
) |
154
|
|
|
); |
155
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
156
|
|
|
return $payment; |
157
|
|
|
} |
158
|
|
|
$transaction = $payment->transaction(); |
159
|
|
View Code Duplication |
if (! $transaction instanceof EEI_Transaction) { |
160
|
|
|
$payment->set_gateway_response( |
161
|
|
|
esc_html__( |
162
|
|
|
'Could not process this payment because it has no associated transaction.', |
163
|
|
|
'event_espresso' |
164
|
|
|
) |
165
|
|
|
); |
166
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
167
|
|
|
return $payment; |
168
|
|
|
} |
169
|
|
|
$order_description = mb_strcut($this->_format_order_description($payment), 0, 127); |
|
|
|
|
170
|
|
|
$primary_registration = $transaction->primary_registration(); |
171
|
|
|
$primary_attendee = $primary_registration instanceof EE_Registration |
172
|
|
|
? $primary_registration->attendee() |
173
|
|
|
: false; |
174
|
|
|
$locale = explode('-', get_bloginfo('language')); |
175
|
|
|
// Gather request parameters. |
176
|
|
|
$token_request_dtls = array( |
177
|
|
|
'METHOD' => 'SetExpressCheckout', |
178
|
|
|
'PAYMENTREQUEST_0_AMT' => $payment->amount(), |
179
|
|
|
'PAYMENTREQUEST_0_CURRENCYCODE' => $payment->currency_code(), |
180
|
|
|
'PAYMENTREQUEST_0_DESC' => $order_description, |
181
|
|
|
'RETURNURL' => $return_url, |
182
|
|
|
'CANCELURL' => $cancel_url, |
183
|
|
|
'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', |
184
|
|
|
// Buyer does not need to create a PayPal account to check out. |
185
|
|
|
// This is referred to as PayPal Account Optional. |
186
|
|
|
'SOLUTIONTYPE' => 'Sole', |
187
|
|
|
//EE will blow up if you change this |
188
|
|
|
'BUTTONSOURCE' => 'EventEspresso_SP', |
189
|
|
|
// Locale of the pages displayed by PayPal during Express Checkout. |
190
|
|
|
'LOCALECODE' => $locale[1] |
191
|
|
|
); |
192
|
|
|
// Show itemized list. |
193
|
|
|
$itemized_list = $this->itemize_list($payment, $transaction); |
194
|
|
|
$token_request_dtls = array_merge($token_request_dtls, $itemized_list); |
195
|
|
|
// Automatically filling out shipping and contact information. |
196
|
|
|
if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) { |
197
|
|
|
// If you do not pass the shipping address, PayPal obtains it from the buyer's account profile. |
198
|
|
|
$token_request_dtls['NOSHIPPING'] = '2'; |
199
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address(); |
200
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2(); |
201
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city(); |
202
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTATE'] = $primary_attendee->state_abbrev(); |
203
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $primary_attendee->country_ID(); |
204
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip(); |
205
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email(); |
206
|
|
|
$token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone(); |
207
|
|
|
} elseif (! $this->_request_shipping_addr) { |
208
|
|
|
// Do not request shipping details on the PP Checkout page. |
209
|
|
|
$token_request_dtls['NOSHIPPING'] = '1'; |
210
|
|
|
$token_request_dtls['REQCONFIRMSHIPPING'] = '0'; |
211
|
|
|
} |
212
|
|
|
// Used a business/personal logo on the PayPal page. |
213
|
|
|
if (! empty($this->_image_url)) { |
214
|
|
|
$token_request_dtls['LOGOIMG'] = $this->_image_url; |
215
|
|
|
} |
216
|
|
|
$token_request_dtls = apply_filters( |
217
|
|
|
'FHEE__EEG_Paypal_Express__set_redirection_info__arguments', |
218
|
|
|
$token_request_dtls, |
219
|
|
|
$this |
220
|
|
|
); |
221
|
|
|
// Request PayPal token. |
222
|
|
|
$token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment); |
223
|
|
|
$token_rstatus = $this->_ppExpress_check_response($token_request_response); |
224
|
|
|
$response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args'])) |
225
|
|
|
? $token_rstatus['args'] |
226
|
|
|
: array(); |
227
|
|
|
if ($token_rstatus['status']) { |
228
|
|
|
// We got the Token so we may continue with the payment and redirect the client. |
229
|
|
|
$payment->set_details($response_args); |
230
|
|
|
$gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com'; |
231
|
|
|
$payment->set_redirect_url( |
232
|
|
|
$gateway_url |
233
|
|
|
. '/checkoutnow?useraction=commit&cmd=_express-checkout&token=' |
234
|
|
|
. $response_args['TOKEN'] |
235
|
|
|
); |
236
|
|
View Code Duplication |
} else { |
237
|
|
|
if (isset($response_args['L_ERRORCODE'])) { |
238
|
|
|
$payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']); |
239
|
|
|
} else { |
240
|
|
|
$payment->set_gateway_response( |
241
|
|
|
esc_html__( |
242
|
|
|
'Error occurred while trying to setup the Express Checkout.', |
243
|
|
|
'event_espresso' |
244
|
|
|
) |
245
|
|
|
); |
246
|
|
|
} |
247
|
|
|
$payment->set_details($response_args); |
248
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
249
|
|
|
} |
250
|
|
|
return $payment; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
|
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* @param array $update_info { |
257
|
|
|
* @type string $gateway_txn_id |
258
|
|
|
* @type string status an EEMI_Payment status |
259
|
|
|
* } |
260
|
|
|
* @param EEI_Transaction $transaction |
261
|
|
|
* @return EEI_Payment |
262
|
|
|
*/ |
263
|
|
|
public function handle_payment_update($update_info, $transaction) |
264
|
|
|
{ |
265
|
|
|
$payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null; |
266
|
|
|
if ($payment instanceof EEI_Payment) { |
267
|
|
|
$this->log(array('Return from Authorization' => $update_info), $payment); |
268
|
|
|
$transaction = $payment->transaction(); |
269
|
|
View Code Duplication |
if (! $transaction instanceof EEI_Transaction) { |
270
|
|
|
$payment->set_gateway_response( |
271
|
|
|
esc_html__( |
272
|
|
|
'Could not process this payment because it has no associated transaction.', |
273
|
|
|
'event_espresso' |
274
|
|
|
) |
275
|
|
|
); |
276
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
277
|
|
|
return $payment; |
278
|
|
|
} |
279
|
|
|
$primary_registrant = $transaction->primary_registration(); |
280
|
|
|
$payment_details = $payment->details(); |
281
|
|
|
// Check if we still have the token. |
282
|
|
|
if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) { |
283
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
284
|
|
|
return $payment; |
285
|
|
|
} |
286
|
|
|
$cdetails_request_dtls = array( |
287
|
|
|
'METHOD' => 'GetExpressCheckoutDetails', |
288
|
|
|
'TOKEN' => $payment_details['TOKEN'], |
289
|
|
|
); |
290
|
|
|
// Request Customer Details. |
291
|
|
|
$cdetails_request_response = $this->_ppExpress_request( |
292
|
|
|
$cdetails_request_dtls, |
293
|
|
|
'Customer Details', |
294
|
|
|
$payment |
295
|
|
|
); |
296
|
|
|
$cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response); |
297
|
|
|
$cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args'])) |
298
|
|
|
? $cdetails_rstatus['args'] |
299
|
|
|
: array(); |
300
|
|
|
if ($cdetails_rstatus['status']) { |
301
|
|
|
// We got the PayerID so now we can Complete the transaction. |
302
|
|
|
$docheckout_request_dtls = array( |
303
|
|
|
'METHOD' => 'DoExpressCheckoutPayment', |
304
|
|
|
'PAYERID' => $cdata_response_args['PAYERID'], |
305
|
|
|
'TOKEN' => $payment_details['TOKEN'], |
306
|
|
|
'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', |
307
|
|
|
'PAYMENTREQUEST_0_AMT' => $payment->amount(), |
308
|
|
|
'PAYMENTREQUEST_0_CURRENCYCODE' => $payment->currency_code(), |
309
|
|
|
//EE will blow up if you change this |
310
|
|
|
'BUTTONSOURCE' => 'EventEspresso_SP', |
311
|
|
|
); |
312
|
|
|
// Include itemized list. |
313
|
|
|
$itemized_list = $this->itemize_list( |
314
|
|
|
$payment, |
315
|
|
|
$transaction, |
316
|
|
|
$cdata_response_args |
317
|
|
|
); |
318
|
|
|
$docheckout_request_dtls = array_merge($docheckout_request_dtls, $itemized_list); |
319
|
|
|
// Payment Checkout/Capture. |
320
|
|
|
$docheckout_request_response = $this->_ppExpress_request( |
321
|
|
|
$docheckout_request_dtls, |
322
|
|
|
'Do Payment', |
323
|
|
|
$payment |
324
|
|
|
); |
325
|
|
|
$docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response); |
326
|
|
|
$docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args'])) |
327
|
|
|
? $docheckout_rstatus['args'] |
328
|
|
|
: array(); |
329
|
|
|
if ($docheckout_rstatus['status']) { |
330
|
|
|
// All is well, payment approved. |
331
|
|
|
$primary_registration_code = $primary_registrant instanceof EE_Registration ? |
332
|
|
|
$primary_registrant->reg_code() |
333
|
|
|
: ''; |
334
|
|
|
$payment->set_extra_accntng($primary_registration_code); |
335
|
|
|
$payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT']) |
336
|
|
|
? (float)$docheckout_response_args['PAYMENTINFO_0_AMT'] |
337
|
|
|
: 0); |
338
|
|
|
$payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']) |
339
|
|
|
? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'] |
340
|
|
|
: null); |
341
|
|
|
$payment->set_details($cdata_response_args); |
342
|
|
|
$payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK']) |
343
|
|
|
? $docheckout_response_args['PAYMENTINFO_0_ACK'] |
344
|
|
|
: ''); |
345
|
|
|
$payment->set_status($this->_pay_model->approved_status()); |
346
|
|
View Code Duplication |
} else { |
347
|
|
|
if (isset($docheckout_response_args['L_ERRORCODE'])) { |
348
|
|
|
$payment->set_gateway_response( |
349
|
|
|
$docheckout_response_args['L_ERRORCODE'] |
350
|
|
|
. '; ' |
351
|
|
|
. $docheckout_response_args['L_SHORTMESSAGE'] |
352
|
|
|
); |
353
|
|
|
} else { |
354
|
|
|
$payment->set_gateway_response( |
355
|
|
|
esc_html__( |
356
|
|
|
'Error occurred while trying to Capture the funds.', |
357
|
|
|
'event_espresso' |
358
|
|
|
) |
359
|
|
|
); |
360
|
|
|
} |
361
|
|
|
$payment->set_details($docheckout_response_args); |
362
|
|
|
$payment->set_status($this->_pay_model->declined_status()); |
363
|
|
|
} |
364
|
|
View Code Duplication |
} else { |
365
|
|
|
if (isset($cdata_response_args['L_ERRORCODE'])) { |
366
|
|
|
$payment->set_gateway_response( |
367
|
|
|
$cdata_response_args['L_ERRORCODE'] |
368
|
|
|
. '; ' |
369
|
|
|
. $cdata_response_args['L_SHORTMESSAGE'] |
370
|
|
|
); |
371
|
|
|
} else { |
372
|
|
|
$payment->set_gateway_response( |
373
|
|
|
esc_html__( |
374
|
|
|
'Error occurred while trying to get payment Details from PayPal.', |
375
|
|
|
'event_espresso' |
376
|
|
|
) |
377
|
|
|
); |
378
|
|
|
} |
379
|
|
|
$payment->set_details($cdata_response_args); |
380
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
381
|
|
|
} |
382
|
|
|
} else { |
383
|
|
|
$payment->set_gateway_response( |
384
|
|
|
esc_html__( |
385
|
|
|
'Error occurred while trying to process the payment.', |
386
|
|
|
'event_espresso' |
387
|
|
|
) |
388
|
|
|
); |
389
|
|
|
$payment->set_status($this->_pay_model->failed_status()); |
390
|
|
|
} |
391
|
|
|
return $payment; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
|
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Make a list of items that are in the giver transaction. |
398
|
|
|
* |
399
|
|
|
* @param EEI_Payment $payment |
400
|
|
|
* @param EEI_Transaction $transaction |
401
|
|
|
* @param array $request_response_args Data from a previous communication with PP. |
402
|
|
|
* @return array |
403
|
|
|
*/ |
404
|
|
|
public function itemize_list(EEI_Payment $payment, EEI_Transaction $transaction, $request_response_args = array()) |
405
|
|
|
{ |
406
|
|
|
$itemized_list = array(); |
407
|
|
|
// If we have data from a previous communication with PP (on this transaction) we may use that for our list... |
408
|
|
|
if ( |
409
|
|
|
! empty($request_response_args) |
410
|
|
|
&& array_key_exists('L_PAYMENTREQUEST_0_AMT0', $request_response_args) |
411
|
|
|
&& array_key_exists('PAYMENTREQUEST_0_ITEMAMT', $request_response_args) |
412
|
|
|
) { |
413
|
|
|
foreach ($request_response_args as $arg_key => $arg_val) { |
414
|
|
|
if ( |
415
|
|
|
strpos($arg_key, 'PAYMENTREQUEST_') !== false |
416
|
|
|
&& strpos($arg_key, 'NOTIFYURL') === false |
417
|
|
|
) { |
418
|
|
|
$itemized_list[$arg_key] = $arg_val; |
419
|
|
|
} |
420
|
|
|
} |
421
|
|
|
// If we got only a few Items then something is not right. |
422
|
|
|
if (count($itemized_list) > 2) { |
423
|
|
|
return $itemized_list; |
424
|
|
|
} else { |
425
|
|
|
if (WP_DEBUG) { |
426
|
|
|
throw new EE_Error( |
427
|
|
|
sprintf( |
428
|
|
|
esc_html__( |
429
|
|
|
// @codingStandardsIgnoreStart |
430
|
|
|
'Unable to continue with the checkout because a proper purchase list could not be generated. The purchased list we could have sent was %1$s', |
431
|
|
|
// @codingStandardsIgnoreEnd |
432
|
|
|
'event_espresso' |
433
|
|
|
), |
434
|
|
|
wp_json_encode($itemized_list) |
435
|
|
|
) |
436
|
|
|
); |
437
|
|
|
} |
438
|
|
|
// Reset the list and log an error, maybe allow to try and generate a new list (below). |
439
|
|
|
$itemized_list = array(); |
440
|
|
|
$this->log( |
441
|
|
|
array( |
442
|
|
|
esc_html__( |
443
|
|
|
'Could not generate a proper item list with:', |
444
|
|
|
'event_espresso' |
445
|
|
|
) => $request_response_args |
446
|
|
|
), |
447
|
|
|
$payment |
448
|
|
|
); |
449
|
|
|
} |
450
|
|
|
} |
451
|
|
|
// ...otherwise we generate a new list for this transaction. |
452
|
|
|
if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) { |
453
|
|
|
$item_num = 0; |
454
|
|
|
$itemized_sum = 0; |
455
|
|
|
$total_line_items = $transaction->total_line_item(); |
456
|
|
|
// Go through each item in the list. |
457
|
|
|
foreach ($total_line_items->get_items() as $line_item) { |
458
|
|
|
if ($line_item instanceof EE_Line_Item) { |
459
|
|
|
// PayPal doesn't like line items with 0.00 amount, so we may skip those. |
460
|
|
|
if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) { |
461
|
|
|
continue; |
462
|
|
|
} |
463
|
|
|
$unit_price = $line_item->unit_price(); |
464
|
|
|
$line_item_quantity = $line_item->quantity(); |
465
|
|
|
// This is a discount. |
466
|
|
|
if ($line_item->is_percent()) { |
467
|
|
|
$unit_price = $line_item->total(); |
468
|
|
|
$line_item_quantity = 1; |
469
|
|
|
} |
470
|
|
|
// Item Name. |
471
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut( |
472
|
|
|
$this->_format_line_item_name($line_item, $payment), |
|
|
|
|
473
|
|
|
0, |
474
|
|
|
127 |
475
|
|
|
); |
476
|
|
|
// Item description. |
477
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_DESC' . $item_num] = mb_strcut( |
478
|
|
|
$this->_format_line_item_desc($line_item, $payment), |
|
|
|
|
479
|
|
|
0, |
480
|
|
|
127 |
481
|
|
|
); |
482
|
|
|
// Cost of individual item. |
483
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency($unit_price); |
|
|
|
|
484
|
|
|
// Item Number. |
485
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1; |
486
|
|
|
// Item quantity. |
487
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_QTY' . $item_num] = $line_item_quantity; |
488
|
|
|
// Digital item is sold. |
489
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical'; |
490
|
|
|
$itemized_sum += $line_item->total(); |
491
|
|
|
++$item_num; |
492
|
|
|
} |
493
|
|
|
} |
494
|
|
|
// Item's sales S/H and tax amount. |
495
|
|
|
$itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $total_line_items->get_items_total(); |
496
|
|
|
$itemized_list['PAYMENTREQUEST_0_TAXAMT'] = $total_line_items->get_total_tax(); |
497
|
|
|
$itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0'; |
498
|
|
|
$itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0'; |
499
|
|
|
$itemized_sum_diff_from_txn_total = round( |
500
|
|
|
$transaction->total() - $itemized_sum - $total_line_items->get_total_tax(), |
501
|
|
|
2 |
502
|
|
|
); |
503
|
|
|
// If we were not able to recognize some item like promotion, surcharge or cancellation, |
504
|
|
|
// add the difference as an extra line item. |
505
|
|
|
if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) { |
506
|
|
|
// Item Name. |
507
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NAME' . $item_num] = mb_strcut( |
508
|
|
|
esc_html__( |
509
|
|
|
'Other (promotion/surcharge/cancellation)', |
510
|
|
|
'event_espresso' |
511
|
|
|
), |
512
|
|
|
0, |
513
|
|
|
127 |
514
|
|
|
); |
515
|
|
|
// Item description. |
516
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_DESC' . $item_num] = ''; |
517
|
|
|
// Cost of individual item. |
518
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_AMT' . $item_num] = $this->format_currency( |
|
|
|
|
519
|
|
|
$itemized_sum_diff_from_txn_total |
520
|
|
|
); |
521
|
|
|
// Item Number. |
522
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NUMBER' . $item_num] = $item_num + 1; |
523
|
|
|
// Item quantity. |
524
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_QTY' . $item_num] = 1; |
525
|
|
|
// Digital item is sold. |
526
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num] = 'Physical'; |
527
|
|
|
$item_num++; |
528
|
|
|
} |
529
|
|
|
} else { |
530
|
|
|
// Just one Item. |
531
|
|
|
// Item Name. |
532
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NAME0'] = mb_strcut( |
533
|
|
|
$this->_format_partial_payment_line_item_name($payment), |
|
|
|
|
534
|
|
|
0, |
535
|
|
|
127 |
536
|
|
|
); |
537
|
|
|
// Item description. |
538
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_DESC0'] = mb_strcut( |
539
|
|
|
$this->_format_partial_payment_line_item_desc($payment), |
|
|
|
|
540
|
|
|
0, |
541
|
|
|
127 |
542
|
|
|
); |
543
|
|
|
// Cost of individual item. |
544
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_AMT0'] = $this->format_currency($payment->amount()); |
|
|
|
|
545
|
|
|
// Item Number. |
546
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_NUMBER0'] = 1; |
547
|
|
|
// Item quantity. |
548
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_QTY0'] = 1; |
549
|
|
|
// Digital item is sold. |
550
|
|
|
$itemized_list['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical'; |
551
|
|
|
// Item's sales S/H and tax amount. |
552
|
|
|
$itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $this->format_currency($payment->amount()); |
|
|
|
|
553
|
|
|
$itemized_list['PAYMENTREQUEST_0_TAXAMT'] = '0'; |
554
|
|
|
$itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0'; |
555
|
|
|
$itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0'; |
556
|
|
|
} |
557
|
|
|
return $itemized_list; |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
|
561
|
|
|
|
562
|
|
|
/** |
563
|
|
|
* Make the Express checkout request. |
564
|
|
|
* |
565
|
|
|
* @param array $request_params |
566
|
|
|
* @param string $request_text |
567
|
|
|
* @param EEI_Payment $payment |
568
|
|
|
* @return mixed |
569
|
|
|
*/ |
570
|
|
|
public function _ppExpress_request($request_params, $request_text, $payment) |
571
|
|
|
{ |
572
|
|
|
$request_dtls = array( |
573
|
|
|
'VERSION' => '204.0', |
574
|
|
|
'USER' => urlencode($this->_api_username), |
575
|
|
|
'PWD' => urlencode($this->_api_password), |
576
|
|
|
'SIGNATURE' => urlencode($this->_api_signature), |
577
|
|
|
); |
578
|
|
|
$dtls = array_merge($request_dtls, $request_params); |
579
|
|
|
$this->_log_clean_request($dtls, $payment, $request_text . ' Request'); |
580
|
|
|
// Request Customer Details. |
581
|
|
|
$request_response = wp_remote_post( |
582
|
|
|
$this->_base_gateway_url, |
583
|
|
|
array( |
584
|
|
|
'method' => 'POST', |
585
|
|
|
'timeout' => 45, |
586
|
|
|
'httpversion' => '1.1', |
587
|
|
|
'cookies' => array(), |
588
|
|
|
'headers' => array(), |
589
|
|
|
'body' => http_build_query($dtls), |
590
|
|
|
) |
591
|
|
|
); |
592
|
|
|
// Log the response. |
593
|
|
|
$this->log(array($request_text . ' Response' => $request_response), $payment); |
594
|
|
|
return $request_response; |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
|
598
|
|
|
|
599
|
|
|
/** |
600
|
|
|
* Check the response status. |
601
|
|
|
* |
602
|
|
|
* @param mixed $request_response |
603
|
|
|
* @return array |
604
|
|
|
*/ |
605
|
|
|
public function _ppExpress_check_response($request_response) |
606
|
|
|
{ |
607
|
|
|
if (is_wp_error($request_response) || empty($request_response['body'])) { |
608
|
|
|
// If we got here then there was an error in this request. |
609
|
|
|
return array('status' => false, 'args' => $request_response); |
610
|
|
|
} |
611
|
|
|
$response_args = array(); |
612
|
|
|
parse_str(urldecode($request_response['body']), $response_args); |
613
|
|
|
if (! isset($response_args['ACK'])) { |
614
|
|
|
return array('status' => false, 'args' => $request_response); |
615
|
|
|
} |
616
|
|
|
if ( |
617
|
|
|
( |
618
|
|
|
isset($response_args['PAYERID']) |
619
|
|
|
|| isset($response_args['TOKEN']) |
620
|
|
|
|| isset($response_args['PAYMENTINFO_0_TRANSACTIONID']) |
621
|
|
|
|| (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed') |
622
|
|
|
) |
623
|
|
|
&& in_array($response_args['ACK'], array('Success', 'SuccessWithWarning'), true) |
624
|
|
|
) { |
625
|
|
|
// Response status OK, return response parameters for further processing. |
626
|
|
|
return array('status' => true, 'args' => $response_args); |
627
|
|
|
} |
628
|
|
|
$errors = $this->_get_errors($response_args); |
629
|
|
|
return array('status' => false, 'args' => $errors); |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
|
633
|
|
|
|
634
|
|
|
/** |
635
|
|
|
* Log a "Cleared" request. |
636
|
|
|
* |
637
|
|
|
* @param array $request |
638
|
|
|
* @param EEI_Payment $payment |
639
|
|
|
* @param string $info |
640
|
|
|
* @return void |
641
|
|
|
*/ |
642
|
|
|
private function _log_clean_request($request, $payment, $info) |
643
|
|
|
{ |
644
|
|
|
$cleaned_request_data = $request; |
645
|
|
|
unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']); |
646
|
|
|
$this->log(array($info => $cleaned_request_data), $payment); |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
|
650
|
|
|
|
651
|
|
|
/** |
652
|
|
|
* Get error from the response data. |
653
|
|
|
* |
654
|
|
|
* @param array $data_array |
655
|
|
|
* @return array |
656
|
|
|
*/ |
657
|
|
|
private function _get_errors($data_array) |
658
|
|
|
{ |
659
|
|
|
$errors = array(); |
660
|
|
|
$n = 0; |
661
|
|
|
while (isset($data_array["L_ERRORCODE{$n}"])) { |
662
|
|
|
$l_error_code = isset($data_array["L_ERRORCODE{$n}"]) |
663
|
|
|
? $data_array["L_ERRORCODE{$n}"] |
664
|
|
|
: ''; |
665
|
|
|
$l_severity_code = isset($data_array["L_SEVERITYCODE{$n}"]) |
666
|
|
|
? $data_array["L_SEVERITYCODE{$n}"] |
667
|
|
|
: ''; |
668
|
|
|
$l_short_message = isset($data_array["L_SHORTMESSAGE{$n}"]) |
669
|
|
|
? $data_array["L_SHORTMESSAGE{$n}"] |
670
|
|
|
: ''; |
671
|
|
|
$l_long_message = isset($data_array["L_LONGMESSAGE{$n}"]) |
672
|
|
|
? $data_array["L_LONGMESSAGE{$n}"] |
673
|
|
|
: ''; |
674
|
|
|
if ($n === 0) { |
675
|
|
|
$errors = array( |
676
|
|
|
'L_ERRORCODE' => $l_error_code, |
677
|
|
|
'L_SHORTMESSAGE' => $l_short_message, |
678
|
|
|
'L_LONGMESSAGE' => $l_long_message, |
679
|
|
|
'L_SEVERITYCODE' => $l_severity_code, |
680
|
|
|
); |
681
|
|
|
} else { |
682
|
|
|
$errors['L_ERRORCODE'] .= ', ' . $l_error_code; |
683
|
|
|
$errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message; |
684
|
|
|
$errors['L_LONGMESSAGE'] .= ', ' . $l_long_message; |
685
|
|
|
$errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code; |
686
|
|
|
} |
687
|
|
|
$n++; |
688
|
|
|
} |
689
|
|
|
return $errors; |
690
|
|
|
} |
691
|
|
|
|
692
|
|
|
} |
693
|
|
|
// End of file EEG_Paypal_Express.gateway.php |
694
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.