Passed
Pull Request — v3.0 (#554)
by
unknown
02:01
created

Helpers::setApplicationContext()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
c 1
b 0
f 1
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Srmklive\PayPal\Traits\PayPalAPI\Subscriptions;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Str;
7
use Throwable;
8
9
trait Helpers
10
{
11
    /**
12
     * @var array
13
     */
14
    protected $trial_pricing = [];
15
16
    /**
17
     * @var int
18
     */
19
    protected $payment_failure_threshold = 3;
20
21
    /**
22
     * @var array
23
     */
24
    protected $product;
25
26
    /**
27
     * @var array
28
     */
29
    protected $billing_plan;
30
31
    /**
32
     * @var array
33
     */
34
    protected $shipping_address;
35
36
    /**
37
     * @var array
38
     */
39
    protected $payment_preferences;
40
41
    /**
42
     * @var bool
43
     */
44
    protected $has_setup_fee = false;
45
46
    /**
47
     * @var string
48
     */
49
    protected $return_url;
50
51
    /**
52
     * @var string
53
     */
54
    protected $cancel_url;
55
56
    /**
57
     * @var array
58
     */
59
    protected $application_context;
60
61
    /**
62
     * Setup a subscription.
63
     *
64
     * @param string $customer_name
65
     * @param string $customer_email
66
     * @param string $start_date
67
     *
68
     * @throws Throwable
69
     *
70
     * @return array|\Psr\Http\Message\StreamInterface|string
71
     */
72
    public function setupSubscription(string $customer_name, string $customer_email, string $start_date = '')
73
    {
74
        $start_date = !empty($start_date) ? Carbon::parse($start_date)->toIso8601String() : Carbon::now()->toIso8601String();
75
76
        $body = [
77
            'plan_id'    => $this->billing_plan['id'],
78
            'start_time' => $start_date,
79
            'quantity'   => 1,
80
            'subscriber' => [
81
                'name'          => [
82
                    'given_name' => $customer_name,
83
                ],
84
                'email_address' => $customer_email,
85
            ],
86
        ];
87
88
        if ($this->has_setup_fee) {
89
            $body['plan'] = [
90
                'payment_preferences' => $this->payment_preferences,
91
            ];
92
        }
93
94
        if (isset($this->shipping_address)) {
95
            $body['subscriber']['shipping_address'] = $this->shipping_address;
96
        }
97
98
        if (!empty($this->application_context)) {
99
            $body['application_context'] = $this->application_context;
100
        }
101
102
        if ($this->return_url && $this->cancel_url) {
103
            $body['application_context']['return_url'] = $this->return_url;
104
            $body['application_context']['cancel_url'] = $this->cancel_url;
105
        }
106
107
        $subscription = $this->createSubscription($body);
0 ignored issues
show
Bug introduced by
It seems like createSubscription() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
        /** @scrutinizer ignore-call */ 
108
        $subscription = $this->createSubscription($body);
Loading history...
108
109
        unset($this->product);
110
        unset($this->billing_plan);
111
        unset($this->trial_pricing);
112
        unset($this->return_url);
113
        unset($this->cancel_url);
114
        unset($this->application_context);
115
116
        return $subscription;
117
    }
118
119
    /**
120
     * Add a subscription trial pricing tier.
121
     *
122
     * @param string    $interval_type
123
     * @param int       $interval_count
124
     * @param float|int $price
125
     *
126
     * @return \Srmklive\PayPal\Services\PayPal
127
     */
128
    public function addPlanTrialPricing(string $interval_type, int $interval_count, float $price = 0): \Srmklive\PayPal\Services\PayPal
129
    {
130
        $this->trial_pricing = $this->addPlanBillingCycle($interval_type, $interval_count, $price, true);
131
132
        return $this;
133
    }
134
135
    /**
136
     * Create a recurring daily billing plan.
137
     *
138
     * @param string    $name
139
     * @param string    $description
140
     * @param float|int $price
141
     *
142
     * @throws Throwable
143
     *
144
     * @return \Srmklive\PayPal\Services\PayPal
145
     */
146
    public function addDailyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
147
    {
148
        if (isset($this->billing_plan)) {
149
            return $this;
150
        }
151
152
        $plan_pricing = $this->addPlanBillingCycle('DAY', 1, $price);
153
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
154
155
        $this->addBillingPlan($name, $description, $billing_cycles);
156
157
        return $this;
158
    }
159
160
    /**
161
     * Create a recurring weekly billing plan.
162
     *
163
     * @param string    $name
164
     * @param string    $description
165
     * @param float|int $price
166
     *
167
     * @throws Throwable
168
     *
169
     * @return \Srmklive\PayPal\Services\PayPal
170
     */
171
    public function addWeeklyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
172
    {
173
        if (isset($this->billing_plan)) {
174
            return $this;
175
        }
176
177
        $plan_pricing = $this->addPlanBillingCycle('WEEK', 1, $price);
178
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
179
180
        $this->addBillingPlan($name, $description, $billing_cycles);
181
182
        return $this;
183
    }
184
185
    /**
186
     * Create a recurring monthly billing plan.
187
     *
188
     * @param string    $name
189
     * @param string    $description
190
     * @param float|int $price
191
     *
192
     * @throws Throwable
193
     *
194
     * @return \Srmklive\PayPal\Services\PayPal
195
     */
196
    public function addMonthlyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
197
    {
198
        if (isset($this->billing_plan)) {
199
            return $this;
200
        }
201
202
        $plan_pricing = $this->addPlanBillingCycle('MONTH', 1, $price);
203
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
204
205
        $this->addBillingPlan($name, $description, $billing_cycles);
206
207
        return $this;
208
    }
209
210
    /**
211
     * Create a recurring annual billing plan.
212
     *
213
     * @param string    $name
214
     * @param string    $description
215
     * @param float|int $price
216
     *
217
     * @throws Throwable
218
     *
219
     * @return \Srmklive\PayPal\Services\PayPal
220
     */
221
    public function addAnnualPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
222
    {
223
        if (isset($this->billing_plan)) {
224
            return $this;
225
        }
226
227
        $plan_pricing = $this->addPlanBillingCycle('YEAR', 1, $price);
228
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
229
230
        $this->addBillingPlan($name, $description, $billing_cycles);
231
232
        return $this;
233
    }
234
235
    /**
236
     * Create a recurring billing plan with custom intervals.
237
     *
238
     * @param string    $name
239
     * @param string    $description
240
     * @param float|int $price
241
     * @param string    $interval_unit
242
     * @param int       $interval_count
243
     *
244
     * @throws Throwable
245
     *
246
     * @return \Srmklive\PayPal\Services\PayPal
247
     */
248
    public function addCustomPlan(string $name, string $description, float $price, string $interval_unit, int $interval_count): \Srmklive\PayPal\Services\PayPal
249
    {
250
        $billing_intervals = ['DAY', 'WEEK', 'MONTH', 'YEAR'];
251
252
        if (isset($this->billing_plan)) {
253
            return $this;
254
        }
255
256
        if (!in_array($interval_unit, $billing_intervals)) {
257
            throw new \RuntimeException('Billing intervals should either be '.implode(', ', $billing_intervals));
258
        }
259
260
        $plan_pricing = $this->addPlanBillingCycle($interval_unit, $interval_count, $price);
261
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
262
263
        $this->addBillingPlan($name, $description, $billing_cycles);
264
265
        return $this;
266
    }
267
268
    /**
269
     * Add Plan's Billing cycle.
270
     *
271
     * @param string $interval_unit
272
     * @param int    $interval_count
273
     * @param float  $price
274
     * @param bool   $trial
275
     *
276
     * @return array
277
     */
278
    protected function addPlanBillingCycle(string $interval_unit, int $interval_count, float $price, bool $trial = false): array
279
    {
280
        $pricing_scheme = [
281
            'fixed_price' => [
282
                'value'         => $price,
283
                'currency_code' => $this->getCurrency(),
0 ignored issues
show
Bug introduced by
It seems like getCurrency() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

283
                'currency_code' => $this->/** @scrutinizer ignore-call */ getCurrency(),
Loading history...
284
            ],
285
        ];
286
287
        if (empty($this->trial_pricing)) {
288
            $plan_sequence = 1;
289
        } else {
290
            $plan_sequence = 2;
291
        }
292
293
        return [
294
            'frequency' => [
295
                'interval_unit'  => $interval_unit,
296
                'interval_count' => $interval_count,
297
            ],
298
            'tenure_type'    => ($trial === true) ? 'TRIAL' : 'REGULAR',
299
            'sequence'       => ($trial === true) ? 1 : $plan_sequence,
300
            'total_cycles'   => ($trial === true) ? 1 : 0,
301
            'pricing_scheme' => $pricing_scheme,
302
        ];
303
    }
304
305
    /**
306
     * Create a product for a subscription's billing plan.
307
     *
308
     * @param string $name
309
     * @param string $description
310
     * @param string $type
311
     * @param string $category
312
     *
313
     * @throws Throwable
314
     *
315
     * @return \Srmklive\PayPal\Services\PayPal
316
     */
317
    public function addProduct(string $name, string $description, string $type, string $category): \Srmklive\PayPal\Services\PayPal
318
    {
319
        if (isset($this->product)) {
320
            return $this;
321
        }
322
323
        $request_id = Str::random();
324
325
        $this->product = $this->createProduct([
0 ignored issues
show
Bug introduced by
It seems like createProduct() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

325
        /** @scrutinizer ignore-call */ 
326
        $this->product = $this->createProduct([
Loading history...
326
            'name'          => $name,
327
            'description'   => $description,
328
            'type'          => $type,
329
            'category'      => $category,
330
        ], $request_id);
331
332
        return $this;
333
    }
334
335
    /**
336
     * Add subscription's billing plan's product by ID.
337
     *
338
     * @param string $product_id
339
     *
340
     * @return \Srmklive\PayPal\Services\PayPal
341
     */
342
    public function addProductById(string $product_id): \Srmklive\PayPal\Services\PayPal
343
    {
344
        $this->product = [
345
            'id' => $product_id,
346
        ];
347
348
        return $this;
349
    }
350
351
    /**
352
     * Add subscription's billing plan by ID.
353
     *
354
     * @param string $plan_id
355
     *
356
     * @return \Srmklive\PayPal\Services\PayPal
357
     */
358
    public function addBillingPlanById(string $plan_id): \Srmklive\PayPal\Services\PayPal
359
    {
360
        $this->billing_plan = [
361
            'id' => $plan_id,
362
        ];
363
364
        return $this;
365
    }
366
367
    /**
368
     * Create a product for a subscription's billing plan.
369
     *
370
     * @param string $name
371
     * @param string $description
372
     * @param array  $billing_cycles
373
     *
374
     * @throws Throwable
375
     *
376
     * @return void
377
     */
378
    protected function addBillingPlan(string $name, string $description, array $billing_cycles): void
379
    {
380
        $request_id = Str::random();
381
382
        $plan_params = [
383
            'product_id'          => $this->product['id'],
384
            'name'                => $name,
385
            'description'         => $description,
386
            'status'              => 'ACTIVE',
387
            'billing_cycles'      => $billing_cycles,
388
            'payment_preferences' => [
389
                'auto_bill_outstanding'     => true,
390
                'setup_fee_failure_action'  => 'CONTINUE',
391
                'payment_failure_threshold' => $this->payment_failure_threshold,
392
            ],
393
        ];
394
395
        $this->billing_plan = $this->createPlan($plan_params, $request_id);
0 ignored issues
show
Bug introduced by
It seems like createPlan() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

395
        /** @scrutinizer ignore-call */ 
396
        $this->billing_plan = $this->createPlan($plan_params, $request_id);
Loading history...
396
    }
397
398
    /**
399
     * Set application context.
400
     *
401
     * @param array $data
402
     * @return \Srmklive\PayPal\Services\PayPal
403
     */
404
    public function setApplicationContext(array $data): \Srmklive\PayPal\Services\PayPal
405
    {
406
        $this->application_context = $data;
407
408
        return $this;
409
    }
410
411
    /**
412
     * Set return & cancel urls.
413
     *
414
     * @param string $return_url
415
     * @param string $cancel_url
416
     *
417
     * @return \Srmklive\PayPal\Services\PayPal
418
     */
419
    public function setReturnAndCancelUrl(string $return_url, string $cancel_url): \Srmklive\PayPal\Services\PayPal
420
    {
421
        $this->return_url = $return_url;
422
        $this->cancel_url = $cancel_url;
423
424
        return $this;
425
    }
426
427
    /**
428
     * Set custom failure threshold when adding a subscription.
429
     *
430
     * @param int $threshold
431
     *
432
     * @return \Srmklive\PayPal\Services\PayPal
433
     */
434
    public function addPaymentFailureThreshold(int $threshold): \Srmklive\PayPal\Services\PayPal
435
    {
436
        $this->payment_failure_threshold = $threshold;
437
438
        return $this;
439
    }
440
441
    /**
442
     * Add setup fee when adding a subscription.
443
     *
444
     * @param float $price
445
     *
446
     * @return \Srmklive\PayPal\Services\PayPal
447
     */
448
    public function addSetupFee(float $price): \Srmklive\PayPal\Services\PayPal
449
    {
450
        $this->has_setup_fee = true;
451
        $this->payment_preferences = [
452
            'auto_bill_outstanding'     => true,
453
            'setup_fee'                 => [
454
                'value'         => $price,
455
                'currency_code' => $this->getCurrency(),
456
            ],
457
            'setup_fee_failure_action'  => 'CONTINUE',
458
            'payment_failure_threshold' => $this->payment_failure_threshold,
459
        ];
460
461
        return $this;
462
    }
463
464
    /**
465
     * Add shipping address.
466
     *
467
     * @param string $full_name
468
     * @param string $address_line_1
469
     * @param string $address_line_2
470
     * @param string $admin_area_2
471
     * @param string $admin_area_1
472
     * @param string $postal_code
473
     * @param string $country_code
474
     *
475
     * @return \Srmklive\PayPal\Services\PayPal
476
     */
477
    public function addShippingAddress(string $full_name, string $address_line_1, string $address_line_2, string $admin_area_2, string $admin_area_1, string $postal_code, string $country_code): \Srmklive\PayPal\Services\PayPal
478
    {
479
        $this->shipping_address = [
480
            'name' => [
481
                'full_name' => $full_name,
482
            ],
483
            'address' => [
484
                'address_line_1'  => $address_line_1,
485
                'address_line_2'  => $address_line_2,
486
                'admin_area_2'    => $admin_area_2,
487
                'admin_area_1'    => $admin_area_1,
488
                'postal_code'     => $postal_code,
489
                'country_code'    => $country_code,
490
            ],
491
        ];
492
493
        return $this;
494
    }
495
}
496