Passed
Pull Request — v3.0 (#603)
by
unknown
13:30
created

Helpers::addSetupFee()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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