Passed
Push — main ( 5b8ed0...39c0b3 )
by Michael
03:33
created

StripePaymentProvider::prepareCustomer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\StripeIntegration\Providers;
6
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Traits\Macroable;
10
use Laravel\Cashier\Exceptions\IncompletePayment;
11
use Laravel\Cashier\Payment;
12
use Laravel\Cashier\PaymentMethod as CashierPaymentMethod;
13
use MichaelRubel\StripeIntegration\DataTransferObjects\OffsessionChargeData;
14
use MichaelRubel\StripeIntegration\DataTransferObjects\StripeChargeData;
15
use MichaelRubel\StripeIntegration\Decorators\StripePaymentAmount;
16
use MichaelRubel\StripeIntegration\Providers\Contracts\PaymentProviderContract;
17
use Money\Currency;
18
use Stripe\Customer;
19
use Stripe\Exception\ApiErrorException;
20
use Stripe\PaymentIntent;
21
use Stripe\PaymentMethod;
22
use Stripe\SetupIntent;
23
use Stripe\StripeClient;
24
25
class StripePaymentProvider implements PaymentProviderContract
26
{
27
    use Macroable;
0 ignored issues
show
Bug introduced by
The trait Illuminate\Support\Traits\Macroable requires the property $name which is not provided by MichaelRubel\StripeInteg...s\StripePaymentProvider.
Loading history...
28
29
    /**
30
     * @return void
31
     */
32 14
    public function __construct(
33
        protected StripeClient $stripeClient
34
    ) {
35
    }
36
37
    /**
38
     * Set the Cashier's currency.
39
     *
40
     * @param Currency $currency
41
     *
42
     * @return void
43
     */
44 1
    public function configureCashierCurrency(Currency $currency): void
45
    {
46 1
        config([
47 1
            'cashier.currency' => $currency->getCode(),
48
        ]);
49
    }
50
51
    /**
52
     * Create the Stripe setup intent.
53
     *
54
     * @param Model $model
55
     * @param array $options
56
     *
57
     * @return SetupIntent
58
     */
59 1
    public function setupIntentUsing(Model $model, array $options = []): SetupIntent
60
    {
61 1
        $options = collect([
0 ignored issues
show
Bug introduced by
array('usage' => 'off_session') of type array<string,string> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

61
        $options = collect(/** @scrutinizer ignore-type */ [
Loading history...
62
            'usage' => 'off_session',
63 1
        ])->merge($options)->toArray();
0 ignored issues
show
Bug introduced by
$options of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::merge(). ( Ignorable by Annotation )

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

63
        ])->merge(/** @scrutinizer ignore-type */ $options)->toArray();
Loading history...
64
65 1
        return call($model)->createSetupIntent($options);
66
    }
67
68
    /**
69
     * Prepare the customer to work with the payment system.
70
     *
71
     * @param Model $model
72
     *
73
     * @return Customer
74
     */
75 3
    public function prepareCustomer(Model $model): Customer
76
    {
77 3
        return call($model)->createOrGetStripeCustomer();
78
    }
79
80
    /**
81
     * Update the default payment method for model.
82
     *
83
     * @param Model                $model
84
     * @param PaymentMethod|string $paymentMethod
85
     *
86
     * @return CashierPaymentMethod
87
     */
88 3
    public function updatePaymentMethod(Model $model, PaymentMethod|string $paymentMethod): CashierPaymentMethod
89
    {
90 3
        return call($model)->updateDefaultPaymentMethod($paymentMethod);
91
    }
92
93
    /**
94
     * Attach the payment method to the customer.
95
     *
96
     * @param PaymentMethod|CashierPaymentMethod $paymentMethod
97
     * @param Customer                           $customer
98
     * @param array                              $params
99
     * @param array                              $options
100
     *
101
     * @return PaymentMethod
102
     */
103 3
    public function attachPaymentMethodToCustomer(
104
        PaymentMethod|CashierPaymentMethod $paymentMethod,
105
        Customer $customer,
106
        array $params = [],
107
        array $options = []
108
    ): PaymentMethod {
109 3
        $params = collect([
0 ignored issues
show
Bug introduced by
array('customer' => $customer->id) of type array<string,string> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

109
        $params = collect(/** @scrutinizer ignore-type */ [
Loading history...
110 3
            'customer' => $customer->id,
111 3
        ])->merge($params)->toArray();
0 ignored issues
show
Bug introduced by
$params of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::merge(). ( Ignorable by Annotation )

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

111
        ])->merge(/** @scrutinizer ignore-type */ $params)->toArray();
Loading history...
112
113 3
        return call($this->stripeClient->paymentMethods)->attach(
114 3
            $paymentMethod->id,
115
            $params,
116
            $options
117
        );
118
    }
119
120
    /**
121
     * Perform a simple charge.
122
     *
123
     * @param StripeChargeData $data
124
     *
125
     * @return Payment
126
     * @throws IncompletePayment
127
     */
128 1
    public function charge(StripeChargeData $data): Payment
129
    {
130 1
        return call($data->model)->charge(
131 1
            $data->payment_amount->getAmount(),
132 1
            $data->payment_method->id,
133 1
            $data->options
134
        );
135
    }
136
137
    /**
138
     * Create a payment intent.
139
     *
140
     * @param StripePaymentAmount $paymentAmount
141
     * @param Model               $model
142
     * @param array               $params
143
     * @param array               $options
144
     *
145
     * @return PaymentIntent
146
     */
147 2
    public function createPaymentIntent(
148
        StripePaymentAmount $paymentAmount,
149
        Model $model,
150
        array $params = [],
151
        array $options = []
152
    ): PaymentIntent {
153 2
        return call($this->stripeClient->paymentIntents)->create(
154 2
            collect([
0 ignored issues
show
Bug introduced by
array('amount' => $payme...ypes' => array('card')) of type array<string,array<integ...string>|integer|string> is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

154
            collect(/** @scrutinizer ignore-type */ [
Loading history...
155 2
                'amount'               => $paymentAmount->getAmount(),
156 2
                'currency'             => $paymentAmount->getCurrency()->getCode(),
157
                'payment_method_types' => ['card'],
158
            ])
159 2
            ->when($model->stripeId(), fn ($params) => $params->merge([
160
                'customer' => $model->stripeId(),
161
            ]))
162 2
            ->merge($params)
0 ignored issues
show
Bug introduced by
$params of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::merge(). ( Ignorable by Annotation )

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

162
            ->merge(/** @scrutinizer ignore-type */ $params)
Loading history...
163 2
            ->toArray(),
164
            $options
165
        );
166
    }
167
168
    /**
169
     * Retrieve the payment intent.
170
     *
171
     * @param string $intent_id
172
     * @param array  $params
173
     * @param array  $options
174
     *
175
     * @return PaymentIntent
176
     *
177
     * @throws ApiErrorException
178
     */
179 1
    public function retrievePaymentIntent(string $intent_id, array $params = [], array $options = []): PaymentIntent
180
    {
181 1
        return call($this->stripeClient->paymentIntents)->retrieve(
182
            $intent_id,
183
            $params,
184
            $options
185
        );
186
    }
187
188
    /**
189
     * Update the payment intent.
190
     *
191
     * @param string $intent_id
192
     * @param array  $params
193
     * @param array  $options
194
     *
195
     * @return PaymentIntent
196
     *
197
     * @throws ApiErrorException
198
     */
199 1
    public function updatePaymentIntent(string $intent_id, array $params = [], array $options = []): PaymentIntent
200
    {
201 1
        return call($this->stripeClient->paymentIntents)->update(
202
            $intent_id,
203
            $params,
204
            $options
205
        );
206
    }
207
208
    /**
209
     * Confirm the payment intent.
210
     *
211
     * @param PaymentIntent $paymentIntent
212
     * @param array         $confirmation_params
213
     * @param array         $confirmation_options
214
     *
215
     * @return PaymentIntent
216
     */
217 2
    public function confirmPaymentIntent(
218
        PaymentIntent $paymentIntent,
219
        array $confirmation_params = [],
220
        array $confirmation_options = []
221
    ): PaymentIntent {
222 2
        return call($this->stripeClient->paymentIntents)->confirm(
223 2
            $paymentIntent->id,
224
            $confirmation_params,
225
            $confirmation_options
226
        );
227
    }
228
229
    /**
230
     * Perform an offsession charge.
231
     *
232
     * @param OffsessionChargeData $data
233
     *
234
     * @return PaymentIntent
235
     * @throws ApiErrorException
236
     */
237 1
    public function offsessionCharge(OffsessionChargeData $data): PaymentIntent
238
    {
239 1
        $paymentIntent = $this->createPaymentIntent(
240 1
            $data->payment_amount,
241 1
            $data->model
242
        );
243
244 1
        $confirmation_params = collect([
0 ignored issues
show
Bug introduced by
array('payment_method' =...ultPaymentMethod()->id) of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

244
        $confirmation_params = collect(/** @scrutinizer ignore-type */ [
Loading history...
245 1
            'payment_method' => call($data->model)->defaultPaymentMethod()->id,
246 1
        ])->merge($data->confirmation_params)->toArray();
0 ignored issues
show
Bug introduced by
$data->confirmation_params of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::merge(). ( Ignorable by Annotation )

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

246
        ])->merge(/** @scrutinizer ignore-type */ $data->confirmation_params)->toArray();
Loading history...
247
248 1
        return $this->confirmPaymentIntent(
249
            $paymentIntent,
250
            $confirmation_params,
251 1
            $data->confirmation_options
252
        );
253
    }
254
}
255