Passed
Push — v3.0 ( 850008...ceae39 )
by Raza
09:35
created

Helpers::addTaxes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 8
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 $taxes;
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 ($this->return_url && $this->cancel_url) {
99
            $body['application_context'] = [
100
                'return_url' => $this->return_url,
101
                'cancel_url' => $this->cancel_url,
102
            ];
103
        }
104
105
        if (isset($this->taxes)) {
106
            $body['taxes'] = $this->taxes;
107
        }
108
109
        $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

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

284
                'currency_code' => $this->/** @scrutinizer ignore-call */ getCurrency(),
Loading history...
285
            ],
286
        ];
287
288
        if (empty($this->trial_pricing)) {
289
            $plan_sequence = 1;
290
        } else {
291
            $plan_sequence = 2;
292
        }
293
294
        return [
295
            'frequency' => [
296
                'interval_unit'  => $interval_unit,
297
                'interval_count' => $interval_count,
298
            ],
299
            'tenure_type'    => ($trial === true) ? 'TRIAL' : 'REGULAR',
300
            'sequence'       => ($trial === true) ? 1 : $plan_sequence,
301
            'total_cycles'   => ($trial === true) ? 1 : 0,
302
            'pricing_scheme' => $pricing_scheme,
303
        ];
304
    }
305
306
    /**
307
     * Create a product for a subscription's billing plan.
308
     *
309
     * @param string $name
310
     * @param string $description
311
     * @param string $type
312
     * @param string $category
313
     *
314
     * @throws Throwable
315
     *
316
     * @return \Srmklive\PayPal\Services\PayPal
317
     */
318
    public function addProduct(string $name, string $description, string $type, string $category): \Srmklive\PayPal\Services\PayPal
319
    {
320
        if (isset($this->product)) {
321
            return $this;
322
        }
323
324
        $request_id = Str::random();
325
326
        $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

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

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