Completed
Push — master ( fc9960...d78316 )
by Raza
01:34
created

ExpressCheckout::setCartItems()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 3
nc 1
nop 1
1
<?php
2
3
namespace Srmklive\PayPal\Services;
4
5
use Illuminate\Support\Collection;
6
use Srmklive\PayPal\Traits\PayPalRequest as PayPalAPIRequest;
7
use Srmklive\PayPal\Traits\PayPalTransactions;
8
use Srmklive\PayPal\Traits\RecurringProfiles;
9
10
class ExpressCheckout
11
{
12
    // Integrate PayPal Request trait
13
    use PayPalAPIRequest, PayPalTransactions, RecurringProfiles;
14
15
    /**
16
     * ExpressCheckout constructor.
17
     *
18
     * @param array $config
19
     *
20
     * @throws \Exception
21
     */
22
    public function __construct(array $config = [])
23
    {
24
        // Setting PayPal API Credentials
25
        $this->setConfig($config);
26
27
        $this->httpBodyParam = 'form_params';
28
29
        $this->options = [];
30
    }
31
32
    /**
33
     * Set ExpressCheckout API endpoints & options.
34
     *
35
     * @param array $credentials
36
     *
37
     * @return void
38
     */
39
    public function setExpressCheckoutOptions($credentials)
40
    {
41
        // Setting API Endpoints
42
        if ($this->mode === 'sandbox') {
43
            $this->config['api_url'] = !empty($this->config['secret']) ?
44
                'https://api-3t.sandbox.paypal.com/nvp' : 'https://api.sandbox.paypal.com/nvp';
45
46
            $this->config['gateway_url'] = 'https://www.sandbox.paypal.com';
47
            $this->config['ipn_url'] = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';
48 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
49
            $this->config['api_url'] = !empty($this->config['secret']) ?
50
                'https://api-3t.paypal.com/nvp' : 'https://api.paypal.com/nvp';
51
52
            $this->config['gateway_url'] = 'https://www.paypal.com';
53
            $this->config['ipn_url'] = 'https://ipnpb.paypal.com/cgi-bin/webscr';
54
        }
55
56
        // Adding params outside sandbox / live array
57
        $this->config['payment_action'] = $credentials['payment_action'];
58
        $this->config['notify_url'] = $credentials['notify_url'];
59
        $this->config['locale'] = $credentials['locale'];
60
    }
61
62
    /**
63
     * Set cart item details for PayPal.
64
     *
65
     * @param array $items
66
     *
67
     * @return \Illuminate\Support\Collection
68
     */
69
    protected function setCartItems($items)
70
    {
71
        return (new Collection($items))->map(function ($item, $num) {
72
            return [
73
                'L_PAYMENTREQUEST_0_NAME'.$num  => $item['name'],
74
                'L_PAYMENTREQUEST_0_AMT'.$num   => $item['price'],
75
                'L_PAYMENTREQUEST_0_DESC'.$num  => isset($item['desc']) ? $item['desc'] : null,
76
                'L_PAYMENTREQUEST_0_QTY'.$num   => isset($item['qty']) ? $item['qty'] : 1,
77
            ];
78
        })->flatMap(function ($value) {
79
            return $value;
80
        });
81
    }
82
83
    /**
84
     * Set Recurring payments details for SetExpressCheckout API call.
85
     *
86
     * @param array $data
87
     * @param bool  $subscription
88
     */
89
    protected function setExpressCheckoutRecurringPaymentConfig($data, $subscription = false)
90
    {
91
        $billingType = $this->billingType;
92
93
        // Overwrite billing type if $subscription flag is enabled
94
        if ($subscription) {
95
            $billingType = 'RecurringPayments';
96
        }
97
98
        // Send L_BILLINGTYPE0 and L_BILLINGAGREEMENTDESCRIPTION0 only if there is billing type
99
        if (isset($billingType)) {
100
            $this->post = $this->post->merge([
101
                'L_BILLINGTYPE0'                 => $billingType,
102
                'L_BILLINGAGREEMENTDESCRIPTION0' => !empty($data['subscription_desc']) ?
103
                    $data['subscription_desc'] : $data['invoice_description'],
104
            ]);
105
        }
106
    }
107
108
    /**
109
     * Set item subtotal if available.
110
     *
111
     * @param array $data
112
     */
113
    protected function setItemSubTotal($data)
114
    {
115
        $this->subtotal = isset($data['subtotal']) ? $data['subtotal'] : $data['total'];
116
    }
117
118
    /**
119
     * Set shipping amount if available.
120
     *
121
     * @param array $data
122
     */
123
    protected function setShippingAmount($data)
124
    {
125
        if (isset($data['shipping'])) {
126
            $this->post = $this->post->merge([
127
                'PAYMENTREQUEST_0_SHIPPINGAMT' => $data['shipping'],
128
            ]);
129
        }
130
    }
131
132
    /**
133
     * Set tax amount if available.
134
     *
135
     * @param array $data
136
     */
137
    protected function setTaxAmount($data)
138
    {
139
        if (isset($data['tax'])) {
140
            $this->post = $this->post->merge([
141
                'PAYMENTREQUEST_0_TAXAMT' => $data['tax'],
142
            ]);
143
        }
144
    }
145
146
    /**
147
     * Set shipping discount if available.
148
     *
149
     * @param array $data
150
     */
151
    protected function setShippingDiscount($data)
152
    {
153
        if (isset($data['shipping_discount'])) {
154
            if ($data['shipping_discount'] > 0) {
155
                $data['shipping_discount'] *= -1;
156
            }
157
158
            $this->post = $this->post->merge([
159
                'PAYMENTREQUEST_0_SHIPDISCAMT' => $data['shipping_discount'],
160
                'PAYMENTREQUEST_0_AMT'         => round($data['total'] + $data['shipping_discount'], 2),
161
            ]);
162
        }
163
    }
164
165
    /**
166
     * Perform a SetExpressCheckout API call on PayPal.
167
     *
168
     * @param array $data
169
     * @param bool  $subscription
170
     *
171
     * @throws \Exception
172
     *
173
     * @return array|\Psr\Http\Message\StreamInterface
174
     */
175
    public function setExpressCheckout($data, $subscription = false)
176
    {
177
        $this->setItemSubTotal($data);
178
179
        $this->post = $this->setCartItems($data['items'])->merge([
180
            'PAYMENTREQUEST_0_ITEMAMT'       => $this->subtotal,
181
            'PAYMENTREQUEST_0_AMT'           => $data['total'],
182
            'PAYMENTREQUEST_0_PAYMENTACTION' => $this->paymentAction,
183
            'PAYMENTREQUEST_0_CURRENCYCODE'  => $this->currency,
184
            'PAYMENTREQUEST_0_DESC'          => $data['invoice_description'],
185
            'PAYMENTREQUEST_0_INVNUM'        => $data['invoice_id'],
186
            'NOSHIPPING'                     => 1,
187
            'RETURNURL'                      => $data['return_url'],
188
            'CANCELURL'                      => $data['cancel_url'],
189
            'LOCALE'                         => $this->locale,
190
        ]);
191
192
        $this->setShippingAmount($data);
193
194
        $this->setShippingDiscount($data);
195
196
        $this->setTaxAmount($data);
197
198
        $this->setExpressCheckoutRecurringPaymentConfig($data, $subscription);
199
200
        $response = $this->doPayPalRequest('SetExpressCheckout');
201
202
        return collect($response)->merge([
203
            'paypal_link' => !empty($response['TOKEN']) ? $this->config['gateway_url'].'/webscr?cmd=_express-checkout&token='.$response['TOKEN'] : null,
204
        ])->toArray();
205
    }
206
207
    /**
208
     * Perform a GetExpressCheckoutDetails API call on PayPal.
209
     *
210
     * @param string $token
211
     *
212
     * @throws \Exception
213
     *
214
     * @return array|\Psr\Http\Message\StreamInterface
215
     */
216
    public function getExpressCheckoutDetails($token)
217
    {
218
        $this->setRequestData([
219
            'TOKEN' => $token,
220
        ]);
221
222
        return $this->doPayPalRequest('GetExpressCheckoutDetails');
223
    }
224
225
    /**
226
     * Perform DoExpressCheckoutPayment API call on PayPal.
227
     *
228
     * @param array  $data
229
     * @param string $token
230
     * @param string $payerid
231
     *
232
     * @throws \Exception
233
     *
234
     * @return array|\Psr\Http\Message\StreamInterface
235
     */
236
    public function doExpressCheckoutPayment($data, $token, $payerid)
237
    {
238
        $this->setItemSubTotal($data);
239
240
        $this->post = $this->setCartItems($data['items'])->merge([
241
            'TOKEN'                          => $token,
242
            'PAYERID'                        => $payerid,
243
            'PAYMENTREQUEST_0_ITEMAMT'       => $this->subtotal,
244
            'PAYMENTREQUEST_0_AMT'           => $data['total'],
245
            'PAYMENTREQUEST_0_PAYMENTACTION' => !empty($this->config['payment_action']) ? $this->config['payment_action'] : 'Sale',
246
            'PAYMENTREQUEST_0_CURRENCYCODE'  => $this->currency,
247
            'PAYMENTREQUEST_0_DESC'          => $data['invoice_description'],
248
            'PAYMENTREQUEST_0_INVNUM'        => $data['invoice_id'],
249
            'PAYMENTREQUEST_0_NOTIFYURL'     => $this->notifyUrl,
250
        ]);
251
252
        $this->setShippingAmount($data);
253
254
        return $this->doPayPalRequest('DoExpressCheckoutPayment');
255
    }
256
257
    /**
258
     * Perform a DoAuthorization API call on PayPal.
259
     *
260
     * @param string $authorization_id Transaction ID
261
     * @param float  $amount           Amount to capture
262
     * @param array  $data             Optional request fields
263
     *
264
     * @throws \Exception
265
     *
266
     * @return array|\Psr\Http\Message\StreamInterface
267
     */
268
    public function doAuthorization($authorization_id, $amount, $data = [])
269
    {
270
        $this->setRequestData(
271
            array_merge($data, [
272
                'AUTHORIZATIONID' => $authorization_id,
273
                'AMT'             => $amount,
274
            ])
275
        );
276
277
        return $this->doPayPalRequest('DoAuthorization');
278
    }
279
280
    /**
281
     * Perform a DoCapture API call on PayPal.
282
     *
283
     * @param string $authorization_id Transaction ID
284
     * @param float  $amount           Amount to capture
285
     * @param string $complete         Indicates whether or not this is the last capture.
286
     * @param array  $data             Optional request fields
287
     *
288
     * @throws \Exception
289
     *
290
     * @return array|\Psr\Http\Message\StreamInterface
291
     */
292
    public function doCapture($authorization_id, $amount, $complete = 'Complete', $data = [])
293
    {
294
        $this->setRequestData(
295
            array_merge($data, [
296
                'AUTHORIZATIONID' => $authorization_id,
297
                'AMT'             => $amount,
298
                'COMPLETETYPE'    => $complete,
299
                'CURRENCYCODE'    => $this->currency,
300
            ])
301
        );
302
303
        return $this->doPayPalRequest('DoCapture');
304
    }
305
306
    /**
307
     * Perform a DoReauthorization API call on PayPal to reauthorize an existing authorization transaction.
308
     *
309
     * @param string $authorization_id
310
     * @param float  $amount
311
     * @param array  $data
312
     *
313
     * @throws \Exception
314
     *
315
     * @return array|\Psr\Http\Message\StreamInterface
316
     */
317
    public function doReAuthorization($authorization_id, $amount, $data = [])
318
    {
319
        $this->setRequestData(
320
            array_merge($data, [
321
                'AUTHORIZATIONID' => $authorization_id,
322
                'AMOUNT'          => $amount,
323
            ])
324
        );
325
326
        return $this->doPayPalRequest('DoReauthorization');
327
    }
328
329
    /**
330
     * Perform a DoVoid API call on PayPal.
331
     *
332
     * @param string $authorization_id Transaction ID
333
     * @param array  $data             Optional request fields
334
     *
335
     * @throws \Exception
336
     *
337
     * @return array|\Psr\Http\Message\StreamInterface
338
     */
339
    public function doVoid($authorization_id, $data = [])
340
    {
341
        $this->setRequestData(
342
            array_merge($data, [
343
                'AUTHORIZATIONID' => $authorization_id,
344
            ])
345
        );
346
347
        return $this->doPayPalRequest('DoVoid');
348
    }
349
350
    /**
351
     * Perform a CreateBillingAgreement API call on PayPal.
352
     *
353
     * @param string $token
354
     *
355
     * @throws \Exception
356
     *
357
     * @return array|\Psr\Http\Message\StreamInterface
358
     */
359
    public function createBillingAgreement($token)
360
    {
361
        $this->setRequestData([
362
            'TOKEN' => $token,
363
        ]);
364
365
        return $this->doPayPalRequest('CreateBillingAgreement');
366
    }
367
368
    /**
369
     * Perform a CreateRecurringPaymentsProfile API call on PayPal.
370
     *
371
     * @param array  $data
372
     * @param string $token
373
     *
374
     * @throws \Exception
375
     *
376
     * @return array|\Psr\Http\Message\StreamInterface
377
     */
378
    public function createRecurringPaymentsProfile($data, $token)
379
    {
380
        $this->post = $this->setRequestData($data)->merge([
381
            'TOKEN' => $token,
382
        ]);
383
384
        return $this->doPayPalRequest('CreateRecurringPaymentsProfile');
385
    }
386
387
    /**
388
     * Perform a GetRecurringPaymentsProfileDetails API call on PayPal.
389
     *
390
     * @param string $id
391
     *
392
     * @throws \Exception
393
     *
394
     * @return array|\Psr\Http\Message\StreamInterface
395
     */
396
    public function getRecurringPaymentsProfileDetails($id)
397
    {
398
        $this->setRequestData([
399
            'PROFILEID' => $id,
400
        ]);
401
402
        return $this->doPayPalRequest('GetRecurringPaymentsProfileDetails');
403
    }
404
405
    /**
406
     * Perform a UpdateRecurringPaymentsProfile API call on PayPal.
407
     *
408
     * @param array  $data
409
     * @param string $id
410
     *
411
     * @throws \Exception
412
     *
413
     * @return array|\Psr\Http\Message\StreamInterface
414
     */
415
    public function updateRecurringPaymentsProfile($data, $id)
416
    {
417
        $this->post = $this->setRequestData($data)->merge([
418
            'PROFILEID' => $id,
419
        ]);
420
421
        return $this->doPayPalRequest('UpdateRecurringPaymentsProfile');
422
    }
423
424
    /**
425
     * Change Recurring payment profile status on PayPal.
426
     *
427
     * @param string $id
428
     * @param string $status
429
     *
430
     * @throws \Exception
431
     *
432
     * @return array|\Psr\Http\Message\StreamInterface
433
     */
434
    protected function manageRecurringPaymentsProfileStatus($id, $status)
435
    {
436
        $this->setRequestData([
437
            'PROFILEID' => $id,
438
            'ACTION'    => $status,
439
        ]);
440
441
        return $this->doPayPalRequest('ManageRecurringPaymentsProfileStatus');
442
    }
443
444
    /**
445
     * Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to cancel a RecurringPaymentsProfile.
446
     *
447
     * @param string $id
448
     *
449
     * @throws \Exception
450
     *
451
     * @return array|\Psr\Http\Message\StreamInterface
452
     */
453
    public function cancelRecurringPaymentsProfile($id)
454
    {
455
        return $this->manageRecurringPaymentsProfileStatus($id, 'Cancel');
456
    }
457
458
    /**
459
     * Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to suspend a RecurringPaymentsProfile.
460
     *
461
     * @param string $id
462
     *
463
     * @throws \Exception
464
     *
465
     * @return array|\Psr\Http\Message\StreamInterface
466
     */
467
    public function suspendRecurringPaymentsProfile($id)
468
    {
469
        return $this->manageRecurringPaymentsProfileStatus($id, 'Suspend');
470
    }
471
472
    /**
473
     * Perform a ManageRecurringPaymentsProfileStatus API call on PayPal to reactivate a RecurringPaymentsProfile.
474
     *
475
     * @param string $id
476
     *
477
     * @throws \Exception
478
     *
479
     * @return array|\Psr\Http\Message\StreamInterface
480
     */
481
    public function reactivateRecurringPaymentsProfile($id)
482
    {
483
        return $this->manageRecurringPaymentsProfileStatus($id, 'Reactivate');
484
    }
485
}
486