Passed
Pull Request — v3.0 (#491)
by
unknown
02:22
created

Helpers::addPlanTrialPricing()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
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
    protected $return_url;
32
33
    protected $cancel_url;
34
35
    /**
36
     * Setup a subscription.
37
     *
38
     * @param string $customer_name
39
     * @param string $customer_email
40
     * @param string $start_date
41
     *
42
     * @throws Throwable
43
     *
44
     * @return array|\Psr\Http\Message\StreamInterface|string
45
     */
46
    public function setupSubscription(string $customer_name, string $customer_email, string $start_date = '')
47
    {
48
        $start_date = isset($start_date) ? Carbon::parse($start_date)->toIso8601String() : Carbon::now()->toIso8601String();
49
50
        $body = [
51
            'plan_id'    => $this->billing_plan['id'],
52
            'start_time' => $start_date,
53
            'quantity'   => 1,
54
            'subscriber' => [
55
                'name'          => [
56
                    'given_name' => $customer_name,
57
                ],
58
                'email_address' => $customer_email,
59
            ],
60
        ];
61
62
        if ($this->return_url && $this->cancel_url) {
63
            $body['application_context'] = [
64
                'return_url' => $this->return_url,
65
                'cancel_url' => $this->cancel_url,
66
            ];
67
        }
68
69
        $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

69
        /** @scrutinizer ignore-call */ 
70
        $subscription = $this->createSubscription($body);
Loading history...
70
71
        unset($this->product);
72
        unset($this->billing_plan);
73
        unset($this->trial_pricing);
74
75
        return $subscription;
76
    }
77
78
    /**
79
     * Add a subscription trial pricing tier.
80
     *
81
     * @param string    $interval_type
82
     * @param int       $interval_count
83
     * @param float|int $price
84
     *
85
     * @return \Srmklive\PayPal\Services\PayPal
86
     */
87
    public function addPlanTrialPricing(string $interval_type, int $interval_count, float $price = 0): \Srmklive\PayPal\Services\PayPal
88
    {
89
        $this->trial_pricing = $this->addPlanBillingCycle($interval_type, $interval_count, $price, true);
90
91
        return $this;
92
    }
93
94
    /**
95
     * Create a recurring daily billing plan.
96
     *
97
     * @param string    $name
98
     * @param string    $description
99
     * @param float|int $price
100
     *
101
     * @throws Throwable
102
     *
103
     * @return \Srmklive\PayPal\Services\PayPal
104
     */
105
    public function addDailyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
106
    {
107
        if (isset($this->billing_plan)) {
108
            return $this;
109
        }
110
111
        $plan_pricing = $this->addPlanBillingCycle('DAY', 1, $price);
112
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
113
114
        $this->addBillingPlan($name, $description, $billing_cycles);
115
116
        return $this;
117
    }
118
119
    /**
120
     * Create a recurring weekly billing plan.
121
     *
122
     * @param string    $name
123
     * @param string    $description
124
     * @param float|int $price
125
     *
126
     * @throws Throwable
127
     *
128
     * @return \Srmklive\PayPal\Services\PayPal
129
     */
130
    public function addWeeklyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
131
    {
132
        if (isset($this->billing_plan)) {
133
            return $this;
134
        }
135
136
        $plan_pricing = $this->addPlanBillingCycle('WEEK', 1, $price);
137
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
138
139
        $this->addBillingPlan($name, $description, $billing_cycles);
140
141
        return $this;
142
    }
143
144
    /**
145
     * Create a recurring monthly billing plan.
146
     *
147
     * @param string    $name
148
     * @param string    $description
149
     * @param float|int $price
150
     *
151
     * @throws Throwable
152
     *
153
     * @return \Srmklive\PayPal\Services\PayPal
154
     */
155
    public function addMonthlyPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
156
    {
157
        if (isset($this->billing_plan)) {
158
            return $this;
159
        }
160
161
        $plan_pricing = $this->addPlanBillingCycle('MONTH', 1, $price);
162
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
163
164
        $this->addBillingPlan($name, $description, $billing_cycles);
165
166
        return $this;
167
    }
168
169
    /**
170
     * Create a recurring annual billing plan.
171
     *
172
     * @param string    $name
173
     * @param string    $description
174
     * @param float|int $price
175
     *
176
     * @throws Throwable
177
     *
178
     * @return \Srmklive\PayPal\Services\PayPal
179
     */
180
    public function addAnnualPlan(string $name, string $description, float $price): \Srmklive\PayPal\Services\PayPal
181
    {
182
        if (isset($this->billing_plan)) {
183
            return $this;
184
        }
185
186
        $plan_pricing = $this->addPlanBillingCycle('YEAR', 1, $price);
187
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
188
189
        $this->addBillingPlan($name, $description, $billing_cycles);
190
191
        return $this;
192
    }
193
194
    /**
195
     * Create a recurring billing plan with custom intervals.
196
     *
197
     * @param string    $name
198
     * @param string    $description
199
     * @param float|int $price
200
     * @param string    $interval_unit
201
     * @param int       $interval_count
202
     *
203
     * @throws Throwable
204
     *
205
     * @return \Srmklive\PayPal\Services\PayPal
206
     */
207
    public function addCustomPlan(string $name, string $description, float $price, string $interval_unit, int $interval_count): \Srmklive\PayPal\Services\PayPal
208
    {
209
        $billing_intervals = ['DAY', 'WEEK', 'MONTH', 'YEAR'];
210
211
        if (isset($this->billing_plan)) {
212
            return $this;
213
        }
214
215
        if (!in_array($interval_unit, $billing_intervals)) {
216
            throw new \RuntimeException('Billing intervals should either be '.implode(', ', $billing_intervals));
217
        }
218
219
        $plan_pricing = $this->addPlanBillingCycle($interval_unit, $interval_count, $price);
220
        $billing_cycles = empty($this->trial_pricing) ? [$plan_pricing] : collect([$this->trial_pricing, $plan_pricing])->filter()->toArray();
221
222
        $this->addBillingPlan($name, $description, $billing_cycles);
223
224
        return $this;
225
    }
226
227
    /**
228
     * Add Plan's Billing cycle.
229
     *
230
     * @param string $interval_unit
231
     * @param int    $interval_count
232
     * @param float  $price
233
     * @param bool   $trial
234
     *
235
     * @return array
236
     */
237
    protected function addPlanBillingCycle(string $interval_unit, int $interval_count, float $price, bool $trial = false): array
238
    {
239
        $pricing_scheme = [
240
            'fixed_price' => [
241
                'value'         => $price,
242
                '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

242
                'currency_code' => $this->/** @scrutinizer ignore-call */ getCurrency(),
Loading history...
243
            ],
244
        ];
245
246
        if (empty($this->trial_pricing)) {
247
            $plan_sequence = 1;
248
        } else {
249
            $plan_sequence = 2;
250
        }
251
252
        return [
253
            'frequency' => [
254
                'interval_unit'  => $interval_unit,
255
                'interval_count' => $interval_count,
256
            ],
257
            'tenure_type'    => ($trial === true) ? 'TRIAL' : 'REGULAR',
258
            'sequence'       => ($trial === true) ? 1 : $plan_sequence,
259
            'total_cycles'   => ($trial === true) ? 1 : 0,
260
            'pricing_scheme' => $pricing_scheme,
261
        ];
262
    }
263
264
    /**
265
     * Create a product for a subscription's billing plan.
266
     *
267
     * @param string $name
268
     * @param string $description
269
     * @param string $type
270
     * @param string $category
271
     *
272
     * @throws Throwable
273
     *
274
     * @return \Srmklive\PayPal\Services\PayPal
275
     */
276
    public function addProduct(string $name, string $description, string $type, string $category): \Srmklive\PayPal\Services\PayPal
277
    {
278
        if (isset($this->product)) {
279
            return $this;
280
        }
281
282
        $request_id = Str::random();
283
284
        $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

284
        /** @scrutinizer ignore-call */ 
285
        $this->product = $this->createProduct([
Loading history...
285
            'name'          => $name,
286
            'description'   => $description,
287
            'type'          => $type,
288
            'category'      => $category,
289
        ], $request_id);
290
291
        return $this;
292
    }
293
294
    /**
295
     * Add subscription's billing plan's product by ID.
296
     *
297
     * @param string $product_id
298
     *
299
     * @return \Srmklive\PayPal\Services\PayPal
300
     */
301
    public function addProductById(string $product_id): \Srmklive\PayPal\Services\PayPal
302
    {
303
        $this->product = [
304
            'id' => $product_id,
305
        ];
306
307
        return $this;
308
    }
309
310
    /**
311
     * Add subscription's billing plan by ID.
312
     *
313
     * @param string $plan_id
314
     *
315
     * @return \Srmklive\PayPal\Services\PayPal
316
     */
317
    public function addBillingPlanById(string $plan_id): \Srmklive\PayPal\Services\PayPal
318
    {
319
        $this->billing_plan = [
320
            'id' => $plan_id,
321
        ];
322
323
        return $this;
324
    }
325
326
    /**
327
     * Create a product for a subscription's billing plan.
328
     *
329
     * @param string $name
330
     * @param string $description
331
     * @param array  $billing_cycles
332
     *
333
     * @throws Throwable
334
     *
335
     * @return void
336
     */
337
    protected function addBillingPlan(string $name, string $description, array $billing_cycles): void
338
    {
339
        $request_id = Str::random();
340
341
        $plan_params = [
342
            'product_id'          => $this->product['id'],
343
            'name'                => $name,
344
            'description'         => $description,
345
            'status'              => 'ACTIVE',
346
            'billing_cycles'      => $billing_cycles,
347
            'payment_preferences' => [
348
                'auto_bill_outstanding'     => true,
349
                'setup_fee_failure_action'  => 'CONTINUE',
350
                'payment_failure_threshold' => $this->payment_failure_threshold,
351
            ],
352
        ];
353
354
        $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

354
        /** @scrutinizer ignore-call */ 
355
        $this->billing_plan = $this->createPlan($plan_params, $request_id);
Loading history...
355
    }
356
357
    /**
358
     * Use custom return urls
359
     *
360
     * @param string $return_url
361
     * @param string $cancel_url
362
     * @return \Srmklive\PayPal\Services\PayPal
363
     */
364
    public function setReturnAndCancelUrl(string $return_url, string $cancel_url)
365
    {
366
        $this->return_url = $return_url;
367
        $this->cancel_url = $cancel_url;
368
369
        return $this;
370
    }
371
}
372