Completed
Branch TASK/changelog-for-591 (52c467)
by
unknown
81:23 queued 67:59
created
caffeinated/payment_methods/Paypal_Pro/EEG_Paypal_Pro.gateway.php 1 patch
Indentation   +588 added lines, -588 removed lines patch added patch discarded remove patch
@@ -11,592 +11,592 @@
 block discarded – undo
11 11
 class EEG_Paypal_Pro extends EE_Onsite_Gateway
12 12
 {
13 13
 
14
-    /**
15
-     * @var $_paypal_api_username string
16
-     */
17
-    protected $_username = null;
18
-
19
-    /**
20
-     * @var $_password string
21
-     */
22
-    protected $_password = null;
23
-
24
-    /**
25
-     * @var $_signature string
26
-     */
27
-    protected $_signature = null;
28
-
29
-    /**
30
-     * @var $_credit_card_types array with the keys for credit card types accepted on this account
31
-     */
32
-    protected $_credit_card_types    = null;
33
-
34
-    protected $_currencies_supported = array(
35
-        'USD',
36
-        'GBP',
37
-        'CAD',
38
-        'AUD',
39
-        'BRL',
40
-        'CHF',
41
-        'CZK',
42
-        'DKK',
43
-        'EUR',
44
-        'HKD',
45
-        'HUF',
46
-        'ILS',
47
-        'JPY',
48
-        'MXN',
49
-        'MYR',
50
-        'NOK',
51
-        'NZD',
52
-        'PHP',
53
-        'PLN',
54
-        'SEK',
55
-        'SGD',
56
-        'THB',
57
-        'TRY',
58
-        'TWD',
59
-        'RUB',
60
-        'INR',
61
-    );
62
-
63
-
64
-
65
-    /**
66
-     * @param EEI_Payment $payment
67
-     * @param array       $billing_info {
68
-     * @type string $credit_card
69
-     * @type string $credit_card_type
70
-     * @type string $exp_month always 2 characters
71
-     * @type string $exp_year always 4 characters
72
-     * @type string $cvv
73
-     * }
74
-     * @see      parent::do_direct_payment for more info
75
-     * @return EE_Payment|EEI_Payment
76
-     * @throws EE_Error
77
-     */
78
-    public function do_direct_payment($payment, $billing_info = null)
79
-    {
80
-        $transaction = $payment->transaction();
81
-        if (! $transaction instanceof EEI_Transaction) {
82
-            throw new EE_Error(
83
-                esc_html__('No transaction for payment while paying with PayPal Pro.', 'event_espresso')
84
-            );
85
-        }
86
-        $primary_registrant = $transaction->primary_registration();
87
-        if (! $primary_registrant instanceof EEI_Registration) {
88
-            throw new EE_Error(
89
-                esc_html__(
90
-                    'No primary registration on transaction while paying with PayPal Pro.',
91
-                    'event_espresso'
92
-                )
93
-            );
94
-        }
95
-        $attendee = $primary_registrant->attendee();
96
-        if (! $attendee instanceof EEI_Attendee) {
97
-            throw new EE_Error(
98
-                esc_html__(
99
-                    'No attendee on primary registration while paying with PayPal Pro.',
100
-                    'event_espresso'
101
-                )
102
-            );
103
-        }
104
-        $gateway_formatter = $this->_get_gateway_formatter();
105
-        $order_description = substr($gateway_formatter->formatOrderDescription($payment), 0, 127);
106
-        // charge for the full amount. Show itemized list
107
-        if ($this->_can_easily_itemize_transaction_for($payment)) {
108
-            $item_num = 1;
109
-            $total_line_item = $transaction->total_line_item();
110
-            $order_items = array();
111
-            foreach ($total_line_item->get_items() as $line_item) {
112
-                // ignore line items with a quantity of 0
113
-                if ($line_item->quantity() == 0) {
114
-                    continue;
115
-                }
116
-                $item = array(
117
-                    // Item Name.  127 char max.
118
-                    'l_name'                 => substr(
119
-                        $gateway_formatter->formatLineItemName($line_item, $payment),
120
-                        0,
121
-                        127
122
-                    ),
123
-                    // Item description.  127 char max.
124
-                    'l_desc'                 => substr(
125
-                        $gateway_formatter->formatLineItemDesc($line_item, $payment),
126
-                        0,
127
-                        127
128
-                    ),
129
-                    // Cost of individual item.
130
-                    'l_amt'                  => $line_item->unit_price(),
131
-                    // Item Number.  127 char max.
132
-                    'l_number'               => $item_num++,
133
-                    // Item quantity.  Must be any positive integer.
134
-                    'l_qty'                  => $line_item->quantity(),
135
-                    // Item's sales tax amount.
136
-                    'l_taxamt'               => '',
137
-                    // eBay auction number of item.
138
-                    'l_ebayitemnumber'       => '',
139
-                    // eBay transaction ID of purchased item.
140
-                    'l_ebayitemauctiontxnid' => '',
141
-                    // eBay order ID for the item.
142
-                    'l_ebayitemorderid'      => '',
143
-                );
144
-                // add to array of all items
145
-                array_push($order_items, $item);
146
-            }
147
-            $item_amount = $total_line_item->get_items_total();
148
-            $tax_amount = $total_line_item->get_total_tax();
149
-        } else {
150
-            $order_items = array();
151
-            $item_amount = $payment->amount();
152
-            $tax_amount = 0;
153
-            array_push($order_items, array(
154
-                // Item Name.  127 char max.
155
-                'l_name'   => substr(
156
-                    $gateway_formatter->formatPartialPaymentLineItemName($payment),
157
-                    0,
158
-                    127
159
-                ),
160
-                // Item description.  127 char max.
161
-                'l_desc'   => substr(
162
-                    $gateway_formatter->formatPartialPaymentLineItemDesc($payment),
163
-                    0,
164
-                    127
165
-                ),
166
-                // Cost of individual item.
167
-                'l_amt'    => $payment->amount(),
168
-                // Item Number.  127 char max.
169
-                'l_number' => 1,
170
-                // Item quantity.  Must be any positive integer.
171
-                'l_qty'    => 1,
172
-            ));
173
-        }
174
-        // Populate data arrays with order data.
175
-        $DPFields = array(
176
-            // How you want to obtain payment ?
177
-            // Authorization indicates the payment is a basic auth subject to settlement with Auth & Capture.
178
-            // Sale indicates that this is a final sale for which you are requesting payment.  Default is Sale.
179
-            'paymentaction'    => 'Sale',
180
-            // Required.  IP address of the payer's browser.
181
-            'ipaddress'        => $_SERVER['REMOTE_ADDR'],
182
-            // Flag to determine whether you want the results returned by FMF.  1 or 0.  Default is 0.
183
-            'returnfmfdetails' => '1',
184
-        );
185
-        $CCDetails = array(
186
-            // Required. Type of credit card.  Visa, MasterCard, Discover, Amex, Maestro, Solo.
187
-            // If Maestro or Solo, the currency code must be GBP.
188
-            //  In addition, either start date or issue number must be specified.
189
-            'creditcardtype' => $billing_info['credit_card_type'],
190
-            // Required.  Credit card number.  No spaces or punctuation.
191
-            'acct'           => $billing_info['credit_card'],
192
-            // Required.  Credit card expiration date.  Format is MMYYYY
193
-            'expdate'        => $billing_info['exp_month'] . $billing_info['exp_year'],
194
-            // Requirements determined by your PayPal account settings.  Security digits for credit card.
195
-            'cvv2'           => $billing_info['cvv'],
196
-        );
197
-        $PayerInfo = array(
198
-            // Email address of payer.
199
-            'email'       => $billing_info['email'],
200
-            // Unique PayPal customer ID for payer.
201
-            'payerid'     => '',
202
-            // Status of payer.  Values are verified or unverified
203
-            'payerstatus' => '',
204
-            // Payer's business name.
205
-            'business'    => '',
206
-        );
207
-        $PayerName = array(
208
-            // Payer's salutation.  20 char max.
209
-            'salutation' => '',
210
-            // Payer's first name.  25 char max.
211
-            'firstname'  => substr($billing_info['first_name'], 0, 25),
212
-            // Payer's middle name.  25 char max.
213
-            'middlename' => '',
214
-            // Payer's last name.  25 char max.
215
-            'lastname'   => substr($billing_info['last_name'], 0, 25),
216
-            // Payer's suffix.  12 char max.
217
-            'suffix'     => '',
218
-        );
219
-        $BillingAddress = array(
220
-            // Required.  First street address.
221
-            'street'      => $billing_info['address'],
222
-            // Second street address.
223
-            'street2'     => $billing_info['address2'],
224
-            // Required.  Name of City.
225
-            'city'        => $billing_info['city'],
226
-            // Required. Name of State or Province.
227
-            'state'       => substr($billing_info['state'], 0, 40),
228
-            // Required.  Country code.
229
-            'countrycode' => $billing_info['country'],
230
-            // Required.  Postal code of payer.
231
-            'zip'         => $billing_info['zip'],
232
-        );
233
-        // check if the registration info contains the needed fields for paypal pro
234
-        // (see https://developer.paypal.com/docs/classic/api/merchant/DoDirectPayment_API_Operation_NVP/)
235
-        if ($attendee->address() && $attendee->city() && $attendee->country_ID()) {
236
-            $use_registration_address_info = true;
237
-        } else {
238
-            $use_registration_address_info = false;
239
-        }
240
-        // so if the attendee has enough data to fill out PayPal Pro's shipping info, use it.
241
-        // If not, use the billing info again
242
-        $ShippingAddress = array(
243
-            'shiptoname'     => substr($use_registration_address_info
244
-                ? $attendee->full_name()
245
-                : $billing_info['first_name'] . ' ' . $billing_info['last_name'], 0, 32),
246
-            'shiptostreet'   => substr($use_registration_address_info
247
-                ? $attendee->address()
248
-                : $billing_info['address'], 0, 100),
249
-            'shiptostreet2'  => substr($use_registration_address_info
250
-                ? $attendee->address2() : $billing_info['address2'], 0, 100),
251
-            'shiptocity'     => substr($use_registration_address_info
252
-                ? $attendee->city()
253
-                : $billing_info['city'], 0, 40),
254
-            'state'          => substr($use_registration_address_info
255
-                ? $attendee->state_name()
256
-                : $billing_info['state'], 0, 40),
257
-            'shiptocountry'  => $use_registration_address_info
258
-                ? $attendee->country_ID()
259
-                : $billing_info['country'],
260
-            'shiptozip'      => substr($use_registration_address_info
261
-                ? $attendee->zip()
262
-                : $billing_info['zip'], 0, 20),
263
-            'shiptophonenum' => substr($use_registration_address_info
264
-                ? $attendee->phone()
265
-                : $billing_info['phone'], 0, 20),
266
-        );
267
-        $PaymentDetails = array(
268
-            // Required.  Total amount of order, including shipping, handling, and tax.
269
-            'amt'          => $gateway_formatter->formatCurrency($payment->amount()),
270
-            // Required.  Three-letter currency code.  Default is USD.
271
-            'currencycode' => $payment->currency_code(),
272
-            // Required if you include itemized cart details. (L_AMTn, etc.)
273
-            // Subtotal of items not including S&H, or tax.
274
-            'itemamt'      => $gateway_formatter->formatCurrency($item_amount),//
275
-            // Total shipping costs for the order.  If you specify shippingamt, you must also specify itemamt.
276
-            'shippingamt'  => '',
277
-            // Total handling costs for the order.  If you specify handlingamt, you must also specify itemamt.
278
-            'handlingamt'  => '',
279
-            // Required if you specify itemized cart tax details.
280
-            // Sum of tax for all items on the order.  Total sales tax.
281
-            'taxamt'       => $gateway_formatter->formatCurrency($tax_amount),
282
-            // Description of the order the customer is purchasing.  127 char max.
283
-            'desc'         => $order_description,
284
-            // Free-form field for your own use.  256 char max.
285
-            'custom'       => $primary_registrant ? $primary_registrant->ID() : '',
286
-            // Your own invoice or tracking number
287
-            'invnum'       => wp_generate_password(12, false),// $transaction->ID(),
288
-            // URL for receiving Instant Payment Notifications.  This overrides what your profile is set to use.
289
-            'notifyurl'    => '',
290
-            'buttonsource' => 'EventEspresso_SP',// EE will blow up if you change this
291
-        );
292
-        // Wrap all data arrays into a single, "master" array which will be passed into the class function.
293
-        $PayPalRequestData = array(
294
-            'DPFields'        => $DPFields,
295
-            'CCDetails'       => $CCDetails,
296
-            'PayerInfo'       => $PayerInfo,
297
-            'PayerName'       => $PayerName,
298
-            'BillingAddress'  => $BillingAddress,
299
-            'ShippingAddress' => $ShippingAddress,
300
-            'PaymentDetails'  => $PaymentDetails,
301
-            'OrderItems'      => $order_items,
302
-        );
303
-        $this->_log_clean_request($PayPalRequestData, $payment);
304
-        try {
305
-            $PayPalResult = $this->prep_and_curl_request($PayPalRequestData);
306
-            // remove PCI-sensitive data so it doesn't get stored
307
-            $PayPalResult = $this->_log_clean_response($PayPalResult, $payment);
308
-            $message = isset($PayPalResult['L_LONGMESSAGE0']) ? $PayPalResult['L_LONGMESSAGE0'] : $PayPalResult['ACK'];
309
-            if (empty($PayPalResult['RAWRESPONSE'])) {
310
-                $payment->set_status($this->_pay_model->failed_status());
311
-                $payment->set_gateway_response(__('No response received from Paypal Pro', 'event_espresso'));
312
-                $payment->set_details($PayPalResult);
313
-            } else {
314
-                if ($this->_APICallSuccessful($PayPalResult)) {
315
-                    $payment->set_status($this->_pay_model->approved_status());
316
-                } else {
317
-                    $payment->set_status($this->_pay_model->declined_status());
318
-                }
319
-                // make sure we interpret the AMT as a float, not an international string
320
-                // (where periods are thousand separators)
321
-                $payment->set_amount(isset($PayPalResult['AMT']) ? floatval($PayPalResult['AMT']) : 0);
322
-                $payment->set_gateway_response($message);
323
-                $payment->set_txn_id_chq_nmbr(isset($PayPalResult['TRANSACTIONID'])
324
-                    ? $PayPalResult['TRANSACTIONID']
325
-                    : null);
326
-                $primary_registration_code = $primary_registrant instanceof EE_Registration
327
-                    ? $primary_registrant->reg_code()
328
-                    : '';
329
-                $payment->set_extra_accntng($primary_registration_code);
330
-                $payment->set_details($PayPalResult);
331
-            }
332
-        } catch (Exception $e) {
333
-            $payment->set_status($this->_pay_model->failed_status());
334
-            $payment->set_gateway_response($e->getMessage());
335
-        }
336
-        // $payment->set_status( $this->_pay_model->declined_status() );
337
-        // $payment->set_gateway_response( '' );
338
-        return $payment;
339
-    }
340
-
341
-
342
-
343
-    /**
344
-     * CLeans out sensitive CC data and then logs it, and returns the cleaned request
345
-     *
346
-     * @param array       $request
347
-     * @param EEI_Payment $payment
348
-     * @return void
349
-     */
350
-    private function _log_clean_request($request, $payment)
351
-    {
352
-        $cleaned_request_data = $request;
353
-        unset($cleaned_request_data['CCDetails']['acct']);
354
-        unset($cleaned_request_data['CCDetails']['cvv2']);
355
-        unset($cleaned_request_data['CCDetails']['expdate']);
356
-        $this->log(array('Paypal Request' => $cleaned_request_data), $payment);
357
-    }
358
-
359
-
360
-
361
-    /**
362
-     * Cleans the response, logs it, and returns it
363
-     *
364
-     * @param array       $response
365
-     * @param EEI_Payment $payment
366
-     * @return array cleaned
367
-     */
368
-    private function _log_clean_response($response, $payment)
369
-    {
370
-        unset($response['REQUESTDATA']['CREDITCARDTYPE']);
371
-        unset($response['REQUESTDATA']['ACCT']);
372
-        unset($response['REQUESTDATA']['EXPDATE']);
373
-        unset($response['REQUESTDATA']['CVV2']);
374
-        unset($response['RAWREQUEST']);
375
-        $this->log(array('Paypal Response' => $response), $payment);
376
-        return $response;
377
-    }
378
-
379
-
380
-
381
-    /**
382
-     * @param $DataArray
383
-     * @return array
384
-     */
385
-    private function prep_and_curl_request($DataArray)
386
-    {
387
-        // Create empty holders for each portion of the NVP string
388
-        $DPFieldsNVP = '&METHOD=DoDirectPayment&BUTTONSOURCE=AngellEYE_PHP_Class_DDP';
389
-        $CCDetailsNVP = '';
390
-        $PayerInfoNVP = '';
391
-        $PayerNameNVP = '';
392
-        $BillingAddressNVP = '';
393
-        $ShippingAddressNVP = '';
394
-        $PaymentDetailsNVP = '';
395
-        $OrderItemsNVP = '';
396
-        $Secure3DNVP = '';
397
-        // DP Fields
398
-        $DPFields = isset($DataArray['DPFields']) ? $DataArray['DPFields'] : array();
399
-        foreach ($DPFields as $DPFieldsVar => $DPFieldsVal) {
400
-            $DPFieldsNVP .= '&' . strtoupper($DPFieldsVar) . '=' . urlencode($DPFieldsVal);
401
-        }
402
-        // CC Details Fields
403
-        $CCDetails = isset($DataArray['CCDetails']) ? $DataArray['CCDetails'] : array();
404
-        foreach ($CCDetails as $CCDetailsVar => $CCDetailsVal) {
405
-            $CCDetailsNVP .= '&' . strtoupper($CCDetailsVar) . '=' . urlencode($CCDetailsVal);
406
-        }
407
-        // PayerInfo Type Fields
408
-        $PayerInfo = isset($DataArray['PayerInfo']) ? $DataArray['PayerInfo'] : array();
409
-        foreach ($PayerInfo as $PayerInfoVar => $PayerInfoVal) {
410
-            $PayerInfoNVP .= '&' . strtoupper($PayerInfoVar) . '=' . urlencode($PayerInfoVal);
411
-        }
412
-        // Payer Name Fields
413
-        $PayerName = isset($DataArray['PayerName']) ? $DataArray['PayerName'] : array();
414
-        foreach ($PayerName as $PayerNameVar => $PayerNameVal) {
415
-            $PayerNameNVP .= '&' . strtoupper($PayerNameVar) . '=' . urlencode($PayerNameVal);
416
-        }
417
-        // Address Fields (Billing)
418
-        $BillingAddress = isset($DataArray['BillingAddress']) ? $DataArray['BillingAddress'] : array();
419
-        foreach ($BillingAddress as $BillingAddressVar => $BillingAddressVal) {
420
-            $BillingAddressNVP .= '&' . strtoupper($BillingAddressVar) . '=' . urlencode($BillingAddressVal);
421
-        }
422
-        // Payment Details Type Fields
423
-        $PaymentDetails = isset($DataArray['PaymentDetails']) ? $DataArray['PaymentDetails'] : array();
424
-        foreach ($PaymentDetails as $PaymentDetailsVar => $PaymentDetailsVal) {
425
-            $PaymentDetailsNVP .= '&' . strtoupper($PaymentDetailsVar) . '=' . urlencode($PaymentDetailsVal);
426
-        }
427
-        // Payment Details Item Type Fields
428
-        $OrderItems = isset($DataArray['OrderItems']) ? $DataArray['OrderItems'] : array();
429
-        $n = 0;
430
-        foreach ($OrderItems as $OrderItemsVar => $OrderItemsVal) {
431
-            $CurrentItem = $OrderItems[ $OrderItemsVar ];
432
-            foreach ($CurrentItem as $CurrentItemVar => $CurrentItemVal) {
433
-                $OrderItemsNVP .= '&' . strtoupper($CurrentItemVar) . $n . '=' . urlencode($CurrentItemVal);
434
-            }
435
-            $n++;
436
-        }
437
-        // Ship To Address Fields
438
-        $ShippingAddress = isset($DataArray['ShippingAddress']) ? $DataArray['ShippingAddress'] : array();
439
-        foreach ($ShippingAddress as $ShippingAddressVar => $ShippingAddressVal) {
440
-            $ShippingAddressNVP .= '&' . strtoupper($ShippingAddressVar) . '=' . urlencode($ShippingAddressVal);
441
-        }
442
-        // 3D Secure Fields
443
-        $Secure3D = isset($DataArray['Secure3D']) ? $DataArray['Secure3D'] : array();
444
-        foreach ($Secure3D as $Secure3DVar => $Secure3DVal) {
445
-            $Secure3DNVP .= '&' . strtoupper($Secure3DVar) . '=' . urlencode($Secure3DVal);
446
-        }
447
-        // Now that we have each chunk we need to go ahead and append them all together for our entire NVP string
448
-        $NVPRequest = 'USER='
449
-                      . $this->_username
450
-                      . '&PWD='
451
-                      . $this->_password
452
-                      . '&VERSION=64.0'
453
-                      . '&SIGNATURE='
454
-                      . $this->_signature
455
-                      . $DPFieldsNVP
456
-                      . $CCDetailsNVP
457
-                      . $PayerInfoNVP
458
-                      . $PayerNameNVP
459
-                      . $BillingAddressNVP
460
-                      . $PaymentDetailsNVP
461
-                      . $OrderItemsNVP
462
-                      . $ShippingAddressNVP
463
-                      . $Secure3DNVP;
464
-        $NVPResponse = $this->_CURLRequest($NVPRequest);
465
-        $NVPRequestArray = $this->_NVPToArray($NVPRequest);
466
-        $NVPResponseArray = $this->_NVPToArray($NVPResponse);
467
-        $Errors = $this->_GetErrors($NVPResponseArray);
468
-        $NVPResponseArray['ERRORS'] = $Errors;
469
-        $NVPResponseArray['REQUESTDATA'] = $NVPRequestArray;
470
-        $NVPResponseArray['RAWREQUEST'] = $NVPRequest;
471
-        $NVPResponseArray['RAWRESPONSE'] = $NVPResponse;
472
-        return $NVPResponseArray;
473
-    }
474
-
475
-
476
-
477
-    /**
478
-     * @param $Request
479
-     * @return mixed
480
-     */
481
-    private function _CURLRequest($Request)
482
-    {
483
-        $EndPointURL = $this->_debug_mode ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp';
484
-        $curl = curl_init();
485
-        curl_setopt($curl, CURLOPT_VERBOSE, apply_filters('FHEE__EEG_Paypal_Pro__CurlRequest__CURLOPT_VERBOSE', true));
486
-        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
487
-        curl_setopt($curl, CURLOPT_TIMEOUT, 60);
488
-        curl_setopt($curl, CURLOPT_URL, $EndPointURL);
489
-        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
490
-        curl_setopt($curl, CURLOPT_POSTFIELDS, $Request);
491
-        curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
492
-        // execute the curl POST
493
-        $Response = curl_exec($curl);
494
-        curl_close($curl);
495
-        return $Response;
496
-    }
497
-
498
-
499
-
500
-    /**
501
-     * @param $NVPString
502
-     * @return array
503
-     */
504
-    private function _NVPToArray($NVPString)
505
-    {
506
-        // prepare responses into array
507
-        $proArray = array();
508
-        while (strlen($NVPString)) {
509
-            // name
510
-            $keypos = strpos($NVPString, '=');
511
-            $keyval = substr($NVPString, 0, $keypos);
512
-            // value
513
-            $valuepos = strpos($NVPString, '&') ? strpos($NVPString, '&') : strlen($NVPString);
514
-            $valval = substr($NVPString, $keypos + 1, $valuepos - $keypos - 1);
515
-            // decoding the response
516
-            $proArray[ $keyval ] = urldecode($valval);
517
-            $NVPString = substr($NVPString, $valuepos + 1, strlen($NVPString));
518
-        }
519
-        return $proArray;
520
-    }
521
-
522
-
523
-
524
-    /**
525
-     * @param array $PayPalResult
526
-     * @return bool
527
-     */
528
-    private function _APICallSuccessful($PayPalResult)
529
-    {
530
-        $approved = false;
531
-        // check main response message from PayPal
532
-        if (isset($PayPalResult['ACK']) && ! empty($PayPalResult['ACK'])) {
533
-            $ack = strtoupper($PayPalResult['ACK']);
534
-            $approved = ($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING' || $ack == 'PARTIALSUCCESS') ? true : false;
535
-        }
536
-        return $approved;
537
-    }
538
-
539
-
540
-
541
-    /**
542
-     * @param $DataArray
543
-     * @return array
544
-     */
545
-    private function _GetErrors($DataArray)
546
-    {
547
-        $Errors = array();
548
-        $n = 0;
549
-        while (isset($DataArray[ 'L_ERRORCODE' . $n . '' ])) {
550
-            $LErrorCode = isset($DataArray[ 'L_ERRORCODE' . $n . '' ]) ? $DataArray[ 'L_ERRORCODE' . $n . '' ] : '';
551
-            $LShortMessage = isset($DataArray[ 'L_SHORTMESSAGE' . $n . '' ])
552
-                ? $DataArray[ 'L_SHORTMESSAGE' . $n . '' ]
553
-                : '';
554
-            $LLongMessage = isset($DataArray[ 'L_LONGMESSAGE' . $n . '' ])
555
-                ? $DataArray[ 'L_LONGMESSAGE' . $n . '' ]
556
-                : '';
557
-            $LSeverityCode = isset($DataArray[ 'L_SEVERITYCODE' . $n . '' ])
558
-                ? $DataArray[ 'L_SEVERITYCODE' . $n . '' ]
559
-                : '';
560
-            $CurrentItem = array(
561
-                'L_ERRORCODE'    => $LErrorCode,
562
-                'L_SHORTMESSAGE' => $LShortMessage,
563
-                'L_LONGMESSAGE'  => $LLongMessage,
564
-                'L_SEVERITYCODE' => $LSeverityCode,
565
-            );
566
-            array_push($Errors, $CurrentItem);
567
-            $n++;
568
-        }
569
-        return $Errors;
570
-    }
571
-
572
-
573
-
574
-    /**
575
-     *        nothing to see here...  move along....
576
-     *
577
-     * @access protected
578
-     * @param $Errors
579
-     * @return string
580
-     */
581
-    private function _DisplayErrors($Errors)
582
-    {
583
-        $error = '';
584
-        foreach ($Errors as $ErrorVar => $ErrorVal) {
585
-            $CurrentError = $Errors[ $ErrorVar ];
586
-            foreach ($CurrentError as $CurrentErrorVar => $CurrentErrorVal) {
587
-                $CurrentVarName = '';
588
-                if ($CurrentErrorVar == 'L_ERRORCODE') {
589
-                    $CurrentVarName = 'Error Code';
590
-                } elseif ($CurrentErrorVar == 'L_SHORTMESSAGE') {
591
-                    $CurrentVarName = 'Short Message';
592
-                } elseif ($CurrentErrorVar == 'L_LONGMESSAGE') {
593
-                    $CurrentVarName = 'Long Message';
594
-                } elseif ($CurrentErrorVar == 'L_SEVERITYCODE') {
595
-                    $CurrentVarName = 'Severity Code';
596
-                }
597
-                $error .= '<br />' . $CurrentVarName . ': ' . $CurrentErrorVal;
598
-            }
599
-        }
600
-        return $error;
601
-    }
14
+	/**
15
+	 * @var $_paypal_api_username string
16
+	 */
17
+	protected $_username = null;
18
+
19
+	/**
20
+	 * @var $_password string
21
+	 */
22
+	protected $_password = null;
23
+
24
+	/**
25
+	 * @var $_signature string
26
+	 */
27
+	protected $_signature = null;
28
+
29
+	/**
30
+	 * @var $_credit_card_types array with the keys for credit card types accepted on this account
31
+	 */
32
+	protected $_credit_card_types    = null;
33
+
34
+	protected $_currencies_supported = array(
35
+		'USD',
36
+		'GBP',
37
+		'CAD',
38
+		'AUD',
39
+		'BRL',
40
+		'CHF',
41
+		'CZK',
42
+		'DKK',
43
+		'EUR',
44
+		'HKD',
45
+		'HUF',
46
+		'ILS',
47
+		'JPY',
48
+		'MXN',
49
+		'MYR',
50
+		'NOK',
51
+		'NZD',
52
+		'PHP',
53
+		'PLN',
54
+		'SEK',
55
+		'SGD',
56
+		'THB',
57
+		'TRY',
58
+		'TWD',
59
+		'RUB',
60
+		'INR',
61
+	);
62
+
63
+
64
+
65
+	/**
66
+	 * @param EEI_Payment $payment
67
+	 * @param array       $billing_info {
68
+	 * @type string $credit_card
69
+	 * @type string $credit_card_type
70
+	 * @type string $exp_month always 2 characters
71
+	 * @type string $exp_year always 4 characters
72
+	 * @type string $cvv
73
+	 * }
74
+	 * @see      parent::do_direct_payment for more info
75
+	 * @return EE_Payment|EEI_Payment
76
+	 * @throws EE_Error
77
+	 */
78
+	public function do_direct_payment($payment, $billing_info = null)
79
+	{
80
+		$transaction = $payment->transaction();
81
+		if (! $transaction instanceof EEI_Transaction) {
82
+			throw new EE_Error(
83
+				esc_html__('No transaction for payment while paying with PayPal Pro.', 'event_espresso')
84
+			);
85
+		}
86
+		$primary_registrant = $transaction->primary_registration();
87
+		if (! $primary_registrant instanceof EEI_Registration) {
88
+			throw new EE_Error(
89
+				esc_html__(
90
+					'No primary registration on transaction while paying with PayPal Pro.',
91
+					'event_espresso'
92
+				)
93
+			);
94
+		}
95
+		$attendee = $primary_registrant->attendee();
96
+		if (! $attendee instanceof EEI_Attendee) {
97
+			throw new EE_Error(
98
+				esc_html__(
99
+					'No attendee on primary registration while paying with PayPal Pro.',
100
+					'event_espresso'
101
+				)
102
+			);
103
+		}
104
+		$gateway_formatter = $this->_get_gateway_formatter();
105
+		$order_description = substr($gateway_formatter->formatOrderDescription($payment), 0, 127);
106
+		// charge for the full amount. Show itemized list
107
+		if ($this->_can_easily_itemize_transaction_for($payment)) {
108
+			$item_num = 1;
109
+			$total_line_item = $transaction->total_line_item();
110
+			$order_items = array();
111
+			foreach ($total_line_item->get_items() as $line_item) {
112
+				// ignore line items with a quantity of 0
113
+				if ($line_item->quantity() == 0) {
114
+					continue;
115
+				}
116
+				$item = array(
117
+					// Item Name.  127 char max.
118
+					'l_name'                 => substr(
119
+						$gateway_formatter->formatLineItemName($line_item, $payment),
120
+						0,
121
+						127
122
+					),
123
+					// Item description.  127 char max.
124
+					'l_desc'                 => substr(
125
+						$gateway_formatter->formatLineItemDesc($line_item, $payment),
126
+						0,
127
+						127
128
+					),
129
+					// Cost of individual item.
130
+					'l_amt'                  => $line_item->unit_price(),
131
+					// Item Number.  127 char max.
132
+					'l_number'               => $item_num++,
133
+					// Item quantity.  Must be any positive integer.
134
+					'l_qty'                  => $line_item->quantity(),
135
+					// Item's sales tax amount.
136
+					'l_taxamt'               => '',
137
+					// eBay auction number of item.
138
+					'l_ebayitemnumber'       => '',
139
+					// eBay transaction ID of purchased item.
140
+					'l_ebayitemauctiontxnid' => '',
141
+					// eBay order ID for the item.
142
+					'l_ebayitemorderid'      => '',
143
+				);
144
+				// add to array of all items
145
+				array_push($order_items, $item);
146
+			}
147
+			$item_amount = $total_line_item->get_items_total();
148
+			$tax_amount = $total_line_item->get_total_tax();
149
+		} else {
150
+			$order_items = array();
151
+			$item_amount = $payment->amount();
152
+			$tax_amount = 0;
153
+			array_push($order_items, array(
154
+				// Item Name.  127 char max.
155
+				'l_name'   => substr(
156
+					$gateway_formatter->formatPartialPaymentLineItemName($payment),
157
+					0,
158
+					127
159
+				),
160
+				// Item description.  127 char max.
161
+				'l_desc'   => substr(
162
+					$gateway_formatter->formatPartialPaymentLineItemDesc($payment),
163
+					0,
164
+					127
165
+				),
166
+				// Cost of individual item.
167
+				'l_amt'    => $payment->amount(),
168
+				// Item Number.  127 char max.
169
+				'l_number' => 1,
170
+				// Item quantity.  Must be any positive integer.
171
+				'l_qty'    => 1,
172
+			));
173
+		}
174
+		// Populate data arrays with order data.
175
+		$DPFields = array(
176
+			// How you want to obtain payment ?
177
+			// Authorization indicates the payment is a basic auth subject to settlement with Auth & Capture.
178
+			// Sale indicates that this is a final sale for which you are requesting payment.  Default is Sale.
179
+			'paymentaction'    => 'Sale',
180
+			// Required.  IP address of the payer's browser.
181
+			'ipaddress'        => $_SERVER['REMOTE_ADDR'],
182
+			// Flag to determine whether you want the results returned by FMF.  1 or 0.  Default is 0.
183
+			'returnfmfdetails' => '1',
184
+		);
185
+		$CCDetails = array(
186
+			// Required. Type of credit card.  Visa, MasterCard, Discover, Amex, Maestro, Solo.
187
+			// If Maestro or Solo, the currency code must be GBP.
188
+			//  In addition, either start date or issue number must be specified.
189
+			'creditcardtype' => $billing_info['credit_card_type'],
190
+			// Required.  Credit card number.  No spaces or punctuation.
191
+			'acct'           => $billing_info['credit_card'],
192
+			// Required.  Credit card expiration date.  Format is MMYYYY
193
+			'expdate'        => $billing_info['exp_month'] . $billing_info['exp_year'],
194
+			// Requirements determined by your PayPal account settings.  Security digits for credit card.
195
+			'cvv2'           => $billing_info['cvv'],
196
+		);
197
+		$PayerInfo = array(
198
+			// Email address of payer.
199
+			'email'       => $billing_info['email'],
200
+			// Unique PayPal customer ID for payer.
201
+			'payerid'     => '',
202
+			// Status of payer.  Values are verified or unverified
203
+			'payerstatus' => '',
204
+			// Payer's business name.
205
+			'business'    => '',
206
+		);
207
+		$PayerName = array(
208
+			// Payer's salutation.  20 char max.
209
+			'salutation' => '',
210
+			// Payer's first name.  25 char max.
211
+			'firstname'  => substr($billing_info['first_name'], 0, 25),
212
+			// Payer's middle name.  25 char max.
213
+			'middlename' => '',
214
+			// Payer's last name.  25 char max.
215
+			'lastname'   => substr($billing_info['last_name'], 0, 25),
216
+			// Payer's suffix.  12 char max.
217
+			'suffix'     => '',
218
+		);
219
+		$BillingAddress = array(
220
+			// Required.  First street address.
221
+			'street'      => $billing_info['address'],
222
+			// Second street address.
223
+			'street2'     => $billing_info['address2'],
224
+			// Required.  Name of City.
225
+			'city'        => $billing_info['city'],
226
+			// Required. Name of State or Province.
227
+			'state'       => substr($billing_info['state'], 0, 40),
228
+			// Required.  Country code.
229
+			'countrycode' => $billing_info['country'],
230
+			// Required.  Postal code of payer.
231
+			'zip'         => $billing_info['zip'],
232
+		);
233
+		// check if the registration info contains the needed fields for paypal pro
234
+		// (see https://developer.paypal.com/docs/classic/api/merchant/DoDirectPayment_API_Operation_NVP/)
235
+		if ($attendee->address() && $attendee->city() && $attendee->country_ID()) {
236
+			$use_registration_address_info = true;
237
+		} else {
238
+			$use_registration_address_info = false;
239
+		}
240
+		// so if the attendee has enough data to fill out PayPal Pro's shipping info, use it.
241
+		// If not, use the billing info again
242
+		$ShippingAddress = array(
243
+			'shiptoname'     => substr($use_registration_address_info
244
+				? $attendee->full_name()
245
+				: $billing_info['first_name'] . ' ' . $billing_info['last_name'], 0, 32),
246
+			'shiptostreet'   => substr($use_registration_address_info
247
+				? $attendee->address()
248
+				: $billing_info['address'], 0, 100),
249
+			'shiptostreet2'  => substr($use_registration_address_info
250
+				? $attendee->address2() : $billing_info['address2'], 0, 100),
251
+			'shiptocity'     => substr($use_registration_address_info
252
+				? $attendee->city()
253
+				: $billing_info['city'], 0, 40),
254
+			'state'          => substr($use_registration_address_info
255
+				? $attendee->state_name()
256
+				: $billing_info['state'], 0, 40),
257
+			'shiptocountry'  => $use_registration_address_info
258
+				? $attendee->country_ID()
259
+				: $billing_info['country'],
260
+			'shiptozip'      => substr($use_registration_address_info
261
+				? $attendee->zip()
262
+				: $billing_info['zip'], 0, 20),
263
+			'shiptophonenum' => substr($use_registration_address_info
264
+				? $attendee->phone()
265
+				: $billing_info['phone'], 0, 20),
266
+		);
267
+		$PaymentDetails = array(
268
+			// Required.  Total amount of order, including shipping, handling, and tax.
269
+			'amt'          => $gateway_formatter->formatCurrency($payment->amount()),
270
+			// Required.  Three-letter currency code.  Default is USD.
271
+			'currencycode' => $payment->currency_code(),
272
+			// Required if you include itemized cart details. (L_AMTn, etc.)
273
+			// Subtotal of items not including S&H, or tax.
274
+			'itemamt'      => $gateway_formatter->formatCurrency($item_amount),//
275
+			// Total shipping costs for the order.  If you specify shippingamt, you must also specify itemamt.
276
+			'shippingamt'  => '',
277
+			// Total handling costs for the order.  If you specify handlingamt, you must also specify itemamt.
278
+			'handlingamt'  => '',
279
+			// Required if you specify itemized cart tax details.
280
+			// Sum of tax for all items on the order.  Total sales tax.
281
+			'taxamt'       => $gateway_formatter->formatCurrency($tax_amount),
282
+			// Description of the order the customer is purchasing.  127 char max.
283
+			'desc'         => $order_description,
284
+			// Free-form field for your own use.  256 char max.
285
+			'custom'       => $primary_registrant ? $primary_registrant->ID() : '',
286
+			// Your own invoice or tracking number
287
+			'invnum'       => wp_generate_password(12, false),// $transaction->ID(),
288
+			// URL for receiving Instant Payment Notifications.  This overrides what your profile is set to use.
289
+			'notifyurl'    => '',
290
+			'buttonsource' => 'EventEspresso_SP',// EE will blow up if you change this
291
+		);
292
+		// Wrap all data arrays into a single, "master" array which will be passed into the class function.
293
+		$PayPalRequestData = array(
294
+			'DPFields'        => $DPFields,
295
+			'CCDetails'       => $CCDetails,
296
+			'PayerInfo'       => $PayerInfo,
297
+			'PayerName'       => $PayerName,
298
+			'BillingAddress'  => $BillingAddress,
299
+			'ShippingAddress' => $ShippingAddress,
300
+			'PaymentDetails'  => $PaymentDetails,
301
+			'OrderItems'      => $order_items,
302
+		);
303
+		$this->_log_clean_request($PayPalRequestData, $payment);
304
+		try {
305
+			$PayPalResult = $this->prep_and_curl_request($PayPalRequestData);
306
+			// remove PCI-sensitive data so it doesn't get stored
307
+			$PayPalResult = $this->_log_clean_response($PayPalResult, $payment);
308
+			$message = isset($PayPalResult['L_LONGMESSAGE0']) ? $PayPalResult['L_LONGMESSAGE0'] : $PayPalResult['ACK'];
309
+			if (empty($PayPalResult['RAWRESPONSE'])) {
310
+				$payment->set_status($this->_pay_model->failed_status());
311
+				$payment->set_gateway_response(__('No response received from Paypal Pro', 'event_espresso'));
312
+				$payment->set_details($PayPalResult);
313
+			} else {
314
+				if ($this->_APICallSuccessful($PayPalResult)) {
315
+					$payment->set_status($this->_pay_model->approved_status());
316
+				} else {
317
+					$payment->set_status($this->_pay_model->declined_status());
318
+				}
319
+				// make sure we interpret the AMT as a float, not an international string
320
+				// (where periods are thousand separators)
321
+				$payment->set_amount(isset($PayPalResult['AMT']) ? floatval($PayPalResult['AMT']) : 0);
322
+				$payment->set_gateway_response($message);
323
+				$payment->set_txn_id_chq_nmbr(isset($PayPalResult['TRANSACTIONID'])
324
+					? $PayPalResult['TRANSACTIONID']
325
+					: null);
326
+				$primary_registration_code = $primary_registrant instanceof EE_Registration
327
+					? $primary_registrant->reg_code()
328
+					: '';
329
+				$payment->set_extra_accntng($primary_registration_code);
330
+				$payment->set_details($PayPalResult);
331
+			}
332
+		} catch (Exception $e) {
333
+			$payment->set_status($this->_pay_model->failed_status());
334
+			$payment->set_gateway_response($e->getMessage());
335
+		}
336
+		// $payment->set_status( $this->_pay_model->declined_status() );
337
+		// $payment->set_gateway_response( '' );
338
+		return $payment;
339
+	}
340
+
341
+
342
+
343
+	/**
344
+	 * CLeans out sensitive CC data and then logs it, and returns the cleaned request
345
+	 *
346
+	 * @param array       $request
347
+	 * @param EEI_Payment $payment
348
+	 * @return void
349
+	 */
350
+	private function _log_clean_request($request, $payment)
351
+	{
352
+		$cleaned_request_data = $request;
353
+		unset($cleaned_request_data['CCDetails']['acct']);
354
+		unset($cleaned_request_data['CCDetails']['cvv2']);
355
+		unset($cleaned_request_data['CCDetails']['expdate']);
356
+		$this->log(array('Paypal Request' => $cleaned_request_data), $payment);
357
+	}
358
+
359
+
360
+
361
+	/**
362
+	 * Cleans the response, logs it, and returns it
363
+	 *
364
+	 * @param array       $response
365
+	 * @param EEI_Payment $payment
366
+	 * @return array cleaned
367
+	 */
368
+	private function _log_clean_response($response, $payment)
369
+	{
370
+		unset($response['REQUESTDATA']['CREDITCARDTYPE']);
371
+		unset($response['REQUESTDATA']['ACCT']);
372
+		unset($response['REQUESTDATA']['EXPDATE']);
373
+		unset($response['REQUESTDATA']['CVV2']);
374
+		unset($response['RAWREQUEST']);
375
+		$this->log(array('Paypal Response' => $response), $payment);
376
+		return $response;
377
+	}
378
+
379
+
380
+
381
+	/**
382
+	 * @param $DataArray
383
+	 * @return array
384
+	 */
385
+	private function prep_and_curl_request($DataArray)
386
+	{
387
+		// Create empty holders for each portion of the NVP string
388
+		$DPFieldsNVP = '&METHOD=DoDirectPayment&BUTTONSOURCE=AngellEYE_PHP_Class_DDP';
389
+		$CCDetailsNVP = '';
390
+		$PayerInfoNVP = '';
391
+		$PayerNameNVP = '';
392
+		$BillingAddressNVP = '';
393
+		$ShippingAddressNVP = '';
394
+		$PaymentDetailsNVP = '';
395
+		$OrderItemsNVP = '';
396
+		$Secure3DNVP = '';
397
+		// DP Fields
398
+		$DPFields = isset($DataArray['DPFields']) ? $DataArray['DPFields'] : array();
399
+		foreach ($DPFields as $DPFieldsVar => $DPFieldsVal) {
400
+			$DPFieldsNVP .= '&' . strtoupper($DPFieldsVar) . '=' . urlencode($DPFieldsVal);
401
+		}
402
+		// CC Details Fields
403
+		$CCDetails = isset($DataArray['CCDetails']) ? $DataArray['CCDetails'] : array();
404
+		foreach ($CCDetails as $CCDetailsVar => $CCDetailsVal) {
405
+			$CCDetailsNVP .= '&' . strtoupper($CCDetailsVar) . '=' . urlencode($CCDetailsVal);
406
+		}
407
+		// PayerInfo Type Fields
408
+		$PayerInfo = isset($DataArray['PayerInfo']) ? $DataArray['PayerInfo'] : array();
409
+		foreach ($PayerInfo as $PayerInfoVar => $PayerInfoVal) {
410
+			$PayerInfoNVP .= '&' . strtoupper($PayerInfoVar) . '=' . urlencode($PayerInfoVal);
411
+		}
412
+		// Payer Name Fields
413
+		$PayerName = isset($DataArray['PayerName']) ? $DataArray['PayerName'] : array();
414
+		foreach ($PayerName as $PayerNameVar => $PayerNameVal) {
415
+			$PayerNameNVP .= '&' . strtoupper($PayerNameVar) . '=' . urlencode($PayerNameVal);
416
+		}
417
+		// Address Fields (Billing)
418
+		$BillingAddress = isset($DataArray['BillingAddress']) ? $DataArray['BillingAddress'] : array();
419
+		foreach ($BillingAddress as $BillingAddressVar => $BillingAddressVal) {
420
+			$BillingAddressNVP .= '&' . strtoupper($BillingAddressVar) . '=' . urlencode($BillingAddressVal);
421
+		}
422
+		// Payment Details Type Fields
423
+		$PaymentDetails = isset($DataArray['PaymentDetails']) ? $DataArray['PaymentDetails'] : array();
424
+		foreach ($PaymentDetails as $PaymentDetailsVar => $PaymentDetailsVal) {
425
+			$PaymentDetailsNVP .= '&' . strtoupper($PaymentDetailsVar) . '=' . urlencode($PaymentDetailsVal);
426
+		}
427
+		// Payment Details Item Type Fields
428
+		$OrderItems = isset($DataArray['OrderItems']) ? $DataArray['OrderItems'] : array();
429
+		$n = 0;
430
+		foreach ($OrderItems as $OrderItemsVar => $OrderItemsVal) {
431
+			$CurrentItem = $OrderItems[ $OrderItemsVar ];
432
+			foreach ($CurrentItem as $CurrentItemVar => $CurrentItemVal) {
433
+				$OrderItemsNVP .= '&' . strtoupper($CurrentItemVar) . $n . '=' . urlencode($CurrentItemVal);
434
+			}
435
+			$n++;
436
+		}
437
+		// Ship To Address Fields
438
+		$ShippingAddress = isset($DataArray['ShippingAddress']) ? $DataArray['ShippingAddress'] : array();
439
+		foreach ($ShippingAddress as $ShippingAddressVar => $ShippingAddressVal) {
440
+			$ShippingAddressNVP .= '&' . strtoupper($ShippingAddressVar) . '=' . urlencode($ShippingAddressVal);
441
+		}
442
+		// 3D Secure Fields
443
+		$Secure3D = isset($DataArray['Secure3D']) ? $DataArray['Secure3D'] : array();
444
+		foreach ($Secure3D as $Secure3DVar => $Secure3DVal) {
445
+			$Secure3DNVP .= '&' . strtoupper($Secure3DVar) . '=' . urlencode($Secure3DVal);
446
+		}
447
+		// Now that we have each chunk we need to go ahead and append them all together for our entire NVP string
448
+		$NVPRequest = 'USER='
449
+					  . $this->_username
450
+					  . '&PWD='
451
+					  . $this->_password
452
+					  . '&VERSION=64.0'
453
+					  . '&SIGNATURE='
454
+					  . $this->_signature
455
+					  . $DPFieldsNVP
456
+					  . $CCDetailsNVP
457
+					  . $PayerInfoNVP
458
+					  . $PayerNameNVP
459
+					  . $BillingAddressNVP
460
+					  . $PaymentDetailsNVP
461
+					  . $OrderItemsNVP
462
+					  . $ShippingAddressNVP
463
+					  . $Secure3DNVP;
464
+		$NVPResponse = $this->_CURLRequest($NVPRequest);
465
+		$NVPRequestArray = $this->_NVPToArray($NVPRequest);
466
+		$NVPResponseArray = $this->_NVPToArray($NVPResponse);
467
+		$Errors = $this->_GetErrors($NVPResponseArray);
468
+		$NVPResponseArray['ERRORS'] = $Errors;
469
+		$NVPResponseArray['REQUESTDATA'] = $NVPRequestArray;
470
+		$NVPResponseArray['RAWREQUEST'] = $NVPRequest;
471
+		$NVPResponseArray['RAWRESPONSE'] = $NVPResponse;
472
+		return $NVPResponseArray;
473
+	}
474
+
475
+
476
+
477
+	/**
478
+	 * @param $Request
479
+	 * @return mixed
480
+	 */
481
+	private function _CURLRequest($Request)
482
+	{
483
+		$EndPointURL = $this->_debug_mode ? 'https://api-3t.sandbox.paypal.com/nvp' : 'https://api-3t.paypal.com/nvp';
484
+		$curl = curl_init();
485
+		curl_setopt($curl, CURLOPT_VERBOSE, apply_filters('FHEE__EEG_Paypal_Pro__CurlRequest__CURLOPT_VERBOSE', true));
486
+		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
487
+		curl_setopt($curl, CURLOPT_TIMEOUT, 60);
488
+		curl_setopt($curl, CURLOPT_URL, $EndPointURL);
489
+		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
490
+		curl_setopt($curl, CURLOPT_POSTFIELDS, $Request);
491
+		curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
492
+		// execute the curl POST
493
+		$Response = curl_exec($curl);
494
+		curl_close($curl);
495
+		return $Response;
496
+	}
497
+
498
+
499
+
500
+	/**
501
+	 * @param $NVPString
502
+	 * @return array
503
+	 */
504
+	private function _NVPToArray($NVPString)
505
+	{
506
+		// prepare responses into array
507
+		$proArray = array();
508
+		while (strlen($NVPString)) {
509
+			// name
510
+			$keypos = strpos($NVPString, '=');
511
+			$keyval = substr($NVPString, 0, $keypos);
512
+			// value
513
+			$valuepos = strpos($NVPString, '&') ? strpos($NVPString, '&') : strlen($NVPString);
514
+			$valval = substr($NVPString, $keypos + 1, $valuepos - $keypos - 1);
515
+			// decoding the response
516
+			$proArray[ $keyval ] = urldecode($valval);
517
+			$NVPString = substr($NVPString, $valuepos + 1, strlen($NVPString));
518
+		}
519
+		return $proArray;
520
+	}
521
+
522
+
523
+
524
+	/**
525
+	 * @param array $PayPalResult
526
+	 * @return bool
527
+	 */
528
+	private function _APICallSuccessful($PayPalResult)
529
+	{
530
+		$approved = false;
531
+		// check main response message from PayPal
532
+		if (isset($PayPalResult['ACK']) && ! empty($PayPalResult['ACK'])) {
533
+			$ack = strtoupper($PayPalResult['ACK']);
534
+			$approved = ($ack == 'SUCCESS' || $ack == 'SUCCESSWITHWARNING' || $ack == 'PARTIALSUCCESS') ? true : false;
535
+		}
536
+		return $approved;
537
+	}
538
+
539
+
540
+
541
+	/**
542
+	 * @param $DataArray
543
+	 * @return array
544
+	 */
545
+	private function _GetErrors($DataArray)
546
+	{
547
+		$Errors = array();
548
+		$n = 0;
549
+		while (isset($DataArray[ 'L_ERRORCODE' . $n . '' ])) {
550
+			$LErrorCode = isset($DataArray[ 'L_ERRORCODE' . $n . '' ]) ? $DataArray[ 'L_ERRORCODE' . $n . '' ] : '';
551
+			$LShortMessage = isset($DataArray[ 'L_SHORTMESSAGE' . $n . '' ])
552
+				? $DataArray[ 'L_SHORTMESSAGE' . $n . '' ]
553
+				: '';
554
+			$LLongMessage = isset($DataArray[ 'L_LONGMESSAGE' . $n . '' ])
555
+				? $DataArray[ 'L_LONGMESSAGE' . $n . '' ]
556
+				: '';
557
+			$LSeverityCode = isset($DataArray[ 'L_SEVERITYCODE' . $n . '' ])
558
+				? $DataArray[ 'L_SEVERITYCODE' . $n . '' ]
559
+				: '';
560
+			$CurrentItem = array(
561
+				'L_ERRORCODE'    => $LErrorCode,
562
+				'L_SHORTMESSAGE' => $LShortMessage,
563
+				'L_LONGMESSAGE'  => $LLongMessage,
564
+				'L_SEVERITYCODE' => $LSeverityCode,
565
+			);
566
+			array_push($Errors, $CurrentItem);
567
+			$n++;
568
+		}
569
+		return $Errors;
570
+	}
571
+
572
+
573
+
574
+	/**
575
+	 *        nothing to see here...  move along....
576
+	 *
577
+	 * @access protected
578
+	 * @param $Errors
579
+	 * @return string
580
+	 */
581
+	private function _DisplayErrors($Errors)
582
+	{
583
+		$error = '';
584
+		foreach ($Errors as $ErrorVar => $ErrorVal) {
585
+			$CurrentError = $Errors[ $ErrorVar ];
586
+			foreach ($CurrentError as $CurrentErrorVar => $CurrentErrorVal) {
587
+				$CurrentVarName = '';
588
+				if ($CurrentErrorVar == 'L_ERRORCODE') {
589
+					$CurrentVarName = 'Error Code';
590
+				} elseif ($CurrentErrorVar == 'L_SHORTMESSAGE') {
591
+					$CurrentVarName = 'Short Message';
592
+				} elseif ($CurrentErrorVar == 'L_LONGMESSAGE') {
593
+					$CurrentVarName = 'Long Message';
594
+				} elseif ($CurrentErrorVar == 'L_SEVERITYCODE') {
595
+					$CurrentVarName = 'Severity Code';
596
+				}
597
+				$error .= '<br />' . $CurrentVarName . ': ' . $CurrentErrorVal;
598
+			}
599
+		}
600
+		return $error;
601
+	}
602 602
 }
Please login to merge, or discard this patch.
payment_methods/Paypal_Express/EEG_Paypal_Express.gateway.php 1 patch
Indentation   +668 added lines, -668 removed lines patch added patch discarded remove patch
@@ -11,676 +11,676 @@
 block discarded – undo
11 11
  */
12 12
 // Quickfix to address https://events.codebasehq.com/projects/event-espresso/tickets/11089 ASAP
13 13
 if (! function_exists('mb_strcut')) {
14
-    /**
15
-     * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
16
-     * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
17
-     * @param $string
18
-     * @param $start
19
-     * @param $length
20
-     * @return bool|string
21
-     */
22
-    function mb_strcut($string, $start, $length = null)
23
-    {
24
-        return mb_substr($string, $start, $length);
25
-    }
14
+	/**
15
+	 * Very simple mimic of mb_substr (which WP ensures exists in wp-includes/compat.php). Still has all the problems of mb_substr
16
+	 * (namely, that we might send too many characters to PayPal; however in this case they just issue a warning but nothing breaks)
17
+	 * @param $string
18
+	 * @param $start
19
+	 * @param $length
20
+	 * @return bool|string
21
+	 */
22
+	function mb_strcut($string, $start, $length = null)
23
+	{
24
+		return mb_substr($string, $start, $length);
25
+	}
26 26
 }
27 27
 class EEG_Paypal_Express extends EE_Offsite_Gateway
28 28
 {
29 29
 
30
-    /**
31
-     * Merchant API Username.
32
-     *
33
-     * @var string
34
-     */
35
-    protected $_api_username;
36
-
37
-    /**
38
-     * Merchant API Password.
39
-     *
40
-     * @var string
41
-     */
42
-    protected $_api_password;
43
-
44
-    /**
45
-     * API Signature.
46
-     *
47
-     * @var string
48
-     */
49
-    protected $_api_signature;
50
-
51
-    /**
52
-     * Request Shipping address on PP checkout page.
53
-     *
54
-     * @var string
55
-     */
56
-    protected $_request_shipping_addr;
57
-
58
-    /**
59
-     * Business/personal logo.
60
-     *
61
-     * @var string
62
-     */
63
-    protected $_image_url;
64
-
65
-    /**
66
-     * gateway URL variable
67
-     *
68
-     * @var string
69
-     */
70
-    protected $_base_gateway_url = '';
71
-
72
-
73
-
74
-    /**
75
-     * EEG_Paypal_Express constructor.
76
-     */
77
-    public function __construct()
78
-    {
79
-        $this->_currencies_supported = array(
80
-            'USD',
81
-            'AUD',
82
-            'BRL',
83
-            'CAD',
84
-            'CZK',
85
-            'DKK',
86
-            'EUR',
87
-            'HKD',
88
-            'HUF',
89
-            'ILS',
90
-            'JPY',
91
-            'MYR',
92
-            'MXN',
93
-            'NOK',
94
-            'NZD',
95
-            'PHP',
96
-            'PLN',
97
-            'GBP',
98
-            'RUB',
99
-            'SGD',
100
-            'SEK',
101
-            'CHF',
102
-            'TWD',
103
-            'THB',
104
-            'TRY',
105
-            'INR',
106
-        );
107
-        parent::__construct();
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * Sets the gateway URL variable based on whether debug mode is enabled or not.
114
-     *
115
-     * @param array $settings_array
116
-     */
117
-    public function set_settings($settings_array)
118
-    {
119
-        parent::set_settings($settings_array);
120
-        // Redirect URL.
121
-        $this->_base_gateway_url = $this->_debug_mode
122
-            ? 'https://api-3t.sandbox.paypal.com/nvp'
123
-            : 'https://api-3t.paypal.com/nvp';
124
-    }
125
-
126
-
127
-
128
-    /**
129
-     * @param EEI_Payment $payment
130
-     * @param array       $billing_info
131
-     * @param string      $return_url
132
-     * @param string      $notify_url
133
-     * @param string      $cancel_url
134
-     * @return \EE_Payment|\EEI_Payment
135
-     * @throws \EE_Error
136
-     */
137
-    public function set_redirection_info(
138
-        $payment,
139
-        $billing_info = array(),
140
-        $return_url = null,
141
-        $notify_url = null,
142
-        $cancel_url = null
143
-    ) {
144
-        if (! $payment instanceof EEI_Payment) {
145
-            $payment->set_gateway_response(
146
-                esc_html__(
147
-                    'Error. No associated payment was found.',
148
-                    'event_espresso'
149
-                )
150
-            );
151
-            $payment->set_status($this->_pay_model->failed_status());
152
-            return $payment;
153
-        }
154
-        $transaction = $payment->transaction();
155
-        if (! $transaction instanceof EEI_Transaction) {
156
-            $payment->set_gateway_response(
157
-                esc_html__(
158
-                    'Could not process this payment because it has no associated transaction.',
159
-                    'event_espresso'
160
-                )
161
-            );
162
-            $payment->set_status($this->_pay_model->failed_status());
163
-            return $payment;
164
-        }
165
-        $gateway_formatter = $this->_get_gateway_formatter();
166
-        $order_description = mb_strcut($gateway_formatter->formatOrderDescription($payment), 0, 127);
167
-        $primary_registration = $transaction->primary_registration();
168
-        $primary_attendee = $primary_registration instanceof EE_Registration
169
-            ? $primary_registration->attendee()
170
-            : false;
171
-        $locale = explode('-', get_bloginfo('language'));
172
-        // Gather request parameters.
173
-        $token_request_dtls = array(
174
-            'METHOD'                         => 'SetExpressCheckout',
175
-            'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
176
-            'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
177
-            'PAYMENTREQUEST_0_DESC'          => $order_description,
178
-            'RETURNURL'                      => $return_url,
179
-            'CANCELURL'                      => $cancel_url,
180
-            'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
181
-            // Buyer does not need to create a PayPal account to check out.
182
-            // This is referred to as PayPal Account Optional.
183
-            'SOLUTIONTYPE'                   => 'Sole',
184
-            // EE will blow up if you change this
185
-            'BUTTONSOURCE'                   => 'EventEspresso_SP',
186
-            // Locale of the pages displayed by PayPal during Express Checkout.
187
-            'LOCALECODE'                     => $locale[1]
188
-        );
189
-        // Show itemized list.
190
-        $itemized_list = $this->itemize_list($payment, $transaction);
191
-        $token_request_dtls = array_merge($token_request_dtls, $itemized_list);
192
-        // Automatically filling out shipping and contact information.
193
-        if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
194
-            // If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
195
-            $token_request_dtls['NOSHIPPING'] = '2';
196
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
197
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
198
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
199
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTATE'] = $primary_attendee->state_abbrev();
200
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $primary_attendee->country_ID();
201
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
202
-            $token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
203
-            $token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
204
-        } elseif (! $this->_request_shipping_addr) {
205
-            // Do not request shipping details on the PP Checkout page.
206
-            $token_request_dtls['NOSHIPPING'] = '1';
207
-            $token_request_dtls['REQCONFIRMSHIPPING'] = '0';
208
-        }
209
-        // Used a business/personal logo on the PayPal page.
210
-        if (! empty($this->_image_url)) {
211
-            $token_request_dtls['LOGOIMG'] = $this->_image_url;
212
-        }
213
-        $token_request_dtls = apply_filters(
214
-            'FHEE__EEG_Paypal_Express__set_redirection_info__arguments',
215
-            $token_request_dtls,
216
-            $this
217
-        );
218
-        // Request PayPal token.
219
-        $token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
220
-        $token_rstatus = $this->_ppExpress_check_response($token_request_response);
221
-        $response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args']))
222
-            ? $token_rstatus['args']
223
-            : array();
224
-        if ($token_rstatus['status']) {
225
-            // We got the Token so we may continue with the payment and redirect the client.
226
-            $payment->set_details($response_args);
227
-            $gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
228
-            $payment->set_redirect_url(
229
-                $gateway_url
230
-                . '/checkoutnow?useraction=commit&cmd=_express-checkout&token='
231
-                . $response_args['TOKEN']
232
-            );
233
-        } else {
234
-            if (isset($response_args['L_ERRORCODE'])) {
235
-                $payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']);
236
-            } else {
237
-                $payment->set_gateway_response(
238
-                    esc_html__(
239
-                        'Error occurred while trying to setup the Express Checkout.',
240
-                        'event_espresso'
241
-                    )
242
-                );
243
-            }
244
-            $payment->set_details($response_args);
245
-            $payment->set_status($this->_pay_model->failed_status());
246
-        }
247
-        return $payment;
248
-    }
249
-
250
-
251
-
252
-    /**
253
-     * @param array           $update_info {
254
-     * @type string           $gateway_txn_id
255
-     * @type string status an EEMI_Payment status
256
-     *                                     }
257
-     * @param EEI_Transaction $transaction
258
-     * @return EEI_Payment
259
-     */
260
-    public function handle_payment_update($update_info, $transaction)
261
-    {
262
-        $payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null;
263
-        if ($payment instanceof EEI_Payment) {
264
-            $this->log(array('Return from Authorization' => $update_info), $payment);
265
-            $transaction = $payment->transaction();
266
-            if (! $transaction instanceof EEI_Transaction) {
267
-                $payment->set_gateway_response(
268
-                    esc_html__(
269
-                        'Could not process this payment because it has no associated transaction.',
270
-                        'event_espresso'
271
-                    )
272
-                );
273
-                $payment->set_status($this->_pay_model->failed_status());
274
-                return $payment;
275
-            }
276
-            $primary_registrant = $transaction->primary_registration();
277
-            $payment_details = $payment->details();
278
-            // Check if we still have the token.
279
-            if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
280
-                $payment->set_status($this->_pay_model->failed_status());
281
-                return $payment;
282
-            }
283
-            $cdetails_request_dtls = array(
284
-                'METHOD' => 'GetExpressCheckoutDetails',
285
-                'TOKEN'  => $payment_details['TOKEN'],
286
-            );
287
-            // Request Customer Details.
288
-            $cdetails_request_response = $this->_ppExpress_request(
289
-                $cdetails_request_dtls,
290
-                'Customer Details',
291
-                $payment
292
-            );
293
-            $cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
294
-            $cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']))
295
-                ? $cdetails_rstatus['args']
296
-                : array();
297
-            if ($cdetails_rstatus['status']) {
298
-                // We got the PayerID so now we can Complete the transaction.
299
-                $docheckout_request_dtls = array(
300
-                    'METHOD'                         => 'DoExpressCheckoutPayment',
301
-                    'PAYERID'                        => $cdata_response_args['PAYERID'],
302
-                    'TOKEN'                          => $payment_details['TOKEN'],
303
-                    'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
304
-                    'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
305
-                    'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
306
-                    // EE will blow up if you change this
307
-                    'BUTTONSOURCE'                   => 'EventEspresso_SP',
308
-                );
309
-                 // Include itemized list.
310
-                $itemized_list = $this->itemize_list(
311
-                    $payment,
312
-                    $transaction,
313
-                    $cdata_response_args
314
-                );
315
-                $docheckout_request_dtls = array_merge($docheckout_request_dtls, $itemized_list);
316
-                // Payment Checkout/Capture.
317
-                $docheckout_request_response = $this->_ppExpress_request(
318
-                    $docheckout_request_dtls,
319
-                    'Do Payment',
320
-                    $payment
321
-                );
322
-                $docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
323
-                $docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']))
324
-                    ? $docheckout_rstatus['args']
325
-                    : array();
326
-                if ($docheckout_rstatus['status']) {
327
-                    // All is well, payment approved.
328
-                    $primary_registration_code = $primary_registrant instanceof EE_Registration ?
329
-                        $primary_registrant->reg_code()
330
-                        : '';
331
-                    $payment->set_extra_accntng($primary_registration_code);
332
-                    $payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT'])
333
-                        ? (float) $docheckout_response_args['PAYMENTINFO_0_AMT']
334
-                        : 0);
335
-                    $payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'])
336
-                        ? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']
337
-                        : null);
338
-                    $payment->set_details($cdata_response_args);
339
-                    $payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK'])
340
-                        ? $docheckout_response_args['PAYMENTINFO_0_ACK']
341
-                        : '');
342
-                    $payment->set_status($this->_pay_model->approved_status());
343
-                } else {
344
-                    if (isset($docheckout_response_args['L_ERRORCODE'])) {
345
-                        $payment->set_gateway_response(
346
-                            $docheckout_response_args['L_ERRORCODE']
347
-                            . '; '
348
-                            . $docheckout_response_args['L_SHORTMESSAGE']
349
-                        );
350
-                    } else {
351
-                        $payment->set_gateway_response(
352
-                            esc_html__(
353
-                                'Error occurred while trying to Capture the funds.',
354
-                                'event_espresso'
355
-                            )
356
-                        );
357
-                    }
358
-                    $payment->set_details($docheckout_response_args);
359
-                    $payment->set_status($this->_pay_model->declined_status());
360
-                }
361
-            } else {
362
-                if (isset($cdata_response_args['L_ERRORCODE'])) {
363
-                    $payment->set_gateway_response(
364
-                        $cdata_response_args['L_ERRORCODE']
365
-                        . '; '
366
-                        . $cdata_response_args['L_SHORTMESSAGE']
367
-                    );
368
-                } else {
369
-                    $payment->set_gateway_response(
370
-                        esc_html__(
371
-                            'Error occurred while trying to get payment Details from PayPal.',
372
-                            'event_espresso'
373
-                        )
374
-                    );
375
-                }
376
-                $payment->set_details($cdata_response_args);
377
-                $payment->set_status($this->_pay_model->failed_status());
378
-            }
379
-        } else {
380
-            $payment->set_gateway_response(
381
-                esc_html__(
382
-                    'Error occurred while trying to process the payment.',
383
-                    'event_espresso'
384
-                )
385
-            );
386
-            $payment->set_status($this->_pay_model->failed_status());
387
-        }
388
-        return $payment;
389
-    }
390
-
391
-
392
-
393
-    /**
394
-     *  Make a list of items that are in the giver transaction.
395
-     *
396
-     * @param EEI_Payment     $payment
397
-     * @param EEI_Transaction $transaction
398
-     * @param array           $request_response_args Data from a previous communication with PP.
399
-     * @return array
400
-     */
401
-    public function itemize_list(EEI_Payment $payment, EEI_Transaction $transaction, $request_response_args = array())
402
-    {
403
-        $itemized_list = array();
404
-        $gateway_formatter = $this->_get_gateway_formatter();
405
-        // If we have data from a previous communication with PP (on this transaction) we may use that for our list...
406
-        if (! empty($request_response_args)
407
-            && array_key_exists('L_PAYMENTREQUEST_0_AMT0', $request_response_args)
408
-            && array_key_exists('PAYMENTREQUEST_0_ITEMAMT', $request_response_args)
409
-        ) {
410
-            foreach ($request_response_args as $arg_key => $arg_val) {
411
-                if (strpos($arg_key, 'PAYMENTREQUEST_') !== false
412
-                    && strpos($arg_key, 'NOTIFYURL') === false
413
-                ) {
414
-                    $itemized_list[ $arg_key ] = $arg_val;
415
-                }
416
-            }
417
-            // If we got only a few Items then something is not right.
418
-            if (count($itemized_list) > 2) {
419
-                return $itemized_list;
420
-            } else {
421
-                if (WP_DEBUG) {
422
-                    throw new EE_Error(
423
-                        sprintf(
424
-                            esc_html__(
425
-                                // @codingStandardsIgnoreStart
426
-                                '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',
427
-                                // @codingStandardsIgnoreEnd
428
-                                'event_espresso'
429
-                            ),
430
-                            wp_json_encode($itemized_list)
431
-                        )
432
-                    );
433
-                }
434
-                // Reset the list and log an error, maybe allow to try and generate a new list (below).
435
-                $itemized_list = array();
436
-                $this->log(
437
-                    array(
438
-                        esc_html__(
439
-                            'Could not generate a proper item list with:',
440
-                            'event_espresso'
441
-                        ) => $request_response_args
442
-                    ),
443
-                    $payment
444
-                );
445
-            }
446
-        }
447
-        // ...otherwise we generate a new list for this transaction.
448
-        if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) {
449
-            $item_num = 0;
450
-            $itemized_sum = 0;
451
-            $total_line_items = $transaction->total_line_item();
452
-            // Go through each item in the list.
453
-            foreach ($total_line_items->get_items() as $line_item) {
454
-                if ($line_item instanceof EE_Line_Item) {
455
-                    // PayPal doesn't like line items with 0.00 amount, so we may skip those.
456
-                    if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
457
-                        continue;
458
-                    }
459
-                    $unit_price = $line_item->unit_price();
460
-                    $line_item_quantity = $line_item->quantity();
461
-                    // This is a discount.
462
-                    if ($line_item->is_percent()) {
463
-                        $unit_price = $line_item->total();
464
-                        $line_item_quantity = 1;
465
-                    }
466
-                    // Item Name.
467
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_NAME' . $item_num ] = mb_strcut(
468
-                        $gateway_formatter->formatLineItemName($line_item, $payment),
469
-                        0,
470
-                        127
471
-                    );
472
-                    // Item description.
473
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_DESC' . $item_num ] = mb_strcut(
474
-                        $gateway_formatter->formatLineItemDesc($line_item, $payment),
475
-                        0,
476
-                        127
477
-                    );
478
-                    // Cost of individual item.
479
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_AMT' . $item_num ] = $gateway_formatter->formatCurrency($unit_price);
480
-                    // Item Number.
481
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_NUMBER' . $item_num ] = $item_num + 1;
482
-                    // Item quantity.
483
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_QTY' . $item_num ] = $line_item_quantity;
484
-                    // Digital item is sold.
485
-                    $itemized_list[ 'L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num ] = 'Physical';
486
-                    $itemized_sum += $line_item->total();
487
-                    ++$item_num;
488
-                }
489
-            }
490
-            // Item's sales S/H and tax amount.
491
-            $itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $total_line_items->get_items_total();
492
-            $itemized_list['PAYMENTREQUEST_0_TAXAMT'] = $total_line_items->get_total_tax();
493
-            $itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
494
-            $itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
495
-            $itemized_sum_diff_from_txn_total = round(
496
-                $transaction->total() - $itemized_sum - $total_line_items->get_total_tax(),
497
-                2
498
-            );
499
-            // If we were not able to recognize some item like promotion, surcharge or cancellation,
500
-            // add the difference as an extra line item.
501
-            if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
502
-                // Item Name.
503
-                $itemized_list[ 'L_PAYMENTREQUEST_0_NAME' . $item_num ] = mb_strcut(
504
-                    esc_html__(
505
-                        'Other (promotion/surcharge/cancellation)',
506
-                        'event_espresso'
507
-                    ),
508
-                    0,
509
-                    127
510
-                );
511
-                // Item description.
512
-                $itemized_list[ 'L_PAYMENTREQUEST_0_DESC' . $item_num ] = '';
513
-                // Cost of individual item.
514
-                $itemized_list[ 'L_PAYMENTREQUEST_0_AMT' . $item_num ] = $gateway_formatter->formatCurrency(
515
-                    $itemized_sum_diff_from_txn_total
516
-                );
517
-                // Item Number.
518
-                $itemized_list[ 'L_PAYMENTREQUEST_0_NUMBER' . $item_num ] = $item_num + 1;
519
-                // Item quantity.
520
-                $itemized_list[ 'L_PAYMENTREQUEST_0_QTY' . $item_num ] = 1;
521
-                // Digital item is sold.
522
-                $itemized_list[ 'L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num ] = 'Physical';
523
-                $item_num++;
524
-            }
525
-        } else {
526
-            // Just one Item.
527
-            // Item Name.
528
-            $itemized_list['L_PAYMENTREQUEST_0_NAME0'] = mb_strcut(
529
-                $gateway_formatter->formatPartialPaymentLineItemName($payment),
530
-                0,
531
-                127
532
-            );
533
-            // Item description.
534
-            $itemized_list['L_PAYMENTREQUEST_0_DESC0'] = mb_strcut(
535
-                $gateway_formatter->formatPartialPaymentLineItemDesc($payment),
536
-                0,
537
-                127
538
-            );
539
-            // Cost of individual item.
540
-            $itemized_list['L_PAYMENTREQUEST_0_AMT0'] = $gateway_formatter->formatCurrency($payment->amount());
541
-            // Item Number.
542
-            $itemized_list['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
543
-            // Item quantity.
544
-            $itemized_list['L_PAYMENTREQUEST_0_QTY0'] = 1;
545
-            // Digital item is sold.
546
-            $itemized_list['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
547
-            // Item's sales S/H and tax amount.
548
-            $itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $gateway_formatter->formatCurrency($payment->amount());
549
-            $itemized_list['PAYMENTREQUEST_0_TAXAMT'] = '0';
550
-            $itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
551
-            $itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
552
-        }
553
-        return $itemized_list;
554
-    }
555
-
556
-
557
-
558
-    /**
559
-     *  Make the Express checkout request.
560
-     *
561
-     * @param array       $request_params
562
-     * @param string      $request_text
563
-     * @param EEI_Payment $payment
564
-     * @return mixed
565
-     */
566
-    public function _ppExpress_request($request_params, $request_text, $payment)
567
-    {
568
-        $request_dtls = array(
569
-            'VERSION'   => '204.0',
570
-            'USER'      => urlencode($this->_api_username),
571
-            'PWD'       => urlencode($this->_api_password),
572
-            'SIGNATURE' => urlencode($this->_api_signature),
573
-        );
574
-        $dtls = array_merge($request_dtls, $request_params);
575
-        $this->_log_clean_request($dtls, $payment, $request_text . ' Request');
576
-        // Request Customer Details.
577
-        $request_response = wp_remote_post(
578
-            $this->_base_gateway_url,
579
-            array(
580
-                'method'      => 'POST',
581
-                'timeout'     => 45,
582
-                'httpversion' => '1.1',
583
-                'cookies'     => array(),
584
-                'headers'     => array(),
585
-                'body'        => http_build_query($dtls, '', '&'),
586
-            )
587
-        );
588
-        // Log the response.
589
-        $this->log(array($request_text . ' Response' => $request_response), $payment);
590
-        return $request_response;
591
-    }
592
-
593
-
594
-
595
-    /**
596
-     *  Check the response status.
597
-     *
598
-     * @param mixed $request_response
599
-     * @return array
600
-     */
601
-    public function _ppExpress_check_response($request_response)
602
-    {
603
-        if (is_wp_error($request_response) || empty($request_response['body'])) {
604
-            // If we got here then there was an error in this request.
605
-            return array('status' => false, 'args' => $request_response);
606
-        }
607
-        $response_args = array();
608
-        parse_str(urldecode($request_response['body']), $response_args);
609
-        if (! isset($response_args['ACK'])) {
610
-            return array('status' => false, 'args' => $request_response);
611
-        }
612
-        if ((
613
-                isset($response_args['PAYERID'])
614
-                || isset($response_args['TOKEN'])
615
-                || isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
616
-                || (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
617
-            )
618
-            && in_array($response_args['ACK'], array('Success', 'SuccessWithWarning'), true)
619
-        ) {
620
-            // Response status OK, return response parameters for further processing.
621
-            return array('status' => true, 'args' => $response_args);
622
-        }
623
-        $errors = $this->_get_errors($response_args);
624
-        return array('status' => false, 'args' => $errors);
625
-    }
626
-
627
-
628
-
629
-    /**
630
-     *  Log a "Cleared" request.
631
-     *
632
-     * @param array       $request
633
-     * @param EEI_Payment $payment
634
-     * @param string      $info
635
-     * @return void
636
-     */
637
-    private function _log_clean_request($request, $payment, $info)
638
-    {
639
-        $cleaned_request_data = $request;
640
-        unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']);
641
-        $this->log(array($info => $cleaned_request_data), $payment);
642
-    }
643
-
644
-
645
-
646
-    /**
647
-     *  Get error from the response data.
648
-     *
649
-     * @param array $data_array
650
-     * @return array
651
-     */
652
-    private function _get_errors($data_array)
653
-    {
654
-        $errors = array();
655
-        $n = 0;
656
-        while (isset($data_array[ "L_ERRORCODE{$n}" ])) {
657
-            $l_error_code = isset($data_array[ "L_ERRORCODE{$n}" ])
658
-                ? $data_array[ "L_ERRORCODE{$n}" ]
659
-                : '';
660
-            $l_severity_code = isset($data_array[ "L_SEVERITYCODE{$n}" ])
661
-                ? $data_array[ "L_SEVERITYCODE{$n}" ]
662
-                : '';
663
-            $l_short_message = isset($data_array[ "L_SHORTMESSAGE{$n}" ])
664
-                ? $data_array[ "L_SHORTMESSAGE{$n}" ]
665
-                : '';
666
-            $l_long_message = isset($data_array[ "L_LONGMESSAGE{$n}" ])
667
-                ? $data_array[ "L_LONGMESSAGE{$n}" ]
668
-                : '';
669
-            if ($n === 0) {
670
-                $errors = array(
671
-                    'L_ERRORCODE'    => $l_error_code,
672
-                    'L_SHORTMESSAGE' => $l_short_message,
673
-                    'L_LONGMESSAGE'  => $l_long_message,
674
-                    'L_SEVERITYCODE' => $l_severity_code,
675
-                );
676
-            } else {
677
-                $errors['L_ERRORCODE'] .= ', ' . $l_error_code;
678
-                $errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
679
-                $errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
680
-                $errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
681
-            }
682
-            $n++;
683
-        }
684
-        return $errors;
685
-    }
30
+	/**
31
+	 * Merchant API Username.
32
+	 *
33
+	 * @var string
34
+	 */
35
+	protected $_api_username;
36
+
37
+	/**
38
+	 * Merchant API Password.
39
+	 *
40
+	 * @var string
41
+	 */
42
+	protected $_api_password;
43
+
44
+	/**
45
+	 * API Signature.
46
+	 *
47
+	 * @var string
48
+	 */
49
+	protected $_api_signature;
50
+
51
+	/**
52
+	 * Request Shipping address on PP checkout page.
53
+	 *
54
+	 * @var string
55
+	 */
56
+	protected $_request_shipping_addr;
57
+
58
+	/**
59
+	 * Business/personal logo.
60
+	 *
61
+	 * @var string
62
+	 */
63
+	protected $_image_url;
64
+
65
+	/**
66
+	 * gateway URL variable
67
+	 *
68
+	 * @var string
69
+	 */
70
+	protected $_base_gateway_url = '';
71
+
72
+
73
+
74
+	/**
75
+	 * EEG_Paypal_Express constructor.
76
+	 */
77
+	public function __construct()
78
+	{
79
+		$this->_currencies_supported = array(
80
+			'USD',
81
+			'AUD',
82
+			'BRL',
83
+			'CAD',
84
+			'CZK',
85
+			'DKK',
86
+			'EUR',
87
+			'HKD',
88
+			'HUF',
89
+			'ILS',
90
+			'JPY',
91
+			'MYR',
92
+			'MXN',
93
+			'NOK',
94
+			'NZD',
95
+			'PHP',
96
+			'PLN',
97
+			'GBP',
98
+			'RUB',
99
+			'SGD',
100
+			'SEK',
101
+			'CHF',
102
+			'TWD',
103
+			'THB',
104
+			'TRY',
105
+			'INR',
106
+		);
107
+		parent::__construct();
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * Sets the gateway URL variable based on whether debug mode is enabled or not.
114
+	 *
115
+	 * @param array $settings_array
116
+	 */
117
+	public function set_settings($settings_array)
118
+	{
119
+		parent::set_settings($settings_array);
120
+		// Redirect URL.
121
+		$this->_base_gateway_url = $this->_debug_mode
122
+			? 'https://api-3t.sandbox.paypal.com/nvp'
123
+			: 'https://api-3t.paypal.com/nvp';
124
+	}
125
+
126
+
127
+
128
+	/**
129
+	 * @param EEI_Payment $payment
130
+	 * @param array       $billing_info
131
+	 * @param string      $return_url
132
+	 * @param string      $notify_url
133
+	 * @param string      $cancel_url
134
+	 * @return \EE_Payment|\EEI_Payment
135
+	 * @throws \EE_Error
136
+	 */
137
+	public function set_redirection_info(
138
+		$payment,
139
+		$billing_info = array(),
140
+		$return_url = null,
141
+		$notify_url = null,
142
+		$cancel_url = null
143
+	) {
144
+		if (! $payment instanceof EEI_Payment) {
145
+			$payment->set_gateway_response(
146
+				esc_html__(
147
+					'Error. No associated payment was found.',
148
+					'event_espresso'
149
+				)
150
+			);
151
+			$payment->set_status($this->_pay_model->failed_status());
152
+			return $payment;
153
+		}
154
+		$transaction = $payment->transaction();
155
+		if (! $transaction instanceof EEI_Transaction) {
156
+			$payment->set_gateway_response(
157
+				esc_html__(
158
+					'Could not process this payment because it has no associated transaction.',
159
+					'event_espresso'
160
+				)
161
+			);
162
+			$payment->set_status($this->_pay_model->failed_status());
163
+			return $payment;
164
+		}
165
+		$gateway_formatter = $this->_get_gateway_formatter();
166
+		$order_description = mb_strcut($gateway_formatter->formatOrderDescription($payment), 0, 127);
167
+		$primary_registration = $transaction->primary_registration();
168
+		$primary_attendee = $primary_registration instanceof EE_Registration
169
+			? $primary_registration->attendee()
170
+			: false;
171
+		$locale = explode('-', get_bloginfo('language'));
172
+		// Gather request parameters.
173
+		$token_request_dtls = array(
174
+			'METHOD'                         => 'SetExpressCheckout',
175
+			'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
176
+			'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
177
+			'PAYMENTREQUEST_0_DESC'          => $order_description,
178
+			'RETURNURL'                      => $return_url,
179
+			'CANCELURL'                      => $cancel_url,
180
+			'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
181
+			// Buyer does not need to create a PayPal account to check out.
182
+			// This is referred to as PayPal Account Optional.
183
+			'SOLUTIONTYPE'                   => 'Sole',
184
+			// EE will blow up if you change this
185
+			'BUTTONSOURCE'                   => 'EventEspresso_SP',
186
+			// Locale of the pages displayed by PayPal during Express Checkout.
187
+			'LOCALECODE'                     => $locale[1]
188
+		);
189
+		// Show itemized list.
190
+		$itemized_list = $this->itemize_list($payment, $transaction);
191
+		$token_request_dtls = array_merge($token_request_dtls, $itemized_list);
192
+		// Automatically filling out shipping and contact information.
193
+		if ($this->_request_shipping_addr && $primary_attendee instanceof EEI_Attendee) {
194
+			// If you do not pass the shipping address, PayPal obtains it from the buyer's account profile.
195
+			$token_request_dtls['NOSHIPPING'] = '2';
196
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET'] = $primary_attendee->address();
197
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTREET2'] = $primary_attendee->address2();
198
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCITY'] = $primary_attendee->city();
199
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOSTATE'] = $primary_attendee->state_abbrev();
200
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE'] = $primary_attendee->country_ID();
201
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOZIP'] = $primary_attendee->zip();
202
+			$token_request_dtls['PAYMENTREQUEST_0_EMAIL'] = $primary_attendee->email();
203
+			$token_request_dtls['PAYMENTREQUEST_0_SHIPTOPHONENUM'] = $primary_attendee->phone();
204
+		} elseif (! $this->_request_shipping_addr) {
205
+			// Do not request shipping details on the PP Checkout page.
206
+			$token_request_dtls['NOSHIPPING'] = '1';
207
+			$token_request_dtls['REQCONFIRMSHIPPING'] = '0';
208
+		}
209
+		// Used a business/personal logo on the PayPal page.
210
+		if (! empty($this->_image_url)) {
211
+			$token_request_dtls['LOGOIMG'] = $this->_image_url;
212
+		}
213
+		$token_request_dtls = apply_filters(
214
+			'FHEE__EEG_Paypal_Express__set_redirection_info__arguments',
215
+			$token_request_dtls,
216
+			$this
217
+		);
218
+		// Request PayPal token.
219
+		$token_request_response = $this->_ppExpress_request($token_request_dtls, 'Payment Token', $payment);
220
+		$token_rstatus = $this->_ppExpress_check_response($token_request_response);
221
+		$response_args = (isset($token_rstatus['args']) && is_array($token_rstatus['args']))
222
+			? $token_rstatus['args']
223
+			: array();
224
+		if ($token_rstatus['status']) {
225
+			// We got the Token so we may continue with the payment and redirect the client.
226
+			$payment->set_details($response_args);
227
+			$gateway_url = $this->_debug_mode ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
228
+			$payment->set_redirect_url(
229
+				$gateway_url
230
+				. '/checkoutnow?useraction=commit&cmd=_express-checkout&token='
231
+				. $response_args['TOKEN']
232
+			);
233
+		} else {
234
+			if (isset($response_args['L_ERRORCODE'])) {
235
+				$payment->set_gateway_response($response_args['L_ERRORCODE'] . '; ' . $response_args['L_SHORTMESSAGE']);
236
+			} else {
237
+				$payment->set_gateway_response(
238
+					esc_html__(
239
+						'Error occurred while trying to setup the Express Checkout.',
240
+						'event_espresso'
241
+					)
242
+				);
243
+			}
244
+			$payment->set_details($response_args);
245
+			$payment->set_status($this->_pay_model->failed_status());
246
+		}
247
+		return $payment;
248
+	}
249
+
250
+
251
+
252
+	/**
253
+	 * @param array           $update_info {
254
+	 * @type string           $gateway_txn_id
255
+	 * @type string status an EEMI_Payment status
256
+	 *                                     }
257
+	 * @param EEI_Transaction $transaction
258
+	 * @return EEI_Payment
259
+	 */
260
+	public function handle_payment_update($update_info, $transaction)
261
+	{
262
+		$payment = $transaction instanceof EEI_Transaction ? $transaction->last_payment() : null;
263
+		if ($payment instanceof EEI_Payment) {
264
+			$this->log(array('Return from Authorization' => $update_info), $payment);
265
+			$transaction = $payment->transaction();
266
+			if (! $transaction instanceof EEI_Transaction) {
267
+				$payment->set_gateway_response(
268
+					esc_html__(
269
+						'Could not process this payment because it has no associated transaction.',
270
+						'event_espresso'
271
+					)
272
+				);
273
+				$payment->set_status($this->_pay_model->failed_status());
274
+				return $payment;
275
+			}
276
+			$primary_registrant = $transaction->primary_registration();
277
+			$payment_details = $payment->details();
278
+			// Check if we still have the token.
279
+			if (! isset($payment_details['TOKEN']) || empty($payment_details['TOKEN'])) {
280
+				$payment->set_status($this->_pay_model->failed_status());
281
+				return $payment;
282
+			}
283
+			$cdetails_request_dtls = array(
284
+				'METHOD' => 'GetExpressCheckoutDetails',
285
+				'TOKEN'  => $payment_details['TOKEN'],
286
+			);
287
+			// Request Customer Details.
288
+			$cdetails_request_response = $this->_ppExpress_request(
289
+				$cdetails_request_dtls,
290
+				'Customer Details',
291
+				$payment
292
+			);
293
+			$cdetails_rstatus = $this->_ppExpress_check_response($cdetails_request_response);
294
+			$cdata_response_args = (isset($cdetails_rstatus['args']) && is_array($cdetails_rstatus['args']))
295
+				? $cdetails_rstatus['args']
296
+				: array();
297
+			if ($cdetails_rstatus['status']) {
298
+				// We got the PayerID so now we can Complete the transaction.
299
+				$docheckout_request_dtls = array(
300
+					'METHOD'                         => 'DoExpressCheckoutPayment',
301
+					'PAYERID'                        => $cdata_response_args['PAYERID'],
302
+					'TOKEN'                          => $payment_details['TOKEN'],
303
+					'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
304
+					'PAYMENTREQUEST_0_AMT'           => $payment->amount(),
305
+					'PAYMENTREQUEST_0_CURRENCYCODE'  => $payment->currency_code(),
306
+					// EE will blow up if you change this
307
+					'BUTTONSOURCE'                   => 'EventEspresso_SP',
308
+				);
309
+				 // Include itemized list.
310
+				$itemized_list = $this->itemize_list(
311
+					$payment,
312
+					$transaction,
313
+					$cdata_response_args
314
+				);
315
+				$docheckout_request_dtls = array_merge($docheckout_request_dtls, $itemized_list);
316
+				// Payment Checkout/Capture.
317
+				$docheckout_request_response = $this->_ppExpress_request(
318
+					$docheckout_request_dtls,
319
+					'Do Payment',
320
+					$payment
321
+				);
322
+				$docheckout_rstatus = $this->_ppExpress_check_response($docheckout_request_response);
323
+				$docheckout_response_args = (isset($docheckout_rstatus['args']) && is_array($docheckout_rstatus['args']))
324
+					? $docheckout_rstatus['args']
325
+					: array();
326
+				if ($docheckout_rstatus['status']) {
327
+					// All is well, payment approved.
328
+					$primary_registration_code = $primary_registrant instanceof EE_Registration ?
329
+						$primary_registrant->reg_code()
330
+						: '';
331
+					$payment->set_extra_accntng($primary_registration_code);
332
+					$payment->set_amount(isset($docheckout_response_args['PAYMENTINFO_0_AMT'])
333
+						? (float) $docheckout_response_args['PAYMENTINFO_0_AMT']
334
+						: 0);
335
+					$payment->set_txn_id_chq_nmbr(isset($docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID'])
336
+						? $docheckout_response_args['PAYMENTINFO_0_TRANSACTIONID']
337
+						: null);
338
+					$payment->set_details($cdata_response_args);
339
+					$payment->set_gateway_response(isset($docheckout_response_args['PAYMENTINFO_0_ACK'])
340
+						? $docheckout_response_args['PAYMENTINFO_0_ACK']
341
+						: '');
342
+					$payment->set_status($this->_pay_model->approved_status());
343
+				} else {
344
+					if (isset($docheckout_response_args['L_ERRORCODE'])) {
345
+						$payment->set_gateway_response(
346
+							$docheckout_response_args['L_ERRORCODE']
347
+							. '; '
348
+							. $docheckout_response_args['L_SHORTMESSAGE']
349
+						);
350
+					} else {
351
+						$payment->set_gateway_response(
352
+							esc_html__(
353
+								'Error occurred while trying to Capture the funds.',
354
+								'event_espresso'
355
+							)
356
+						);
357
+					}
358
+					$payment->set_details($docheckout_response_args);
359
+					$payment->set_status($this->_pay_model->declined_status());
360
+				}
361
+			} else {
362
+				if (isset($cdata_response_args['L_ERRORCODE'])) {
363
+					$payment->set_gateway_response(
364
+						$cdata_response_args['L_ERRORCODE']
365
+						. '; '
366
+						. $cdata_response_args['L_SHORTMESSAGE']
367
+					);
368
+				} else {
369
+					$payment->set_gateway_response(
370
+						esc_html__(
371
+							'Error occurred while trying to get payment Details from PayPal.',
372
+							'event_espresso'
373
+						)
374
+					);
375
+				}
376
+				$payment->set_details($cdata_response_args);
377
+				$payment->set_status($this->_pay_model->failed_status());
378
+			}
379
+		} else {
380
+			$payment->set_gateway_response(
381
+				esc_html__(
382
+					'Error occurred while trying to process the payment.',
383
+					'event_espresso'
384
+				)
385
+			);
386
+			$payment->set_status($this->_pay_model->failed_status());
387
+		}
388
+		return $payment;
389
+	}
390
+
391
+
392
+
393
+	/**
394
+	 *  Make a list of items that are in the giver transaction.
395
+	 *
396
+	 * @param EEI_Payment     $payment
397
+	 * @param EEI_Transaction $transaction
398
+	 * @param array           $request_response_args Data from a previous communication with PP.
399
+	 * @return array
400
+	 */
401
+	public function itemize_list(EEI_Payment $payment, EEI_Transaction $transaction, $request_response_args = array())
402
+	{
403
+		$itemized_list = array();
404
+		$gateway_formatter = $this->_get_gateway_formatter();
405
+		// If we have data from a previous communication with PP (on this transaction) we may use that for our list...
406
+		if (! empty($request_response_args)
407
+			&& array_key_exists('L_PAYMENTREQUEST_0_AMT0', $request_response_args)
408
+			&& array_key_exists('PAYMENTREQUEST_0_ITEMAMT', $request_response_args)
409
+		) {
410
+			foreach ($request_response_args as $arg_key => $arg_val) {
411
+				if (strpos($arg_key, 'PAYMENTREQUEST_') !== false
412
+					&& strpos($arg_key, 'NOTIFYURL') === false
413
+				) {
414
+					$itemized_list[ $arg_key ] = $arg_val;
415
+				}
416
+			}
417
+			// If we got only a few Items then something is not right.
418
+			if (count($itemized_list) > 2) {
419
+				return $itemized_list;
420
+			} else {
421
+				if (WP_DEBUG) {
422
+					throw new EE_Error(
423
+						sprintf(
424
+							esc_html__(
425
+								// @codingStandardsIgnoreStart
426
+								'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',
427
+								// @codingStandardsIgnoreEnd
428
+								'event_espresso'
429
+							),
430
+							wp_json_encode($itemized_list)
431
+						)
432
+					);
433
+				}
434
+				// Reset the list and log an error, maybe allow to try and generate a new list (below).
435
+				$itemized_list = array();
436
+				$this->log(
437
+					array(
438
+						esc_html__(
439
+							'Could not generate a proper item list with:',
440
+							'event_espresso'
441
+						) => $request_response_args
442
+					),
443
+					$payment
444
+				);
445
+			}
446
+		}
447
+		// ...otherwise we generate a new list for this transaction.
448
+		if ($this->_money->compare_floats($payment->amount(), $transaction->total(), '==')) {
449
+			$item_num = 0;
450
+			$itemized_sum = 0;
451
+			$total_line_items = $transaction->total_line_item();
452
+			// Go through each item in the list.
453
+			foreach ($total_line_items->get_items() as $line_item) {
454
+				if ($line_item instanceof EE_Line_Item) {
455
+					// PayPal doesn't like line items with 0.00 amount, so we may skip those.
456
+					if (EEH_Money::compare_floats($line_item->total(), '0.00', '==')) {
457
+						continue;
458
+					}
459
+					$unit_price = $line_item->unit_price();
460
+					$line_item_quantity = $line_item->quantity();
461
+					// This is a discount.
462
+					if ($line_item->is_percent()) {
463
+						$unit_price = $line_item->total();
464
+						$line_item_quantity = 1;
465
+					}
466
+					// Item Name.
467
+					$itemized_list[ 'L_PAYMENTREQUEST_0_NAME' . $item_num ] = mb_strcut(
468
+						$gateway_formatter->formatLineItemName($line_item, $payment),
469
+						0,
470
+						127
471
+					);
472
+					// Item description.
473
+					$itemized_list[ 'L_PAYMENTREQUEST_0_DESC' . $item_num ] = mb_strcut(
474
+						$gateway_formatter->formatLineItemDesc($line_item, $payment),
475
+						0,
476
+						127
477
+					);
478
+					// Cost of individual item.
479
+					$itemized_list[ 'L_PAYMENTREQUEST_0_AMT' . $item_num ] = $gateway_formatter->formatCurrency($unit_price);
480
+					// Item Number.
481
+					$itemized_list[ 'L_PAYMENTREQUEST_0_NUMBER' . $item_num ] = $item_num + 1;
482
+					// Item quantity.
483
+					$itemized_list[ 'L_PAYMENTREQUEST_0_QTY' . $item_num ] = $line_item_quantity;
484
+					// Digital item is sold.
485
+					$itemized_list[ 'L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num ] = 'Physical';
486
+					$itemized_sum += $line_item->total();
487
+					++$item_num;
488
+				}
489
+			}
490
+			// Item's sales S/H and tax amount.
491
+			$itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $total_line_items->get_items_total();
492
+			$itemized_list['PAYMENTREQUEST_0_TAXAMT'] = $total_line_items->get_total_tax();
493
+			$itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
494
+			$itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
495
+			$itemized_sum_diff_from_txn_total = round(
496
+				$transaction->total() - $itemized_sum - $total_line_items->get_total_tax(),
497
+				2
498
+			);
499
+			// If we were not able to recognize some item like promotion, surcharge or cancellation,
500
+			// add the difference as an extra line item.
501
+			if ($this->_money->compare_floats($itemized_sum_diff_from_txn_total, 0, '!=')) {
502
+				// Item Name.
503
+				$itemized_list[ 'L_PAYMENTREQUEST_0_NAME' . $item_num ] = mb_strcut(
504
+					esc_html__(
505
+						'Other (promotion/surcharge/cancellation)',
506
+						'event_espresso'
507
+					),
508
+					0,
509
+					127
510
+				);
511
+				// Item description.
512
+				$itemized_list[ 'L_PAYMENTREQUEST_0_DESC' . $item_num ] = '';
513
+				// Cost of individual item.
514
+				$itemized_list[ 'L_PAYMENTREQUEST_0_AMT' . $item_num ] = $gateway_formatter->formatCurrency(
515
+					$itemized_sum_diff_from_txn_total
516
+				);
517
+				// Item Number.
518
+				$itemized_list[ 'L_PAYMENTREQUEST_0_NUMBER' . $item_num ] = $item_num + 1;
519
+				// Item quantity.
520
+				$itemized_list[ 'L_PAYMENTREQUEST_0_QTY' . $item_num ] = 1;
521
+				// Digital item is sold.
522
+				$itemized_list[ 'L_PAYMENTREQUEST_0_ITEMCATEGORY' . $item_num ] = 'Physical';
523
+				$item_num++;
524
+			}
525
+		} else {
526
+			// Just one Item.
527
+			// Item Name.
528
+			$itemized_list['L_PAYMENTREQUEST_0_NAME0'] = mb_strcut(
529
+				$gateway_formatter->formatPartialPaymentLineItemName($payment),
530
+				0,
531
+				127
532
+			);
533
+			// Item description.
534
+			$itemized_list['L_PAYMENTREQUEST_0_DESC0'] = mb_strcut(
535
+				$gateway_formatter->formatPartialPaymentLineItemDesc($payment),
536
+				0,
537
+				127
538
+			);
539
+			// Cost of individual item.
540
+			$itemized_list['L_PAYMENTREQUEST_0_AMT0'] = $gateway_formatter->formatCurrency($payment->amount());
541
+			// Item Number.
542
+			$itemized_list['L_PAYMENTREQUEST_0_NUMBER0'] = 1;
543
+			// Item quantity.
544
+			$itemized_list['L_PAYMENTREQUEST_0_QTY0'] = 1;
545
+			// Digital item is sold.
546
+			$itemized_list['L_PAYMENTREQUEST_0_ITEMCATEGORY0'] = 'Physical';
547
+			// Item's sales S/H and tax amount.
548
+			$itemized_list['PAYMENTREQUEST_0_ITEMAMT'] = $gateway_formatter->formatCurrency($payment->amount());
549
+			$itemized_list['PAYMENTREQUEST_0_TAXAMT'] = '0';
550
+			$itemized_list['PAYMENTREQUEST_0_SHIPPINGAMT'] = '0';
551
+			$itemized_list['PAYMENTREQUEST_0_HANDLINGAMT'] = '0';
552
+		}
553
+		return $itemized_list;
554
+	}
555
+
556
+
557
+
558
+	/**
559
+	 *  Make the Express checkout request.
560
+	 *
561
+	 * @param array       $request_params
562
+	 * @param string      $request_text
563
+	 * @param EEI_Payment $payment
564
+	 * @return mixed
565
+	 */
566
+	public function _ppExpress_request($request_params, $request_text, $payment)
567
+	{
568
+		$request_dtls = array(
569
+			'VERSION'   => '204.0',
570
+			'USER'      => urlencode($this->_api_username),
571
+			'PWD'       => urlencode($this->_api_password),
572
+			'SIGNATURE' => urlencode($this->_api_signature),
573
+		);
574
+		$dtls = array_merge($request_dtls, $request_params);
575
+		$this->_log_clean_request($dtls, $payment, $request_text . ' Request');
576
+		// Request Customer Details.
577
+		$request_response = wp_remote_post(
578
+			$this->_base_gateway_url,
579
+			array(
580
+				'method'      => 'POST',
581
+				'timeout'     => 45,
582
+				'httpversion' => '1.1',
583
+				'cookies'     => array(),
584
+				'headers'     => array(),
585
+				'body'        => http_build_query($dtls, '', '&'),
586
+			)
587
+		);
588
+		// Log the response.
589
+		$this->log(array($request_text . ' Response' => $request_response), $payment);
590
+		return $request_response;
591
+	}
592
+
593
+
594
+
595
+	/**
596
+	 *  Check the response status.
597
+	 *
598
+	 * @param mixed $request_response
599
+	 * @return array
600
+	 */
601
+	public function _ppExpress_check_response($request_response)
602
+	{
603
+		if (is_wp_error($request_response) || empty($request_response['body'])) {
604
+			// If we got here then there was an error in this request.
605
+			return array('status' => false, 'args' => $request_response);
606
+		}
607
+		$response_args = array();
608
+		parse_str(urldecode($request_response['body']), $response_args);
609
+		if (! isset($response_args['ACK'])) {
610
+			return array('status' => false, 'args' => $request_response);
611
+		}
612
+		if ((
613
+				isset($response_args['PAYERID'])
614
+				|| isset($response_args['TOKEN'])
615
+				|| isset($response_args['PAYMENTINFO_0_TRANSACTIONID'])
616
+				|| (isset($response_args['PAYMENTSTATUS']) && $response_args['PAYMENTSTATUS'] === 'Completed')
617
+			)
618
+			&& in_array($response_args['ACK'], array('Success', 'SuccessWithWarning'), true)
619
+		) {
620
+			// Response status OK, return response parameters for further processing.
621
+			return array('status' => true, 'args' => $response_args);
622
+		}
623
+		$errors = $this->_get_errors($response_args);
624
+		return array('status' => false, 'args' => $errors);
625
+	}
626
+
627
+
628
+
629
+	/**
630
+	 *  Log a "Cleared" request.
631
+	 *
632
+	 * @param array       $request
633
+	 * @param EEI_Payment $payment
634
+	 * @param string      $info
635
+	 * @return void
636
+	 */
637
+	private function _log_clean_request($request, $payment, $info)
638
+	{
639
+		$cleaned_request_data = $request;
640
+		unset($cleaned_request_data['PWD'], $cleaned_request_data['USER'], $cleaned_request_data['SIGNATURE']);
641
+		$this->log(array($info => $cleaned_request_data), $payment);
642
+	}
643
+
644
+
645
+
646
+	/**
647
+	 *  Get error from the response data.
648
+	 *
649
+	 * @param array $data_array
650
+	 * @return array
651
+	 */
652
+	private function _get_errors($data_array)
653
+	{
654
+		$errors = array();
655
+		$n = 0;
656
+		while (isset($data_array[ "L_ERRORCODE{$n}" ])) {
657
+			$l_error_code = isset($data_array[ "L_ERRORCODE{$n}" ])
658
+				? $data_array[ "L_ERRORCODE{$n}" ]
659
+				: '';
660
+			$l_severity_code = isset($data_array[ "L_SEVERITYCODE{$n}" ])
661
+				? $data_array[ "L_SEVERITYCODE{$n}" ]
662
+				: '';
663
+			$l_short_message = isset($data_array[ "L_SHORTMESSAGE{$n}" ])
664
+				? $data_array[ "L_SHORTMESSAGE{$n}" ]
665
+				: '';
666
+			$l_long_message = isset($data_array[ "L_LONGMESSAGE{$n}" ])
667
+				? $data_array[ "L_LONGMESSAGE{$n}" ]
668
+				: '';
669
+			if ($n === 0) {
670
+				$errors = array(
671
+					'L_ERRORCODE'    => $l_error_code,
672
+					'L_SHORTMESSAGE' => $l_short_message,
673
+					'L_LONGMESSAGE'  => $l_long_message,
674
+					'L_SEVERITYCODE' => $l_severity_code,
675
+				);
676
+			} else {
677
+				$errors['L_ERRORCODE'] .= ', ' . $l_error_code;
678
+				$errors['L_SHORTMESSAGE'] .= ', ' . $l_short_message;
679
+				$errors['L_LONGMESSAGE'] .= ', ' . $l_long_message;
680
+				$errors['L_SEVERITYCODE'] .= ', ' . $l_severity_code;
681
+			}
682
+			$n++;
683
+		}
684
+		return $errors;
685
+	}
686 686
 }
Please login to merge, or discard this patch.
caffeinated/payment_methods/Aim/EEG_Aim.gateway.php 1 patch
Indentation   +605 added lines, -605 removed lines patch added patch discarded remove patch
@@ -25,427 +25,427 @@  discard block
 block discarded – undo
25 25
 class EEG_Aim extends EE_Onsite_Gateway
26 26
 {
27 27
 
28
-    const LIVE_URL    = 'https://secure2.authorize.net/gateway/transact.dll'; // Authnet URL
29
-
30
-    const SANDBOX_URL = 'https://test.authorize.net/gateway/transact.dll';
31
-
32
-    protected $_login_id;
33
-
34
-    protected $_transaction_key;
35
-
36
-    protected $_server;
37
-
38
-    protected $_currencies_supported = array(
39
-        'AUD',
40
-        'USD',
41
-        'CAD',
42
-        'EUR',
43
-        'GBP',
44
-        'NZD',
45
-    );
46
-
47
-    /**
48
-     * Whether to send test transactions (even to live site)
49
-     *
50
-     * @var boolean
51
-     */
52
-    protected $_test_transactions;
53
-
54
-    private $VERIFY_PEER = false;
55
-
56
-    private $_x_post_fields = array(
57
-        "version"        => "3.1",
58
-        "delim_char"     => ",",
59
-        "delim_data"     => "TRUE",
60
-        "relay_response" => "FALSE",
61
-        "encap_char"     => "|",
62
-    );
63
-
64
-    private $_additional_line_items = array();
65
-
66
-    /**
67
-     * A list of all fields in the AIM API.
68
-     * Used to warn user if they try to set a field not offered in the API.
69
-     */
70
-    private $_all_aim_fields = array(
71
-        "address",
72
-        "allow_partial_auth",
73
-        "amount",
74
-        "auth_code",
75
-        "authentication_indicator",
76
-        "bank_aba_code",
77
-        "bank_acct_name",
78
-        "bank_acct_num",
79
-        "bank_acct_type",
80
-        "bank_check_number",
81
-        "bank_name",
82
-        "card_code",
83
-        "card_num",
84
-        "cardholder_authentication_value",
85
-        "city",
86
-        "company",
87
-        "country",
88
-        "cust_id",
89
-        "customer_ip",
90
-        "delim_char",
91
-        "delim_data",
92
-        "description",
93
-        "duplicate_window",
94
-        "duty",
95
-        "echeck_type",
96
-        "email",
97
-        "email_customer",
98
-        "encap_char",
99
-        "exp_date",
100
-        "fax",
101
-        "first_name",
102
-        "footer_email_receipt",
103
-        "freight",
104
-        "header_email_receipt",
105
-        "invoice_num",
106
-        "last_name",
107
-        "line_item",
108
-        "login",
109
-        "method",
110
-        "phone",
111
-        "po_num",
112
-        "recurring_billing",
113
-        "relay_response",
114
-        "ship_to_address",
115
-        "ship_to_city",
116
-        "ship_to_company",
117
-        "ship_to_country",
118
-        "ship_to_first_name",
119
-        "ship_to_last_name",
120
-        "ship_to_state",
121
-        "ship_to_zip",
122
-        "split_tender_id",
123
-        "state",
124
-        "tax",
125
-        "tax_exempt",
126
-        "test_request",
127
-        "tran_key",
128
-        "trans_id",
129
-        "type",
130
-        "version",
131
-        "zip",
132
-        "solution_id",
133
-        "currency_code"
134
-    );
135
-
136
-
137
-    /**
138
-     * Gets the URL where the request should go. This is filterable
139
-     *
140
-     * @return string
141
-     */
142
-    protected function _get_server_url()
143
-    {
144
-        return apply_filters(
145
-            'FHEE__EEG_Aim___get_server_url',
146
-            $this->_debug_mode ? self::SANDBOX_URL : self::LIVE_URL,
147
-            $this
148
-        );
149
-    }
150
-
151
-
152
-    /**
153
-     * TEMPORARY CALLBACK! Do not use
154
-     * Callback which filters the server url. This is added so site admins can revert to using
155
-     * the old AIM server in case Akamai service breaks their integration.
156
-     * Using Akamai will, however, be mandatory on June 30th 2016 Authorize.net
157
-     * (see http://www.authorize.net/support/akamaifaqs/#firewall?utm_campaign=April%202016%20Technical%20Updates%20for%20Merchants.html&utm_medium=email&utm_source=Eloqua&elqTrackId=46103bdc375c411a979c2f658fc99074&elq=7026706360154fee9b6d588b27d8eb6a&elqaid=506&elqat=1&elqCampaignId=343)
158
-     * Once that happens, this will be obsolete and WILL BE REMOVED.
159
-     *
160
-     * @param string $url
161
-     * @param EEG_Aim $gateway_object
162
-     * @return string
163
-     */
164
-    public function possibly_use_deprecated_aim_server($url, EEG_Aim $gateway_object)
165
-    {
166
-        if ($gateway_object->_server === 'authorize.net' && ! $gateway_object->_debug_mode) {
167
-            return 'https://secure.authorize.net/gateway/transact.dll';
168
-        } else {
169
-            return $url;
170
-        }
171
-    }
172
-
173
-
174
-    /**
175
-     * Asks the gateway to do whatever it does to process the payment. Onsite gateways will
176
-     * usually send a request directly to the payment provider and update the payment's status based on that;
177
-     * whereas offsite gateways will usually just update the payment with the URL and query parameters to use
178
-     * for sending the request via http_remote_request()
179
-     *
180
-     * @param EEI_Payment $payment
181
-     * @param array $billing_info {
182
-     *  @type $credit_card string
183
-     *  @type $cvv string
184
-     *  @type $exp_month string
185
-     *  @type $exp_year string
186
-     *  @see parent::do_direct_payment
187
-     * }
188
-     * @return EEI_Payment updated
189
-     */
190
-    public function do_direct_payment($payment, $billing_info = null)
191
-    {
192
-        add_filter('FHEE__EEG_Aim___get_server_url', array($this, 'possibly_use_deprecated_aim_server'), 10, 2);
193
-        // Enable test mode if needed
194
-        // 4007000000027  <-- test successful visa
195
-        // 4222222222222  <-- test failure card number
196
-
197
-        $item_num = 1;
198
-        $transaction = $payment->transaction();
199
-        $gateway_formatter = $this->_get_gateway_formatter();
200
-        $order_description = $gateway_formatter->formatOrderDescription($payment);
201
-        $primary_registrant = $transaction->primary_registration();
202
-        // if we're are charging for the full amount, show the normal line items
203
-        // and the itemized total adds up properly
204
-        if ($this->_can_easily_itemize_transaction_for($payment)) {
205
-            $total_line_item = $transaction->total_line_item();
206
-            foreach ($total_line_item->get_items() as $line_item) {
207
-                if ($line_item->quantity() == 0) {
208
-                    continue;
209
-                }
210
-                $this->addLineItem(
211
-                    $item_num++,
212
-                    $gateway_formatter->formatLineItemName($line_item, $payment),
213
-                    $gateway_formatter->formatLineItemDesc($line_item, $payment),
214
-                    $line_item->quantity(),
215
-                    $line_item->unit_price(),
216
-                    'N'
217
-                );
218
-                $order_description .= $line_item->desc().', ';
219
-            }
220
-            foreach ($total_line_item->tax_descendants() as $tax_line_item) {
221
-                $this->addLineItem(
222
-                    $item_num++,
223
-                    $tax_line_item->name(),
224
-                    $tax_line_item->desc(),
225
-                    1,
226
-                    $tax_line_item->total(),
227
-                    'N'
228
-                );
229
-            }
230
-        }
231
-
232
-        // start transaction
233
-        // if in debug mode, use authorize.net's sandbox id; otherwise use the Event Espresso partner id
234
-        $partner_id = $this->_debug_mode ? 'AAA100302' : 'AAA105363';
235
-        $this->setField('solution_id', $partner_id);
236
-        $this->setField('amount', $gateway_formatter->formatCurrency($payment->amount()));
237
-        $this->setField('description', substr(rtrim($order_description, ', '), 0, 255));
238
-        $this->_set_sensitive_billing_data($billing_info);
239
-        $this->setField('first_name', $billing_info['first_name']);
240
-        $this->setField('last_name', $billing_info['last_name']);
241
-        $this->setField('email', $billing_info['email']);
242
-        $this->setField('company', $billing_info['company']);
243
-        $this->setField('address', $billing_info['address'].' '.$billing_info['address2']);
244
-        $this->setField('city', $billing_info['city']);
245
-        $this->setField('state', $billing_info['state']);
246
-        $this->setField('country', $billing_info['country']);
247
-        $this->setField('zip', $billing_info['zip']);
248
-        $this->setField('fax', $billing_info['fax']);
249
-        $this->setField('cust_id', $primary_registrant->ID());
250
-        $this->setField('phone', $billing_info['phone']);
251
-        $currency_config = LoaderFactory::getLoader()->load('EE_Currency_Config');
252
-        $this->setField('currency_code', $currency_config->code);
253
-        // invoice_num would be nice to have it be unique per SPCO page-load, that way if users
254
-        // press back, they don't submit a duplicate. However, we may be keeping the user on teh same spco page
255
-        // in which case, we need to generate teh invoice num per request right here...
256
-        $this->setField('invoice_num', wp_generate_password(12, false));// $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
257
-        // tell AIM that any duplicates sent in the next 5 minutes are to be ignored
258
-        $this->setField('duplicate_window', 5 * MINUTE_IN_SECONDS);
259
-
260
-        if ($this->_test_transactions) {
261
-            $this->test_request = "true";
262
-        }
263
-
264
-        // Capture response
265
-        $this->type = "AUTH_CAPTURE";
266
-        $response = $this->_sendRequest($payment);
267
-        if (! empty($response)) {
268
-            if ($response->error_message) {
269
-                $payment->set_status($this->_pay_model->failed_status());
270
-                $payment->set_gateway_response($response->error_message);
271
-            } else {
272
-                $payment_status = $response->approved
273
-                    ? $this->_pay_model->approved_status()
274
-                    : $this->_pay_model->declined_status();
275
-                $payment->set_status($payment_status);
276
-                // make sure we interpret the AMT as a float, not an international string (where periods are thousand separators)
277
-                $payment->set_amount((float) $response->amount);
278
-                $payment->set_gateway_response(
279
-                    sprintf(
280
-                        esc_html__('%1$s (Reason Code: %2$s)', 'event_espresso'),
281
-                        $response->response_reason_text,
282
-                        $response->response_reason_code
283
-                    )
284
-                );
285
-                if ($this->_debug_mode) {
286
-                    $txn_id = $response->invoice_number;
287
-                } else {
288
-                    $txn_id = $response->transaction_id;
289
-                }
290
-                $payment->set_txn_id_chq_nmbr($txn_id);
291
-            }
292
-            $payment->set_extra_accntng($primary_registrant->reg_code());
293
-            $payment->set_details(print_r($response, true));
294
-        } else {
295
-            $payment->set_status($this->_pay_model->failed_status());
296
-            $payment->set_gateway_response(__("There was no response from Authorize.net", 'event_espresso'));
297
-            $payment->set_details(print_r($response, true));
298
-        }
299
-        return $payment;
300
-    }
301
-
302
-
303
-    /**
304
-     * Sets billing data for the upcoming request to AIM that is considered sensitive;
305
-     * also this method can be overridden by children classes to easily change
306
-     * what billing data gets sent
307
-     *
308
-     * @param array $billing_info
309
-     */
310
-    protected function _set_sensitive_billing_data($billing_info)
311
-    {
312
-        $this->setField('card_num', $billing_info['credit_card']);
313
-        $this->setField('exp_date', $billing_info['exp_month'] . $billing_info['exp_year']);
314
-        $this->setField('card_code', $billing_info['cvv']);
315
-    }
316
-
317
-
318
-    /**
319
-     * Add a line item.
320
-     *
321
-     * @param string $item_id
322
-     * @param string $item_name
323
-     * @param string $item_description
324
-     * @param string $item_quantity
325
-     * @param string $item_unit_price
326
-     * @param string $item_taxable
327
-     */
328
-    public function addLineItem($item_id, $item_name, $item_description, $item_quantity, $item_unit_price, $item_taxable)
329
-    {
330
-        $args = array(
331
-            substr($item_id, 0, 31),
332
-            substr($item_name, 0, 31),
333
-            substr($item_description, 0, 255),
334
-            number_format(abs($item_quantity), 2, '.', ''),
335
-            number_format(abs($item_unit_price), 2, '.', ''),
336
-            $item_taxable === 'N' ? 'N' : 'Y'
337
-        );
338
-        $this->_additional_line_items[] = implode('<|>', $args);
339
-    }
340
-
341
-
342
-    /**
343
-     * Set an individual name/value pair. This will append x_ to the name
344
-     * before posting.
345
-     *
346
-     * @param string $name
347
-     * @param string $value
348
-     * @throws AuthorizeNetException
349
-     */
350
-    protected function setField($name, $value)
351
-    {
352
-        if (in_array($name, $this->_all_aim_fields)) {
353
-            $this->_x_post_fields[ $name ] = $value;
354
-        } else {
355
-            throw new AuthorizeNetException("Error: no field $name exists in the AIM API.
28
+	const LIVE_URL    = 'https://secure2.authorize.net/gateway/transact.dll'; // Authnet URL
29
+
30
+	const SANDBOX_URL = 'https://test.authorize.net/gateway/transact.dll';
31
+
32
+	protected $_login_id;
33
+
34
+	protected $_transaction_key;
35
+
36
+	protected $_server;
37
+
38
+	protected $_currencies_supported = array(
39
+		'AUD',
40
+		'USD',
41
+		'CAD',
42
+		'EUR',
43
+		'GBP',
44
+		'NZD',
45
+	);
46
+
47
+	/**
48
+	 * Whether to send test transactions (even to live site)
49
+	 *
50
+	 * @var boolean
51
+	 */
52
+	protected $_test_transactions;
53
+
54
+	private $VERIFY_PEER = false;
55
+
56
+	private $_x_post_fields = array(
57
+		"version"        => "3.1",
58
+		"delim_char"     => ",",
59
+		"delim_data"     => "TRUE",
60
+		"relay_response" => "FALSE",
61
+		"encap_char"     => "|",
62
+	);
63
+
64
+	private $_additional_line_items = array();
65
+
66
+	/**
67
+	 * A list of all fields in the AIM API.
68
+	 * Used to warn user if they try to set a field not offered in the API.
69
+	 */
70
+	private $_all_aim_fields = array(
71
+		"address",
72
+		"allow_partial_auth",
73
+		"amount",
74
+		"auth_code",
75
+		"authentication_indicator",
76
+		"bank_aba_code",
77
+		"bank_acct_name",
78
+		"bank_acct_num",
79
+		"bank_acct_type",
80
+		"bank_check_number",
81
+		"bank_name",
82
+		"card_code",
83
+		"card_num",
84
+		"cardholder_authentication_value",
85
+		"city",
86
+		"company",
87
+		"country",
88
+		"cust_id",
89
+		"customer_ip",
90
+		"delim_char",
91
+		"delim_data",
92
+		"description",
93
+		"duplicate_window",
94
+		"duty",
95
+		"echeck_type",
96
+		"email",
97
+		"email_customer",
98
+		"encap_char",
99
+		"exp_date",
100
+		"fax",
101
+		"first_name",
102
+		"footer_email_receipt",
103
+		"freight",
104
+		"header_email_receipt",
105
+		"invoice_num",
106
+		"last_name",
107
+		"line_item",
108
+		"login",
109
+		"method",
110
+		"phone",
111
+		"po_num",
112
+		"recurring_billing",
113
+		"relay_response",
114
+		"ship_to_address",
115
+		"ship_to_city",
116
+		"ship_to_company",
117
+		"ship_to_country",
118
+		"ship_to_first_name",
119
+		"ship_to_last_name",
120
+		"ship_to_state",
121
+		"ship_to_zip",
122
+		"split_tender_id",
123
+		"state",
124
+		"tax",
125
+		"tax_exempt",
126
+		"test_request",
127
+		"tran_key",
128
+		"trans_id",
129
+		"type",
130
+		"version",
131
+		"zip",
132
+		"solution_id",
133
+		"currency_code"
134
+	);
135
+
136
+
137
+	/**
138
+	 * Gets the URL where the request should go. This is filterable
139
+	 *
140
+	 * @return string
141
+	 */
142
+	protected function _get_server_url()
143
+	{
144
+		return apply_filters(
145
+			'FHEE__EEG_Aim___get_server_url',
146
+			$this->_debug_mode ? self::SANDBOX_URL : self::LIVE_URL,
147
+			$this
148
+		);
149
+	}
150
+
151
+
152
+	/**
153
+	 * TEMPORARY CALLBACK! Do not use
154
+	 * Callback which filters the server url. This is added so site admins can revert to using
155
+	 * the old AIM server in case Akamai service breaks their integration.
156
+	 * Using Akamai will, however, be mandatory on June 30th 2016 Authorize.net
157
+	 * (see http://www.authorize.net/support/akamaifaqs/#firewall?utm_campaign=April%202016%20Technical%20Updates%20for%20Merchants.html&utm_medium=email&utm_source=Eloqua&elqTrackId=46103bdc375c411a979c2f658fc99074&elq=7026706360154fee9b6d588b27d8eb6a&elqaid=506&elqat=1&elqCampaignId=343)
158
+	 * Once that happens, this will be obsolete and WILL BE REMOVED.
159
+	 *
160
+	 * @param string $url
161
+	 * @param EEG_Aim $gateway_object
162
+	 * @return string
163
+	 */
164
+	public function possibly_use_deprecated_aim_server($url, EEG_Aim $gateway_object)
165
+	{
166
+		if ($gateway_object->_server === 'authorize.net' && ! $gateway_object->_debug_mode) {
167
+			return 'https://secure.authorize.net/gateway/transact.dll';
168
+		} else {
169
+			return $url;
170
+		}
171
+	}
172
+
173
+
174
+	/**
175
+	 * Asks the gateway to do whatever it does to process the payment. Onsite gateways will
176
+	 * usually send a request directly to the payment provider and update the payment's status based on that;
177
+	 * whereas offsite gateways will usually just update the payment with the URL and query parameters to use
178
+	 * for sending the request via http_remote_request()
179
+	 *
180
+	 * @param EEI_Payment $payment
181
+	 * @param array $billing_info {
182
+	 *  @type $credit_card string
183
+	 *  @type $cvv string
184
+	 *  @type $exp_month string
185
+	 *  @type $exp_year string
186
+	 *  @see parent::do_direct_payment
187
+	 * }
188
+	 * @return EEI_Payment updated
189
+	 */
190
+	public function do_direct_payment($payment, $billing_info = null)
191
+	{
192
+		add_filter('FHEE__EEG_Aim___get_server_url', array($this, 'possibly_use_deprecated_aim_server'), 10, 2);
193
+		// Enable test mode if needed
194
+		// 4007000000027  <-- test successful visa
195
+		// 4222222222222  <-- test failure card number
196
+
197
+		$item_num = 1;
198
+		$transaction = $payment->transaction();
199
+		$gateway_formatter = $this->_get_gateway_formatter();
200
+		$order_description = $gateway_formatter->formatOrderDescription($payment);
201
+		$primary_registrant = $transaction->primary_registration();
202
+		// if we're are charging for the full amount, show the normal line items
203
+		// and the itemized total adds up properly
204
+		if ($this->_can_easily_itemize_transaction_for($payment)) {
205
+			$total_line_item = $transaction->total_line_item();
206
+			foreach ($total_line_item->get_items() as $line_item) {
207
+				if ($line_item->quantity() == 0) {
208
+					continue;
209
+				}
210
+				$this->addLineItem(
211
+					$item_num++,
212
+					$gateway_formatter->formatLineItemName($line_item, $payment),
213
+					$gateway_formatter->formatLineItemDesc($line_item, $payment),
214
+					$line_item->quantity(),
215
+					$line_item->unit_price(),
216
+					'N'
217
+				);
218
+				$order_description .= $line_item->desc().', ';
219
+			}
220
+			foreach ($total_line_item->tax_descendants() as $tax_line_item) {
221
+				$this->addLineItem(
222
+					$item_num++,
223
+					$tax_line_item->name(),
224
+					$tax_line_item->desc(),
225
+					1,
226
+					$tax_line_item->total(),
227
+					'N'
228
+				);
229
+			}
230
+		}
231
+
232
+		// start transaction
233
+		// if in debug mode, use authorize.net's sandbox id; otherwise use the Event Espresso partner id
234
+		$partner_id = $this->_debug_mode ? 'AAA100302' : 'AAA105363';
235
+		$this->setField('solution_id', $partner_id);
236
+		$this->setField('amount', $gateway_formatter->formatCurrency($payment->amount()));
237
+		$this->setField('description', substr(rtrim($order_description, ', '), 0, 255));
238
+		$this->_set_sensitive_billing_data($billing_info);
239
+		$this->setField('first_name', $billing_info['first_name']);
240
+		$this->setField('last_name', $billing_info['last_name']);
241
+		$this->setField('email', $billing_info['email']);
242
+		$this->setField('company', $billing_info['company']);
243
+		$this->setField('address', $billing_info['address'].' '.$billing_info['address2']);
244
+		$this->setField('city', $billing_info['city']);
245
+		$this->setField('state', $billing_info['state']);
246
+		$this->setField('country', $billing_info['country']);
247
+		$this->setField('zip', $billing_info['zip']);
248
+		$this->setField('fax', $billing_info['fax']);
249
+		$this->setField('cust_id', $primary_registrant->ID());
250
+		$this->setField('phone', $billing_info['phone']);
251
+		$currency_config = LoaderFactory::getLoader()->load('EE_Currency_Config');
252
+		$this->setField('currency_code', $currency_config->code);
253
+		// invoice_num would be nice to have it be unique per SPCO page-load, that way if users
254
+		// press back, they don't submit a duplicate. However, we may be keeping the user on teh same spco page
255
+		// in which case, we need to generate teh invoice num per request right here...
256
+		$this->setField('invoice_num', wp_generate_password(12, false));// $billing_info['_reg-page-billing-invoice-'.$this->_gateway_name]['value']);
257
+		// tell AIM that any duplicates sent in the next 5 minutes are to be ignored
258
+		$this->setField('duplicate_window', 5 * MINUTE_IN_SECONDS);
259
+
260
+		if ($this->_test_transactions) {
261
+			$this->test_request = "true";
262
+		}
263
+
264
+		// Capture response
265
+		$this->type = "AUTH_CAPTURE";
266
+		$response = $this->_sendRequest($payment);
267
+		if (! empty($response)) {
268
+			if ($response->error_message) {
269
+				$payment->set_status($this->_pay_model->failed_status());
270
+				$payment->set_gateway_response($response->error_message);
271
+			} else {
272
+				$payment_status = $response->approved
273
+					? $this->_pay_model->approved_status()
274
+					: $this->_pay_model->declined_status();
275
+				$payment->set_status($payment_status);
276
+				// make sure we interpret the AMT as a float, not an international string (where periods are thousand separators)
277
+				$payment->set_amount((float) $response->amount);
278
+				$payment->set_gateway_response(
279
+					sprintf(
280
+						esc_html__('%1$s (Reason Code: %2$s)', 'event_espresso'),
281
+						$response->response_reason_text,
282
+						$response->response_reason_code
283
+					)
284
+				);
285
+				if ($this->_debug_mode) {
286
+					$txn_id = $response->invoice_number;
287
+				} else {
288
+					$txn_id = $response->transaction_id;
289
+				}
290
+				$payment->set_txn_id_chq_nmbr($txn_id);
291
+			}
292
+			$payment->set_extra_accntng($primary_registrant->reg_code());
293
+			$payment->set_details(print_r($response, true));
294
+		} else {
295
+			$payment->set_status($this->_pay_model->failed_status());
296
+			$payment->set_gateway_response(__("There was no response from Authorize.net", 'event_espresso'));
297
+			$payment->set_details(print_r($response, true));
298
+		}
299
+		return $payment;
300
+	}
301
+
302
+
303
+	/**
304
+	 * Sets billing data for the upcoming request to AIM that is considered sensitive;
305
+	 * also this method can be overridden by children classes to easily change
306
+	 * what billing data gets sent
307
+	 *
308
+	 * @param array $billing_info
309
+	 */
310
+	protected function _set_sensitive_billing_data($billing_info)
311
+	{
312
+		$this->setField('card_num', $billing_info['credit_card']);
313
+		$this->setField('exp_date', $billing_info['exp_month'] . $billing_info['exp_year']);
314
+		$this->setField('card_code', $billing_info['cvv']);
315
+	}
316
+
317
+
318
+	/**
319
+	 * Add a line item.
320
+	 *
321
+	 * @param string $item_id
322
+	 * @param string $item_name
323
+	 * @param string $item_description
324
+	 * @param string $item_quantity
325
+	 * @param string $item_unit_price
326
+	 * @param string $item_taxable
327
+	 */
328
+	public function addLineItem($item_id, $item_name, $item_description, $item_quantity, $item_unit_price, $item_taxable)
329
+	{
330
+		$args = array(
331
+			substr($item_id, 0, 31),
332
+			substr($item_name, 0, 31),
333
+			substr($item_description, 0, 255),
334
+			number_format(abs($item_quantity), 2, '.', ''),
335
+			number_format(abs($item_unit_price), 2, '.', ''),
336
+			$item_taxable === 'N' ? 'N' : 'Y'
337
+		);
338
+		$this->_additional_line_items[] = implode('<|>', $args);
339
+	}
340
+
341
+
342
+	/**
343
+	 * Set an individual name/value pair. This will append x_ to the name
344
+	 * before posting.
345
+	 *
346
+	 * @param string $name
347
+	 * @param string $value
348
+	 * @throws AuthorizeNetException
349
+	 */
350
+	protected function setField($name, $value)
351
+	{
352
+		if (in_array($name, $this->_all_aim_fields)) {
353
+			$this->_x_post_fields[ $name ] = $value;
354
+		} else {
355
+			throw new AuthorizeNetException("Error: no field $name exists in the AIM API.
356 356
             To set a custom field use setCustomField('field','value') instead.");
357
-        }
358
-    }
359
-
360
-
361
-    /**
362
-     * Posts the request to AuthorizeNet & returns response.
363
-     *
364
-     * @param $payment
365
-     * @return \EE_AuthorizeNetAIM_Response
366
-     */
367
-    private function _sendRequest($payment)
368
-    {
369
-        $this->_x_post_fields['login'] = $this->_login_id;
370
-        $this->_x_post_fields['tran_key'] = $this->_transaction_key;
371
-        $x_keys = array();
372
-        foreach ($this->_x_post_fields as $key => $value) {
373
-            $x_keys[] = "x_$key=" . urlencode($this->_get_unsupported_character_remover()->format($value));
374
-        }
375
-        // Add line items
376
-        foreach ($this->_additional_line_items as $key => $value) {
377
-            $x_keys[] =  "x_line_item=" . urlencode($this->_get_unsupported_character_remover()->format($value));
378
-        }
379
-        $this->_log_clean_request($x_keys, $payment);
380
-        $post_url = $this->_get_server_url();
381
-        $curl_request = curl_init($post_url);
382
-        $post_body = implode("&", $x_keys);
383
-        curl_setopt($curl_request, CURLOPT_POSTFIELDS, $post_body);
384
-        curl_setopt($curl_request, CURLOPT_HEADER, 0);
385
-        curl_setopt($curl_request, CURLOPT_TIMEOUT, 45);
386
-        curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
387
-        curl_setopt($curl_request, CURLOPT_SSL_VERIFYHOST, 2);
388
-        if ($this->VERIFY_PEER) {
389
-            curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__) . '/ssl/cert.pem');
390
-        } else {
391
-            curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);
392
-        }
393
-
394
-        if (preg_match('/xml/', $post_url)) {
395
-            curl_setopt($curl_request, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
396
-        }
397
-
398
-        $response = curl_exec($curl_request);
399
-
400
-        curl_close($curl_request);
401
-        $response_obj =  new EE_AuthorizeNetAIM_Response($response);
402
-
403
-        return $this->_log_and_clean_response($response_obj, $payment);
404
-    }
405
-
406
-
407
-    /**
408
-     * Logs the clean data only
409
-     *
410
-     * @param array $request_array
411
-     * @param EEI_Payment $payment
412
-     */
413
-    protected function _log_clean_request($request_array, $payment)
414
-    {
415
-        $keys_to_filter_out = array('x_card_num', 'x_card_code', 'x_exp_date');
416
-        foreach ($request_array as $index => $keyvaltogether) {
417
-            foreach ($keys_to_filter_out as $key) {
418
-                if (strpos($keyvaltogether, $key) === 0) {
419
-                    // found it at the first character
420
-                    // so its one of them
421
-                    unset($request_array[ $index ]);
422
-                }
423
-            }
424
-        }
425
-        $this->log(
426
-            array(
427
-                'AIM Request sent:' => $request_array,
428
-                'Server URL'        => $this->_get_server_url()
429
-            ),
430
-            $payment
431
-        );
432
-    }
433
-
434
-
435
-
436
-    /**
437
-     * Logs the response and cleans it
438
-     *
439
-     * @param EE_AuthorizeNetAIM_Response $response_obj
440
-     * @param EE_Payment                  $payment
441
-     * @return \EE_AuthorizeNetAIM_Response
442
-     */
443
-    private function _log_and_clean_response($response_obj, $payment)
444
-    {
445
-        $response_obj->account_number = '';
446
-        $this->log(array('AIM Response received:' => (array) $response_obj), $payment);
447
-        return $response_obj;
448
-    }
357
+		}
358
+	}
359
+
360
+
361
+	/**
362
+	 * Posts the request to AuthorizeNet & returns response.
363
+	 *
364
+	 * @param $payment
365
+	 * @return \EE_AuthorizeNetAIM_Response
366
+	 */
367
+	private function _sendRequest($payment)
368
+	{
369
+		$this->_x_post_fields['login'] = $this->_login_id;
370
+		$this->_x_post_fields['tran_key'] = $this->_transaction_key;
371
+		$x_keys = array();
372
+		foreach ($this->_x_post_fields as $key => $value) {
373
+			$x_keys[] = "x_$key=" . urlencode($this->_get_unsupported_character_remover()->format($value));
374
+		}
375
+		// Add line items
376
+		foreach ($this->_additional_line_items as $key => $value) {
377
+			$x_keys[] =  "x_line_item=" . urlencode($this->_get_unsupported_character_remover()->format($value));
378
+		}
379
+		$this->_log_clean_request($x_keys, $payment);
380
+		$post_url = $this->_get_server_url();
381
+		$curl_request = curl_init($post_url);
382
+		$post_body = implode("&", $x_keys);
383
+		curl_setopt($curl_request, CURLOPT_POSTFIELDS, $post_body);
384
+		curl_setopt($curl_request, CURLOPT_HEADER, 0);
385
+		curl_setopt($curl_request, CURLOPT_TIMEOUT, 45);
386
+		curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
387
+		curl_setopt($curl_request, CURLOPT_SSL_VERIFYHOST, 2);
388
+		if ($this->VERIFY_PEER) {
389
+			curl_setopt($curl_request, CURLOPT_CAINFO, dirname(__DIR__) . '/ssl/cert.pem');
390
+		} else {
391
+			curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false);
392
+		}
393
+
394
+		if (preg_match('/xml/', $post_url)) {
395
+			curl_setopt($curl_request, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
396
+		}
397
+
398
+		$response = curl_exec($curl_request);
399
+
400
+		curl_close($curl_request);
401
+		$response_obj =  new EE_AuthorizeNetAIM_Response($response);
402
+
403
+		return $this->_log_and_clean_response($response_obj, $payment);
404
+	}
405
+
406
+
407
+	/**
408
+	 * Logs the clean data only
409
+	 *
410
+	 * @param array $request_array
411
+	 * @param EEI_Payment $payment
412
+	 */
413
+	protected function _log_clean_request($request_array, $payment)
414
+	{
415
+		$keys_to_filter_out = array('x_card_num', 'x_card_code', 'x_exp_date');
416
+		foreach ($request_array as $index => $keyvaltogether) {
417
+			foreach ($keys_to_filter_out as $key) {
418
+				if (strpos($keyvaltogether, $key) === 0) {
419
+					// found it at the first character
420
+					// so its one of them
421
+					unset($request_array[ $index ]);
422
+				}
423
+			}
424
+		}
425
+		$this->log(
426
+			array(
427
+				'AIM Request sent:' => $request_array,
428
+				'Server URL'        => $this->_get_server_url()
429
+			),
430
+			$payment
431
+		);
432
+	}
433
+
434
+
435
+
436
+	/**
437
+	 * Logs the response and cleans it
438
+	 *
439
+	 * @param EE_AuthorizeNetAIM_Response $response_obj
440
+	 * @param EE_Payment                  $payment
441
+	 * @return \EE_AuthorizeNetAIM_Response
442
+	 */
443
+	private function _log_and_clean_response($response_obj, $payment)
444
+	{
445
+		$response_obj->account_number = '';
446
+		$this->log(array('AIM Response received:' => (array) $response_obj), $payment);
447
+		return $response_obj;
448
+	}
449 449
 }
450 450
 
451 451
 
@@ -461,192 +461,192 @@  discard block
 block discarded – undo
461 461
 class EE_AuthorizeNetAIM_Response
462 462
 {
463 463
 
464
-    const APPROVED = '1';
465
-    const DECLINED = '2';
466
-    const ERROR = '3';
467
-    const HELD = '4';
468
-
469
-    protected $_x_post_fields = array(
470
-        "version"        => "3.1",
471
-        "delim_char"     => ",",
472
-        "delim_data"     => "TRUE",
473
-        "relay_response" => "FALSE",
474
-        "encap_char"     => "|",
475
-    );
476
-    public $approved;
477
-    public $declined;
478
-    public $error;
479
-    public $held;
480
-    public $response_code;
481
-    public $response_subcode;
482
-    public $response_reason_code;
483
-    public $response_reason_text;
484
-    public $authorization_code;
485
-    public $avs_response;
486
-    public $transaction_id;
487
-    public $invoice_number;
488
-    public $description;
489
-    public $amount;
490
-    public $method;
491
-    public $transaction_type;
492
-    public $customer_id;
493
-    public $first_name;
494
-    public $last_name;
495
-    public $company;
496
-    public $address;
497
-    public $city;
498
-    public $state;
499
-    public $zip_code;
500
-    public $country;
501
-    public $phone;
502
-    public $fax;
503
-    public $email_address;
504
-    public $ship_to_first_name;
505
-    public $ship_to_last_name;
506
-    public $ship_to_company;
507
-    public $ship_to_address;
508
-    public $ship_to_city;
509
-    public $ship_to_state;
510
-    public $ship_to_zip_code;
511
-    public $ship_to_country;
512
-    public $tax;
513
-    public $duty;
514
-    public $freight;
515
-    public $tax_exempt;
516
-    public $purchase_order_number;
517
-    public $md5_hash;
518
-    public $card_code_response;
519
-    public $cavv_response; // cardholder_authentication_verification_response
520
-    public $account_number;
521
-    public $card_type;
522
-    public $split_tender_id;
523
-    public $requested_amount;
524
-    public $balance_on_card;
525
-    public $response; // The response string from AuthorizeNet.
526
-    public $error_message;
527
-    private $_response_array = array(); // An array with the split response.
528
-
529
-
530
-    /**
531
-     * Constructor. Parses the AuthorizeNet response string
532
-     *
533
-     * @param string $response The response from the AuthNet server.
534
-     * @var string   $delimiter The delimiter used (default is ",")
535
-     * @var string   $encap_char The encap_char used (default is "|")
536
-     * @var array    $custom_fields Any custom fields set in the request.
537
-     */
538
-
539
-    public function __construct($response)
540
-    {
541
-        $encap_char = $this->_x_post_fields['encap_char'];
542
-        $delimiter = $this->_x_post_fields['delim_char'];
543
-        if ($response) {
544
-            // Split Array
545
-            $this->response = $response;
546
-            if ($encap_char) {
547
-                $this->_response_array = explode($encap_char . $delimiter . $encap_char, substr($response, 1, -1));
548
-            } else {
549
-                $this->_response_array = explode($delimiter, $response);
550
-            }
551
-
552
-            /**
553
-             * If AuthorizeNet doesn't return a delimited response.
554
-             */
555
-            if (count($this->_response_array) < 10) {
556
-                $this->approved = false;
557
-                $this->error = true;
558
-                $this->error_message = sprintf(
559
-                    esc_html__('Unrecognized response from Authorize.net: %1$s', 'event_espresso'),
560
-                    esc_html($response)
561
-                );
562
-                return;
563
-            }
564
-
565
-
566
-
567
-            // Set all fields
568
-            $this->response_code = $this->_response_array[0];
569
-            $this->response_subcode = $this->_response_array[1];
570
-            $this->response_reason_code = $this->_response_array[2];
571
-            $this->response_reason_text = $this->_response_array[3];
572
-            $this->authorization_code = $this->_response_array[4];
573
-            $this->avs_response = $this->_response_array[5];
574
-            $this->transaction_id = $this->_response_array[6];
575
-            $this->invoice_number = $this->_response_array[7];
576
-            $this->description = $this->_response_array[8];
577
-            $this->amount = $this->_response_array[9];
578
-            $this->method = $this->_response_array[10];
579
-            $this->transaction_type = $this->_response_array[11];
580
-            $this->customer_id = $this->_response_array[12];
581
-            $this->first_name = $this->_response_array[13];
582
-            $this->last_name = $this->_response_array[14];
583
-            $this->company = $this->_response_array[15];
584
-            $this->address = $this->_response_array[16];
585
-            $this->city = $this->_response_array[17];
586
-            $this->state = $this->_response_array[18];
587
-            $this->zip_code = $this->_response_array[19];
588
-            $this->country = $this->_response_array[20];
589
-            $this->phone = $this->_response_array[21];
590
-            $this->fax = $this->_response_array[22];
591
-            $this->email_address = $this->_response_array[23];
592
-            $this->ship_to_first_name = $this->_response_array[24];
593
-            $this->ship_to_last_name = $this->_response_array[25];
594
-            $this->ship_to_company = $this->_response_array[26];
595
-            $this->ship_to_address = $this->_response_array[27];
596
-            $this->ship_to_city = $this->_response_array[28];
597
-            $this->ship_to_state = $this->_response_array[29];
598
-            $this->ship_to_zip_code = $this->_response_array[30];
599
-            $this->ship_to_country = $this->_response_array[31];
600
-            $this->tax = $this->_response_array[32];
601
-            $this->duty = $this->_response_array[33];
602
-            $this->freight = $this->_response_array[34];
603
-            $this->tax_exempt = $this->_response_array[35];
604
-            $this->purchase_order_number = $this->_response_array[36];
605
-            $this->md5_hash = $this->_response_array[37];
606
-            $this->card_code_response = $this->_response_array[38];
607
-            $this->cavv_response = $this->_response_array[39];
608
-            $this->account_number = $this->_response_array[50];
609
-            $this->card_type = $this->_response_array[51];
610
-            $this->split_tender_id = $this->_response_array[52];
611
-            $this->requested_amount = $this->_response_array[53];
612
-            $this->balance_on_card = $this->_response_array[54];
613
-
614
-            $this->approved = ($this->response_code === self::APPROVED);
615
-            $this->declined = ($this->response_code === self::DECLINED);
616
-            $this->error = ($this->response_code === self::ERROR);
617
-            $this->held = ($this->response_code === self::HELD);
618
-        } else {
619
-            $this->approved = false;
620
-            $this->error = true;
621
-            $this->error_message = esc_html__(
622
-                'Error connecting to Authorize.net',
623
-                'event_espresso'
624
-            );
625
-        }
626
-    }
464
+	const APPROVED = '1';
465
+	const DECLINED = '2';
466
+	const ERROR = '3';
467
+	const HELD = '4';
468
+
469
+	protected $_x_post_fields = array(
470
+		"version"        => "3.1",
471
+		"delim_char"     => ",",
472
+		"delim_data"     => "TRUE",
473
+		"relay_response" => "FALSE",
474
+		"encap_char"     => "|",
475
+	);
476
+	public $approved;
477
+	public $declined;
478
+	public $error;
479
+	public $held;
480
+	public $response_code;
481
+	public $response_subcode;
482
+	public $response_reason_code;
483
+	public $response_reason_text;
484
+	public $authorization_code;
485
+	public $avs_response;
486
+	public $transaction_id;
487
+	public $invoice_number;
488
+	public $description;
489
+	public $amount;
490
+	public $method;
491
+	public $transaction_type;
492
+	public $customer_id;
493
+	public $first_name;
494
+	public $last_name;
495
+	public $company;
496
+	public $address;
497
+	public $city;
498
+	public $state;
499
+	public $zip_code;
500
+	public $country;
501
+	public $phone;
502
+	public $fax;
503
+	public $email_address;
504
+	public $ship_to_first_name;
505
+	public $ship_to_last_name;
506
+	public $ship_to_company;
507
+	public $ship_to_address;
508
+	public $ship_to_city;
509
+	public $ship_to_state;
510
+	public $ship_to_zip_code;
511
+	public $ship_to_country;
512
+	public $tax;
513
+	public $duty;
514
+	public $freight;
515
+	public $tax_exempt;
516
+	public $purchase_order_number;
517
+	public $md5_hash;
518
+	public $card_code_response;
519
+	public $cavv_response; // cardholder_authentication_verification_response
520
+	public $account_number;
521
+	public $card_type;
522
+	public $split_tender_id;
523
+	public $requested_amount;
524
+	public $balance_on_card;
525
+	public $response; // The response string from AuthorizeNet.
526
+	public $error_message;
527
+	private $_response_array = array(); // An array with the split response.
528
+
529
+
530
+	/**
531
+	 * Constructor. Parses the AuthorizeNet response string
532
+	 *
533
+	 * @param string $response The response from the AuthNet server.
534
+	 * @var string   $delimiter The delimiter used (default is ",")
535
+	 * @var string   $encap_char The encap_char used (default is "|")
536
+	 * @var array    $custom_fields Any custom fields set in the request.
537
+	 */
538
+
539
+	public function __construct($response)
540
+	{
541
+		$encap_char = $this->_x_post_fields['encap_char'];
542
+		$delimiter = $this->_x_post_fields['delim_char'];
543
+		if ($response) {
544
+			// Split Array
545
+			$this->response = $response;
546
+			if ($encap_char) {
547
+				$this->_response_array = explode($encap_char . $delimiter . $encap_char, substr($response, 1, -1));
548
+			} else {
549
+				$this->_response_array = explode($delimiter, $response);
550
+			}
551
+
552
+			/**
553
+			 * If AuthorizeNet doesn't return a delimited response.
554
+			 */
555
+			if (count($this->_response_array) < 10) {
556
+				$this->approved = false;
557
+				$this->error = true;
558
+				$this->error_message = sprintf(
559
+					esc_html__('Unrecognized response from Authorize.net: %1$s', 'event_espresso'),
560
+					esc_html($response)
561
+				);
562
+				return;
563
+			}
564
+
565
+
566
+
567
+			// Set all fields
568
+			$this->response_code = $this->_response_array[0];
569
+			$this->response_subcode = $this->_response_array[1];
570
+			$this->response_reason_code = $this->_response_array[2];
571
+			$this->response_reason_text = $this->_response_array[3];
572
+			$this->authorization_code = $this->_response_array[4];
573
+			$this->avs_response = $this->_response_array[5];
574
+			$this->transaction_id = $this->_response_array[6];
575
+			$this->invoice_number = $this->_response_array[7];
576
+			$this->description = $this->_response_array[8];
577
+			$this->amount = $this->_response_array[9];
578
+			$this->method = $this->_response_array[10];
579
+			$this->transaction_type = $this->_response_array[11];
580
+			$this->customer_id = $this->_response_array[12];
581
+			$this->first_name = $this->_response_array[13];
582
+			$this->last_name = $this->_response_array[14];
583
+			$this->company = $this->_response_array[15];
584
+			$this->address = $this->_response_array[16];
585
+			$this->city = $this->_response_array[17];
586
+			$this->state = $this->_response_array[18];
587
+			$this->zip_code = $this->_response_array[19];
588
+			$this->country = $this->_response_array[20];
589
+			$this->phone = $this->_response_array[21];
590
+			$this->fax = $this->_response_array[22];
591
+			$this->email_address = $this->_response_array[23];
592
+			$this->ship_to_first_name = $this->_response_array[24];
593
+			$this->ship_to_last_name = $this->_response_array[25];
594
+			$this->ship_to_company = $this->_response_array[26];
595
+			$this->ship_to_address = $this->_response_array[27];
596
+			$this->ship_to_city = $this->_response_array[28];
597
+			$this->ship_to_state = $this->_response_array[29];
598
+			$this->ship_to_zip_code = $this->_response_array[30];
599
+			$this->ship_to_country = $this->_response_array[31];
600
+			$this->tax = $this->_response_array[32];
601
+			$this->duty = $this->_response_array[33];
602
+			$this->freight = $this->_response_array[34];
603
+			$this->tax_exempt = $this->_response_array[35];
604
+			$this->purchase_order_number = $this->_response_array[36];
605
+			$this->md5_hash = $this->_response_array[37];
606
+			$this->card_code_response = $this->_response_array[38];
607
+			$this->cavv_response = $this->_response_array[39];
608
+			$this->account_number = $this->_response_array[50];
609
+			$this->card_type = $this->_response_array[51];
610
+			$this->split_tender_id = $this->_response_array[52];
611
+			$this->requested_amount = $this->_response_array[53];
612
+			$this->balance_on_card = $this->_response_array[54];
613
+
614
+			$this->approved = ($this->response_code === self::APPROVED);
615
+			$this->declined = ($this->response_code === self::DECLINED);
616
+			$this->error = ($this->response_code === self::ERROR);
617
+			$this->held = ($this->response_code === self::HELD);
618
+		} else {
619
+			$this->approved = false;
620
+			$this->error = true;
621
+			$this->error_message = esc_html__(
622
+				'Error connecting to Authorize.net',
623
+				'event_espresso'
624
+			);
625
+		}
626
+	}
627 627
 }
628 628
 
629 629
 if (! class_exists('AuthorizeNetException')) {
630
-    /**
631
-     * Class AuthorizeNetException
632
-     *
633
-     * @package    AuthorizeNet
634
-     */
635
-    class AuthorizeNetException extends Exception
636
-    {
637
-
638
-        /**
639
-         * Construct the exception. Note: The message is NOT binary safe.
640
-         *
641
-         * @link http://php.net/manual/en/exception.construct.php
642
-         * @param string $message [optional] The Exception message to throw.
643
-         * @param int $code [optional] The Exception code.
644
-         * @param Exception $previous [optional] The previous exception used for the exception chaining. Since 5.3.0
645
-         * @since 5.1.0
646
-         */
647
-        public function __construct($message = "", $code = 0, Exception $previous = null)
648
-        {
649
-            parent::__construct($message, $code, $previous);
650
-        }
651
-    }
630
+	/**
631
+	 * Class AuthorizeNetException
632
+	 *
633
+	 * @package    AuthorizeNet
634
+	 */
635
+	class AuthorizeNetException extends Exception
636
+	{
637
+
638
+		/**
639
+		 * Construct the exception. Note: The message is NOT binary safe.
640
+		 *
641
+		 * @link http://php.net/manual/en/exception.construct.php
642
+		 * @param string $message [optional] The Exception message to throw.
643
+		 * @param int $code [optional] The Exception code.
644
+		 * @param Exception $previous [optional] The previous exception used for the exception chaining. Since 5.3.0
645
+		 * @since 5.1.0
646
+		 */
647
+		public function __construct($message = "", $code = 0, Exception $previous = null)
648
+		{
649
+			parent::__construct($message, $code, $previous);
650
+		}
651
+	}
652 652
 }
Please login to merge, or discard this patch.
core/services/loaders/CachingLoader.php 1 patch
Indentation   +154 added lines, -154 removed lines patch added patch discarded remove patch
@@ -17,158 +17,158 @@
 block discarded – undo
17 17
 class CachingLoader extends CachingLoaderDecorator
18 18
 {
19 19
 
20
-    /**
21
-     * @var string $identifier
22
-     */
23
-    protected $identifier;
24
-
25
-    /**
26
-     * @var CollectionInterface $cache
27
-     */
28
-    protected $cache;
29
-
30
-    /**
31
-     * @var ObjectIdentifier
32
-     */
33
-    private $object_identifier;
34
-
35
-
36
-    /**
37
-     * CachingLoader constructor.
38
-     *
39
-     * @param LoaderDecoratorInterface $loader
40
-     * @param CollectionInterface      $cache
41
-     * @param ObjectIdentifier         $object_identifier
42
-     * @param string                   $identifier
43
-     * @throws InvalidDataTypeException
44
-     */
45
-    public function __construct(
46
-        LoaderDecoratorInterface $loader,
47
-        CollectionInterface $cache,
48
-        ObjectIdentifier $object_identifier,
49
-        $identifier = ''
50
-    ) {
51
-        parent::__construct($loader);
52
-        $this->cache       = $cache;
53
-        $this->object_identifier = $object_identifier;
54
-        $this->setIdentifier($identifier);
55
-        if ($this->identifier !== '') {
56
-            // to only clear this cache, and assuming an identifier has been set, simply do the following:
57
-            // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
58
-            // where "IDENTIFIER" = the string that was set during construction
59
-            add_action(
60
-                "AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
61
-                array($this, 'reset')
62
-            );
63
-        }
64
-        // to clear ALL caches, simply do the following:
65
-        // do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
66
-        add_action(
67
-            'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
68
-            array($this, 'reset')
69
-        );
70
-    }
71
-
72
-
73
-    /**
74
-     * @return string
75
-     */
76
-    public function identifier()
77
-    {
78
-        return $this->identifier;
79
-    }
80
-
81
-
82
-    /**
83
-     * @param string $identifier
84
-     * @throws InvalidDataTypeException
85
-     */
86
-    private function setIdentifier($identifier)
87
-    {
88
-        if (! is_string($identifier)) {
89
-            throw new InvalidDataTypeException('$identifier', $identifier, 'string');
90
-        }
91
-        $this->identifier = $identifier;
92
-    }
93
-
94
-
95
-    /**
96
-     * @param FullyQualifiedName|string $fqcn
97
-     * @param mixed                     $object
98
-     * @param array                     $arguments
99
-     * @return bool
100
-     * @throws InvalidArgumentException
101
-     */
102
-    public function share($fqcn, $object, array $arguments = array())
103
-    {
104
-        if ($object instanceof $fqcn) {
105
-            return $this->cache->add(
106
-                $object,
107
-                $this->object_identifier->getIdentifier($fqcn, $arguments)
108
-            );
109
-        }
110
-        throw new InvalidArgumentException(
111
-            sprintf(
112
-                esc_html__(
113
-                    'The supplied class name "%1$s" must match the class of the supplied object.',
114
-                    'event_espresso'
115
-                ),
116
-                $fqcn
117
-            )
118
-        );
119
-    }
120
-
121
-
122
-    /**
123
-     * @param FullyQualifiedName|string $fqcn
124
-     * @param array                     $arguments
125
-     * @param bool                      $shared
126
-     * @param array                     $interfaces
127
-     * @return mixed
128
-     */
129
-    public function load($fqcn, $arguments = array(), $shared = true, array $interfaces = array())
130
-    {
131
-        $fqcn = ltrim($fqcn, '\\');
132
-        // caching can be turned off via the following code:
133
-        // add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
134
-        if (apply_filters(
135
-            'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
136
-            false,
137
-            $this
138
-        )) {
139
-            // even though $shared might be true, caching could be bypassed for whatever reason,
140
-            // so we don't want the core loader to cache anything, therefore caching is turned off
141
-            return $this->loader->load($fqcn, $arguments, false);
142
-        }
143
-        $object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
144
-        if ($this->cache->has($object_identifier)) {
145
-            return $this->cache->get($object_identifier);
146
-        }
147
-        $object = $this->loader->load($fqcn, $arguments, $shared);
148
-        if ($object instanceof $fqcn) {
149
-            $this->cache->add($object, $object_identifier);
150
-        }
151
-        return $object;
152
-    }
153
-
154
-
155
-    /**
156
-     * empties cache and calls reset() on loader if method exists
157
-     */
158
-    public function reset()
159
-    {
160
-        $this->clearCache();
161
-        $this->loader->reset();
162
-    }
163
-
164
-
165
-    /**
166
-     * unsets and detaches ALL objects from the cache
167
-     *
168
-     * @since 4.9.62.p
169
-     */
170
-    public function clearCache()
171
-    {
172
-        $this->cache->trashAndDetachAll();
173
-    }
20
+	/**
21
+	 * @var string $identifier
22
+	 */
23
+	protected $identifier;
24
+
25
+	/**
26
+	 * @var CollectionInterface $cache
27
+	 */
28
+	protected $cache;
29
+
30
+	/**
31
+	 * @var ObjectIdentifier
32
+	 */
33
+	private $object_identifier;
34
+
35
+
36
+	/**
37
+	 * CachingLoader constructor.
38
+	 *
39
+	 * @param LoaderDecoratorInterface $loader
40
+	 * @param CollectionInterface      $cache
41
+	 * @param ObjectIdentifier         $object_identifier
42
+	 * @param string                   $identifier
43
+	 * @throws InvalidDataTypeException
44
+	 */
45
+	public function __construct(
46
+		LoaderDecoratorInterface $loader,
47
+		CollectionInterface $cache,
48
+		ObjectIdentifier $object_identifier,
49
+		$identifier = ''
50
+	) {
51
+		parent::__construct($loader);
52
+		$this->cache       = $cache;
53
+		$this->object_identifier = $object_identifier;
54
+		$this->setIdentifier($identifier);
55
+		if ($this->identifier !== '') {
56
+			// to only clear this cache, and assuming an identifier has been set, simply do the following:
57
+			// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__IDENTIFIER');
58
+			// where "IDENTIFIER" = the string that was set during construction
59
+			add_action(
60
+				"AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache__{$identifier}",
61
+				array($this, 'reset')
62
+			);
63
+		}
64
+		// to clear ALL caches, simply do the following:
65
+		// do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache');
66
+		add_action(
67
+			'AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache',
68
+			array($this, 'reset')
69
+		);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @return string
75
+	 */
76
+	public function identifier()
77
+	{
78
+		return $this->identifier;
79
+	}
80
+
81
+
82
+	/**
83
+	 * @param string $identifier
84
+	 * @throws InvalidDataTypeException
85
+	 */
86
+	private function setIdentifier($identifier)
87
+	{
88
+		if (! is_string($identifier)) {
89
+			throw new InvalidDataTypeException('$identifier', $identifier, 'string');
90
+		}
91
+		$this->identifier = $identifier;
92
+	}
93
+
94
+
95
+	/**
96
+	 * @param FullyQualifiedName|string $fqcn
97
+	 * @param mixed                     $object
98
+	 * @param array                     $arguments
99
+	 * @return bool
100
+	 * @throws InvalidArgumentException
101
+	 */
102
+	public function share($fqcn, $object, array $arguments = array())
103
+	{
104
+		if ($object instanceof $fqcn) {
105
+			return $this->cache->add(
106
+				$object,
107
+				$this->object_identifier->getIdentifier($fqcn, $arguments)
108
+			);
109
+		}
110
+		throw new InvalidArgumentException(
111
+			sprintf(
112
+				esc_html__(
113
+					'The supplied class name "%1$s" must match the class of the supplied object.',
114
+					'event_espresso'
115
+				),
116
+				$fqcn
117
+			)
118
+		);
119
+	}
120
+
121
+
122
+	/**
123
+	 * @param FullyQualifiedName|string $fqcn
124
+	 * @param array                     $arguments
125
+	 * @param bool                      $shared
126
+	 * @param array                     $interfaces
127
+	 * @return mixed
128
+	 */
129
+	public function load($fqcn, $arguments = array(), $shared = true, array $interfaces = array())
130
+	{
131
+		$fqcn = ltrim($fqcn, '\\');
132
+		// caching can be turned off via the following code:
133
+		// add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true');
134
+		if (apply_filters(
135
+			'FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache',
136
+			false,
137
+			$this
138
+		)) {
139
+			// even though $shared might be true, caching could be bypassed for whatever reason,
140
+			// so we don't want the core loader to cache anything, therefore caching is turned off
141
+			return $this->loader->load($fqcn, $arguments, false);
142
+		}
143
+		$object_identifier = $this->object_identifier->getIdentifier($fqcn, $arguments);
144
+		if ($this->cache->has($object_identifier)) {
145
+			return $this->cache->get($object_identifier);
146
+		}
147
+		$object = $this->loader->load($fqcn, $arguments, $shared);
148
+		if ($object instanceof $fqcn) {
149
+			$this->cache->add($object, $object_identifier);
150
+		}
151
+		return $object;
152
+	}
153
+
154
+
155
+	/**
156
+	 * empties cache and calls reset() on loader if method exists
157
+	 */
158
+	public function reset()
159
+	{
160
+		$this->clearCache();
161
+		$this->loader->reset();
162
+	}
163
+
164
+
165
+	/**
166
+	 * unsets and detaches ALL objects from the cache
167
+	 *
168
+	 * @since 4.9.62.p
169
+	 */
170
+	public function clearCache()
171
+	{
172
+		$this->cache->trashAndDetachAll();
173
+	}
174 174
 }
Please login to merge, or discard this patch.
core/bootstrap_espresso.php 2 patches
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -6,22 +6,22 @@  discard block
 block discarded – undo
6 6
  */
7 7
 function espresso_load_error_handling()
8 8
 {
9
-    static $error_handling_loaded = false;
10
-    if ($error_handling_loaded) {
11
-        return;
12
-    }
13
-    // load debugging tools
14
-    if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
15
-        require_once EE_HELPERS . 'EEH_Debug_Tools.helper.php';
16
-        \EEH_Debug_Tools::instance();
17
-    }
18
-    // load error handling
19
-    if (is_readable(EE_CORE . 'EE_Error.core.php')) {
20
-        require_once EE_CORE . 'EE_Error.core.php';
21
-    } else {
22
-        wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
23
-    }
24
-    $error_handling_loaded = true;
9
+	static $error_handling_loaded = false;
10
+	if ($error_handling_loaded) {
11
+		return;
12
+	}
13
+	// load debugging tools
14
+	if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
15
+		require_once EE_HELPERS . 'EEH_Debug_Tools.helper.php';
16
+		\EEH_Debug_Tools::instance();
17
+	}
18
+	// load error handling
19
+	if (is_readable(EE_CORE . 'EE_Error.core.php')) {
20
+		require_once EE_CORE . 'EE_Error.core.php';
21
+	} else {
22
+		wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
23
+	}
24
+	$error_handling_loaded = true;
25 25
 }
26 26
 
27 27
 
@@ -35,19 +35,19 @@  discard block
 block discarded – undo
35 35
  */
36 36
 function espresso_load_required($classname, $full_path_to_file)
37 37
 {
38
-    if (is_readable($full_path_to_file)) {
39
-        require_once $full_path_to_file;
40
-    } else {
41
-        throw new \EE_Error(
42
-            sprintf(
43
-                esc_html__(
44
-                    'The %s class file could not be located or is not readable due to file permissions.',
45
-                    'event_espresso'
46
-                ),
47
-                $classname
48
-            )
49
-        );
50
-    }
38
+	if (is_readable($full_path_to_file)) {
39
+		require_once $full_path_to_file;
40
+	} else {
41
+		throw new \EE_Error(
42
+			sprintf(
43
+				esc_html__(
44
+					'The %s class file could not be located or is not readable due to file permissions.',
45
+					'event_espresso'
46
+				),
47
+				$classname
48
+			)
49
+		);
50
+	}
51 51
 }
52 52
 
53 53
 
@@ -66,43 +66,43 @@  discard block
 block discarded – undo
66 66
  */
67 67
 function bootstrap_espresso()
68 68
 {
69
-    require_once __DIR__ . '/espresso_definitions.php';
70
-    try {
71
-        espresso_load_error_handling();
72
-        espresso_load_required(
73
-            'EEH_Base',
74
-            EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
75
-        );
76
-        espresso_load_required(
77
-            'EEH_File',
78
-            EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
79
-        );
80
-        espresso_load_required(
81
-            'EEH_File',
82
-            EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
83
-        );
84
-        espresso_load_required(
85
-            'EEH_Array',
86
-            EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
87
-        );
88
-        espresso_load_required(
89
-            'EE_Base',
90
-            EE_CORE . 'EE_Base.core.php'
91
-        );
92
-        // instantiate and configure PSR4 autoloader
93
-        espresso_load_required(
94
-            'Psr4Autoloader',
95
-            EE_CORE . 'Psr4Autoloader.php'
96
-        );
97
-        espresso_load_required(
98
-            'EE_Psr4AutoloaderInit',
99
-            EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
100
-        );
101
-        $AutoloaderInit = new EE_Psr4AutoloaderInit();
102
-        $AutoloaderInit->initializeAutoloader();
103
-        new EventEspresso\core\services\bootstrap\BootstrapCore();
104
-    } catch (Exception $e) {
105
-        require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
106
-        new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
107
-    }
69
+	require_once __DIR__ . '/espresso_definitions.php';
70
+	try {
71
+		espresso_load_error_handling();
72
+		espresso_load_required(
73
+			'EEH_Base',
74
+			EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
75
+		);
76
+		espresso_load_required(
77
+			'EEH_File',
78
+			EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
79
+		);
80
+		espresso_load_required(
81
+			'EEH_File',
82
+			EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
83
+		);
84
+		espresso_load_required(
85
+			'EEH_Array',
86
+			EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
87
+		);
88
+		espresso_load_required(
89
+			'EE_Base',
90
+			EE_CORE . 'EE_Base.core.php'
91
+		);
92
+		// instantiate and configure PSR4 autoloader
93
+		espresso_load_required(
94
+			'Psr4Autoloader',
95
+			EE_CORE . 'Psr4Autoloader.php'
96
+		);
97
+		espresso_load_required(
98
+			'EE_Psr4AutoloaderInit',
99
+			EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
100
+		);
101
+		$AutoloaderInit = new EE_Psr4AutoloaderInit();
102
+		$AutoloaderInit->initializeAutoloader();
103
+		new EventEspresso\core\services\bootstrap\BootstrapCore();
104
+	} catch (Exception $e) {
105
+		require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
106
+		new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
107
+	}
108 108
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -11,13 +11,13 @@  discard block
 block discarded – undo
11 11
         return;
12 12
     }
13 13
     // load debugging tools
14
-    if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
15
-        require_once EE_HELPERS . 'EEH_Debug_Tools.helper.php';
14
+    if (WP_DEBUG === true && is_readable(EE_HELPERS.'EEH_Debug_Tools.helper.php')) {
15
+        require_once EE_HELPERS.'EEH_Debug_Tools.helper.php';
16 16
         \EEH_Debug_Tools::instance();
17 17
     }
18 18
     // load error handling
19
-    if (is_readable(EE_CORE . 'EE_Error.core.php')) {
20
-        require_once EE_CORE . 'EE_Error.core.php';
19
+    if (is_readable(EE_CORE.'EE_Error.core.php')) {
20
+        require_once EE_CORE.'EE_Error.core.php';
21 21
     } else {
22 22
         wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
23 23
     }
@@ -66,43 +66,43 @@  discard block
 block discarded – undo
66 66
  */
67 67
 function bootstrap_espresso()
68 68
 {
69
-    require_once __DIR__ . '/espresso_definitions.php';
69
+    require_once __DIR__.'/espresso_definitions.php';
70 70
     try {
71 71
         espresso_load_error_handling();
72 72
         espresso_load_required(
73 73
             'EEH_Base',
74
-            EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php'
74
+            EE_CORE.'helpers'.DS.'EEH_Base.helper.php'
75 75
         );
76 76
         espresso_load_required(
77 77
             'EEH_File',
78
-            EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php'
78
+            EE_CORE.'interfaces'.DS.'EEHI_File.interface.php'
79 79
         );
80 80
         espresso_load_required(
81 81
             'EEH_File',
82
-            EE_CORE . 'helpers' . DS . 'EEH_File.helper.php'
82
+            EE_CORE.'helpers'.DS.'EEH_File.helper.php'
83 83
         );
84 84
         espresso_load_required(
85 85
             'EEH_Array',
86
-            EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php'
86
+            EE_CORE.'helpers'.DS.'EEH_Array.helper.php'
87 87
         );
88 88
         espresso_load_required(
89 89
             'EE_Base',
90
-            EE_CORE . 'EE_Base.core.php'
90
+            EE_CORE.'EE_Base.core.php'
91 91
         );
92 92
         // instantiate and configure PSR4 autoloader
93 93
         espresso_load_required(
94 94
             'Psr4Autoloader',
95
-            EE_CORE . 'Psr4Autoloader.php'
95
+            EE_CORE.'Psr4Autoloader.php'
96 96
         );
97 97
         espresso_load_required(
98 98
             'EE_Psr4AutoloaderInit',
99
-            EE_CORE . 'EE_Psr4AutoloaderInit.core.php'
99
+            EE_CORE.'EE_Psr4AutoloaderInit.core.php'
100 100
         );
101 101
         $AutoloaderInit = new EE_Psr4AutoloaderInit();
102 102
         $AutoloaderInit->initializeAutoloader();
103 103
         new EventEspresso\core\services\bootstrap\BootstrapCore();
104 104
     } catch (Exception $e) {
105
-        require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php';
105
+        require_once EE_CORE.'exceptions'.DS.'ExceptionStackTraceDisplay.php';
106 106
         new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e);
107 107
     }
108 108
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
38 38
  * @since           4.0
39 39
  */
40 40
 if (function_exists('espresso_version')) {
41
-    if (! function_exists('espresso_duplicate_plugin_error')) {
42
-        /**
43
-         *    espresso_duplicate_plugin_error
44
-         *    displays if more than one version of EE is activated at the same time
45
-         */
46
-        function espresso_duplicate_plugin_error()
47
-        {
48
-            ?>
41
+	if (! function_exists('espresso_duplicate_plugin_error')) {
42
+		/**
43
+		 *    espresso_duplicate_plugin_error
44
+		 *    displays if more than one version of EE is activated at the same time
45
+		 */
46
+		function espresso_duplicate_plugin_error()
47
+		{
48
+			?>
49 49
             <div class="error">
50 50
                 <p>
51 51
                     <?php
52
-                    echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                    ); ?>
52
+					echo esc_html__(
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+					); ?>
56 56
                 </p>
57 57
             </div>
58 58
             <?php
59
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-        }
61
-    }
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
59
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+		}
61
+	}
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.4.0');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.66.rc.020');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.66.rc.020');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.