Passed
Push — v3.0 ( b3ac55...dc680c )
by Raza
03:58 queued 01:40
created

Helpers::addCustomId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
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 array
48
     */
49
    protected $taxes;
50
51
    /**
52
     * @var string
53
     */
54
    protected $custom_id;
55
56
    /**
57
     * Setup a subscription.
58
     *
59
     * @param string $customer_name
60
     * @param string $customer_email
61
     * @param string $start_date
62
     *
63
     * @throws Throwable
64
     *
65
     * @return array|\Psr\Http\Message\StreamInterface|string
66
     */
67
    public function setupSubscription(string $customer_name, string $customer_email, string $start_date = '')
68
    {
69
        $start_date = !empty($start_date) ? Carbon::parse($start_date)->toIso8601String() : Carbon::now()->toIso8601String();
70
71
        $body = [
72
            'plan_id'    => $this->billing_plan['id'],
73
            'start_time' => $start_date,
74
            'quantity'   => 1,
75
            'subscriber' => [
76
                'name'          => [
77
                    'given_name' => $customer_name,
78
                ],
79
                'email_address' => $customer_email,
80
            ],
81
        ];
82
83
        if ($this->has_setup_fee) {
84
            $body['plan'] = [
85
                'payment_preferences' => $this->payment_preferences,
86
            ];
87
        }
88
89
        if (isset($this->shipping_address)) {
90
            $body['subscriber']['shipping_address'] = $this->shipping_address;
91
        }
92
93
        if (isset($this->experience_context)) {
94
            $body['application_context'] = $this->experience_context;
95
        }
96
97
        if (isset($this->taxes)) {
98
            $body['taxes'] = $this->taxes;
99
        }
100
101
        if (isset($this->custom_id)) {
102
            $body['custom_id'] = $this->custom_id;
103
        }
104
105
        $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

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

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

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

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