├── .gitignore
├── changelog.md
├── composer.json
├── config
└── stripe-server.php
├── migrations
└── 2019_06_19_101000_create_stripe_checkouts_table.php
├── phpunit.xml
├── readme.md
├── src
├── Commands
│ ├── Events.php
│ ├── Purge.php
│ └── StripeCompletedCheckout.php
├── Events
│ ├── CheckoutSessionCompleted.php
│ └── StripeEvent.php
├── Facades
│ └── Stripe.php
├── Models
│ ├── HasStripeCheckout.php
│ ├── HasStripeCheckouts.php
│ └── StripeCheckout.php
├── Nova
│ └── StripeCheckout.php
├── Requests
│ ├── Command.php
│ ├── CreateCharge.php
│ ├── CreateSession.php
│ ├── Events.php
│ └── PaymentIntent.php
├── Stripe.php
└── StripeServerServiceProvider.php
└── views
└── redirector.blade.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Laravel Stripe Server Changelog
2 |
3 | ## 1.2.0
4 |
5 | - Update `stripe-php` to `7.40`
6 | - Change author contact
7 |
8 | ## 1.1.1
9 |
10 | - Fix model on commands
11 |
12 | ## 1.1.0
13 |
14 | - Laravel 7 support
15 |
16 | ## 1.0.0
17 |
18 | - Laravel 6
19 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lab404/laravel-stripe-server",
3 | "description": "Laravel Stripe Server is a library to handle Stripe SCA checkout.",
4 | "type": "library",
5 | "keywords": [
6 | "laravel",
7 | "package",
8 | "plugin",
9 | "stripe",
10 | "server",
11 | "payment",
12 | "sca",
13 | "checkout",
14 | "laravel-package",
15 | "laravel-plugin"
16 | ],
17 | "require": {
18 | "php": "^7.2",
19 | "laravel/framework": "^6.0 | ^7.0",
20 | "stripe/stripe-php": "^7.40"
21 | },
22 | "license": "MIT",
23 | "authors": [
24 | {
25 | "name": "Marceau Ka",
26 | "email": "marceau@casals.fr"
27 | }
28 | ],
29 | "autoload": {
30 | "psr-4": {
31 | "Lab404\\StripeServer\\": "src/"
32 | }
33 | },
34 | "autoload-dev": {
35 | "psr-4": {
36 | "Lab404\\Tests\\": "tests/"
37 | }
38 | },
39 | "extra": {
40 | "laravel": {
41 | "providers": [
42 | "Lab404\\StripeServer\\StripeServerServiceProvider"
43 | ]
44 | }
45 | },
46 | "minimum-stability": "dev",
47 | "prefer-stable": true
48 | }
49 |
--------------------------------------------------------------------------------
/config/stripe-server.php:
--------------------------------------------------------------------------------
1 | \Lab404\StripeServer\Models\StripeCheckout::class,
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/migrations/2019_06_19_101000_create_stripe_checkouts_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
13 | $table->string('payment_intent_id')->nullable()->index();
14 | $table->string('checkout_session_id')->nullable()->index();
15 | $table->boolean('is_paid')->default(0)->index();
16 | $table->string('chargeable_type');
17 | $table->integer('chargeable_id');
18 | $table->timestamps();
19 |
20 | $table->index(['chargeable_type', 'chargeable_id']);
21 | });
22 | }
23 |
24 | public function down()
25 | {
26 | Schema::dropIfExists('stripe_checkouts');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | src/
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Laravel Stripe Server
2 |
3 | Laravel Stripe Server is a library to handle Stripe SCA checkout for your models.
4 |
5 | - [Requirements](#requirements)
6 | - [Intended workflow](#intended-workflow)
7 | - [Installation](#installation)
8 | - [Going deeper](#going-deeper)
9 | - [Nova](#nova)
10 | - [Ideas](#ideas)
11 | - [Tests](#tests)
12 | - [Contribute](#contribute)
13 | - [Licence](#licence)
14 |
15 | ## Requirements
16 |
17 | - Laravel 6.x or 7.x
18 | - PHP >= 7.2
19 |
20 | ### Laravel support
21 |
22 | | Version | Release |
23 | |:-------------:|:-------------:|
24 | | 6.x, 7.x | 1.1 |
25 | | 6.x | 1.0 |
26 | | 5.8 | 0.3 |
27 |
28 | ## Intended workflow
29 |
30 | - You have an `Order` model with a stripe checkout. You create the order in your controller.
31 |
32 | Example model:
33 | ```php
34 | use App\Models\Order;
35 | use Lab404\StripeServer\Facades\Stripe;
36 | use Illuminate\Http\Request;
37 |
38 | class OrderController
39 | {
40 | public function store(Request $request)
41 | {
42 | // Create your order
43 | $order = new Order($request->validated());
44 | $order->save();
45 |
46 | // Create your checkout session
47 | $session = Stripe::requestCreateSession()
48 | ->setCustomerEmail($request->user()->email)
49 | ->setReturnUrls($confirm_url, $cancel_url)
50 | ->setProduct('T-shirt', 5000, 'EUR', 1, $picture_url)
51 | ->call();
52 |
53 | // Create your checkout model
54 | $checkout = Stripe::registerCheckout($session, $order);
55 |
56 | return Stripe::redirectSession($response->id);
57 | }
58 | }
59 | ```
60 |
61 | - Your user is redirected to stripe, he fills his informations and he's redirected to your success URL. The order is not paid yet.
62 | Asynchronously, the plugin will try to get new events from Stripe and will dispatch the `CheckoutSessionCompleted` event:
63 |
64 | Example listener:
65 | ```php
66 | use Lab404\StripeServer\Events\CheckoutSessionCompleted;
67 | use Lab404\StripeServer\Models\StripeCheckout;
68 |
69 | class CheckoutListener
70 | {
71 | public function handle(CheckoutSessionCompleted $event): void
72 | {
73 | /** @var StripeCheckout $checkout */
74 | $checkout = $event->checkout;
75 | /** Your charged model */
76 | $chargeable = $checkout->chargeable;
77 | /** The PaymentIntent returned by Stripe */
78 | $payment = $event->paymentIntent;
79 |
80 | /** Important! Mark the checkout as paid */
81 | $checkout->markAsPaid();
82 | }
83 | }
84 | ```
85 |
86 | - You can use your model like this:
87 | ```php
88 | $order = Order::with('checkout')->first();
89 | if ($order->checkout->is_paid) {
90 | echo 'Order is paid';
91 | } else {
92 | echo 'Order is not paid';
93 | }
94 | ```
95 |
96 | ## Installation
97 |
98 | 1. Require it with Composer:
99 | ```bash
100 | composer require lab404/laravel-stripe-server
101 | ```
102 |
103 | 2. Configure your Stripe keys in `config/services.php`.
104 |
105 | 3. Publish `migrations` and `views` with `php artisan vendor:publish --tag=stripe-server`.
106 |
107 | 4. Migrate `2019_06_19_101000_create_stripe_checkouts_table.php`.
108 |
109 | 5. Schedule the command in `app\Console\Kernel.php`:
110 | ```php
111 | protected function schedule(Schedule $schedule)
112 | {
113 | $schedule->command('stripe:checkout-session-completed')->everyMinute();
114 | }
115 | ```
116 |
117 | 6. Add the `Lab404\StripeServer\Models\HasStripeCheckout` or `HasStripeCheckouts` (if a model can have multiple checkouts) to your chargeable models.
118 |
119 | ## Going deeper
120 |
121 | ### Stripe documentation
122 |
123 | - [Checkout Server Quickstart](https://stripe.com/docs/payments/checkout/server)
124 | - [Checkout Purchase Fulfillment](https://stripe.com/docs/payments/checkout/fulfillment)
125 | - [Going Live with Checkout](https://stripe.com/docs/payments/checkout/live)
126 | - [Strong Customer Authentication](https://stripe.com/docs/strong-customer-authentication)
127 |
128 | ### Access the Stripe Manager
129 |
130 | With facade:
131 | ```php
132 | Stripe::method();
133 | ```
134 |
135 | With DI:
136 | ```
137 | public function index(Lab404\StripeServer\Stripe $stripe)
138 | {
139 | $stripe->method();
140 | }
141 | ```
142 |
143 | With container:
144 | ```
145 | app('stripe')->method();
146 | ```
147 |
148 | ### Available methods
149 |
150 | - `redirectSession(string $session_id): Illuminate\Contracts\View\View`
151 | - `registerCheckout(\Stripe\Checkout\Session $session, Model $model): Illuminate\Database\Eloquent\Model`
152 | - `requestCreateCharge(): StripeServer\Requests\CreateCharge`
153 | - `requestCreateSession(): StripeServer\Requests\CreateSession`
154 | - `requestPaymentIntent(string $id): StripeServer\Requests\PaymentIntent`
155 | - `requestEvents(string $type, int $hours = 24): StripeServer\Requests\Events`
156 | - `requestSessionCheckoutCompletedEvents(int $hours = 24): StripeServer\Requests\Events`
157 |
158 | ### Working with your models
159 |
160 | #### Model with many checkouts
161 |
162 | When a model has the `Lab404\StripeServer\Models\HasStripeCheckouts` you have access to the following methods and scopes:
163 | ```php
164 | // Scopes
165 | Model::hasCheckouts()->get();
166 | Model::hasPaidCheckouts()->get();
167 | Model::hasUnpaidCheckouts()->get();
168 |
169 | // Methods
170 | $models->checkouts(); // returns all checkout for the model
171 |
172 | // Eager loading
173 | $models = Model::with('checkouts')->get();
174 | ```
175 |
176 | #### Model with one checkout
177 |
178 | When a model has the `Lab404\StripeServer\Models\HasStripeCheckout` you have access to the following methods and scopes:
179 | ```php
180 | // Scopes
181 | Model::hasCheckout()->get();
182 | Model::hasPaidCheckout()->get();
183 | Model::hasUnpaidCheckout()->get();
184 |
185 | // Methods
186 | $models->checkout(); // returns the checkout for the model
187 |
188 | // Eager loading
189 | $models = Model::with('checkout')->get();
190 | ```
191 |
192 | ### Customize the `StripeCheckout` model
193 |
194 | Configure `model` in `config/stripe-server.php`. Your custom model should extend the default one.
195 |
196 | ### Customize the redirector
197 |
198 | When you use the `redirectSession()` method, an instance of `Illuminate\View\View` is returned. You can do:
199 |
200 | ```php
201 | return Stripe::redirectSession('...')->with([
202 | 'title' => 'My custom title',
203 | 'message' => 'My customer redirect message'
204 | ]);
205 | ```
206 |
207 | ### Artisan commands
208 |
209 | #### `stripe:checkout-session-completed`
210 |
211 | Get all `checkout.session.completed` Stripe events and dispatch the event `CheckoutSessionCompleted` for each with the `succeeded` status.
212 |
213 | #### `stripe:events`
214 |
215 | Get all Stripe events and dispatch `StripeEvent` for each one.
216 |
217 | #### `stripe:purge`
218 |
219 | Delete all unpaid `StripeCheckout` older than the given days. Customize with the `--days` option, defaults to 7. It's convenient to call it in a scheduler:
220 |
221 | ```
222 | $schedule->command('stripe:purge')->dailyAt('12:00');
223 | ```
224 |
225 | ## Nova
226 |
227 | If you're using [Laravel Nova](https://nova.laravel.com) you can add the `Lab404\StripeServer\Nova\StripeCheckout` resource:
228 |
229 | ```
230 | Laravel\Nova\Nova::resources([
231 | Lab404\StripeServer\Nova\StripeCheckout::class,
232 | ]);
233 | ```
234 |
235 | This resource is not dynamically registered because it's quite simple and you may want to override it. More Nova features like Refund Action or Cards are coming.
236 |
237 | ## TODOs and ideas
238 |
239 | [x] Purge unpaid stripe checkouts
240 | [ ] Refund
241 | [ ] Nova actions
242 |
243 | ## Tests
244 |
245 | TODO
246 |
247 | ## Contribute
248 |
249 | This package is still in development, feel free to contribute!
250 |
251 | ### Contributors
252 |
253 | - [MarceauKa](https://github.com/MarceauKa)
254 | - and all others [contributors](https://github.com/404labfr/laravel-impersonate/graphs/contributors)
255 |
256 | ## Licence
257 |
258 | MIT
259 |
--------------------------------------------------------------------------------
/src/Commands/Events.php:
--------------------------------------------------------------------------------
1 | requestEvents($this->option('period'))->call();
20 |
21 | if ($events->isEmpty()) {
22 | $this->info('No events found for this period.');
23 | }
24 |
25 | $events->each(function ($event) {
26 | $this->info('Dispatching ' . $event->id);
27 | Event::dispatch(new StripeEvent($event));
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Commands/Purge.php:
--------------------------------------------------------------------------------
1 | getTable())
25 | ->where('is_paid', 0)
26 | ->where('created_at', '<=', Carbon::now()->subDays($this->option('days'))->toDateTimeString())
27 | ->delete();
28 |
29 | $this->info('Stripe checkouts purged.');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Commands/StripeCompletedCheckout.php:
--------------------------------------------------------------------------------
1 | requestSessionCheckoutCompletedEvents($this->option('period'))->call();
23 |
24 | if ($events->isEmpty()) {
25 | $this->info('No events found for this period.');
26 | }
27 |
28 | $ids = $events->pluck('payment_intent')->toArray();
29 | $model = Config::get('stripe-server.model');
30 | $model = $model ?? StripeCheckout::class;
31 |
32 | /** @var Collection $checkouts */
33 | $checkouts = $model::with('chargeable')->paymentIntentIdsAre($ids)->isNotPaid()->get();
34 | $checkouts->each(function ($checkout) use ($stripe) {
35 | try {
36 | $this->info('Dispatching ' . $checkout->payment_intent_id);
37 | $payment = $stripe->requestPaymentIntent($checkout->payment_intent_id)->call();
38 | if ($payment && $payment->status === 'succeeded') {
39 | Event::dispatch(new CheckoutSessionCompleted($checkout, $payment));
40 | }
41 | } catch (\Exception $e) {
42 | unset($e);
43 | }
44 | });
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Events/CheckoutSessionCompleted.php:
--------------------------------------------------------------------------------
1 | checkout = $checkout;
21 | $this->paymentIntent = $paymentIntent;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Events/StripeEvent.php:
--------------------------------------------------------------------------------
1 | event = $event;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Facades/Stripe.php:
--------------------------------------------------------------------------------
1 | morphOne(Config::get('stripe-server.model'), 'chargeable');
19 | }
20 |
21 | public function scopeHasCheckout(Builder $query): void
22 | {
23 | $query->has('checkout');
24 | }
25 |
26 | public function scopeHasPaidCheckout(Builder $query): void
27 | {
28 | $query->whereHas('checkout', function ($query) {
29 | $query->where('is_paid', '=', 1);
30 | });
31 | }
32 |
33 | public function scopeHasUnpaidCheckout(Builder $query): void
34 | {
35 | $query->whereHas('checkout', function ($query) {
36 | $query->where('is_paid', '=', 0);
37 | });
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Models/HasStripeCheckouts.php:
--------------------------------------------------------------------------------
1 | morphMany(Config::get('stripe-server.model'), 'chargeable');
19 | }
20 |
21 | public function scopeHasCheckouts(Builder $query): void
22 | {
23 | $query->has('checkouts');
24 | }
25 |
26 | public function scopeHasPaidCheckouts(Builder $query): void
27 | {
28 | $query->whereHas('checkouts', function ($query) {
29 | $query->where('is_paid', '=', 1);
30 | });
31 | }
32 |
33 | public function scopeHasUnpaidCheckouts(Builder $query): void
34 | {
35 | $query->whereHas('checkouts', function ($query) {
36 | $query->where('is_paid', '=', 0);
37 | });
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Models/StripeCheckout.php:
--------------------------------------------------------------------------------
1 | 'bool',
24 | ];
25 |
26 | public function chargeable(): MorphTo
27 | {
28 | return $this->morphTo();
29 | }
30 |
31 | public function markAsPaid(): bool
32 | {
33 | $this->attributes['is_paid'] = 1;
34 | return $this->save();
35 | }
36 |
37 | public function scopeIsPaid(Builder $query): void
38 | {
39 | $query->where('is_paid', 1);
40 | }
41 |
42 | public function scopeIsNotPaid(Builder $query): void
43 | {
44 | $query->where('is_paid', 0);
45 | }
46 |
47 | public function scopePaymentIntentIdsAre(Builder $query, array $ids): Builder
48 | {
49 | return $query->whereIn('payment_intent_id', $ids);
50 | }
51 |
52 | public function scopePaymentIntentIdIs(Builder $query, string $payment_intent_id): Builder
53 | {
54 | return $query->where('payment_intent_id', '=', $payment_intent_id);
55 | }
56 |
57 | public function scopeCheckoutSessionIdIs(Builder $query, string $checkout_session_id): Builder
58 | {
59 | return $query->where('checkout_session_id', '=', $checkout_session_id);
60 | }
61 |
62 | public function scopeCheckoutSessionIdsAre(Builder $query, array $ids): Builder
63 | {
64 | return $query->whereIn('checkout_session_id', $ids);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Nova/StripeCheckout.php:
--------------------------------------------------------------------------------
1 | hideFromIndex()
26 | ->asBigInt(),
27 |
28 | Boolean::make(__('Paid'), 'is_paid'),
29 |
30 | Text::make(__('Session ID'), 'checkout_session_id')
31 | ->exceptOnForms(),
32 |
33 | Text::make(__('Payment intent'), 'payment_intent_id')
34 | ->exceptOnForms(),
35 |
36 | Text::make(__('Chargeable type'), 'chargeable_type')
37 | ->exceptOnForms(),
38 |
39 | Text::make(__('Chargeable ID'), 'chargeable_id')
40 | ->exceptOnForms(),
41 |
42 | DateTime::make(__('Created at'), 'created_at')
43 | ->exceptOnForms(),
44 |
45 | DateTime::make(__('Updated at'), 'updated_at')
46 | ->exceptOnForms(),
47 | ];
48 | }
49 |
50 | public function cards(Request $request): array
51 | {
52 | return [];
53 | }
54 |
55 | public function filters(Request $request): array
56 | {
57 | return [];
58 | }
59 |
60 | public function lenses(Request $request): array
61 | {
62 | return [];
63 | }
64 |
65 | public function actions(Request $request): array
66 | {
67 | return [];
68 | }
69 |
70 | public static function singularLabel(): string
71 | {
72 | return __('Checkout');
73 | }
74 |
75 | public static function label(): string
76 | {
77 | return __('Checkouts');
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/Requests/Command.php:
--------------------------------------------------------------------------------
1 | class();
20 | $method = $this->method();
21 |
22 | try {
23 | return $class::$method($this->params);
24 | } catch (\Exception $e) {
25 | throw new \RuntimeException($e->getMessage(), $e->getCode(), $e);
26 | }
27 | }
28 |
29 | abstract protected function class(): string;
30 |
31 | abstract protected function method(): string;
32 | }
33 |
--------------------------------------------------------------------------------
/src/Requests/CreateCharge.php:
--------------------------------------------------------------------------------
1 | null,
11 | 'currency' => null,
12 | 'source' => null,
13 | 'description' => null,
14 | ];
15 |
16 | public function setAmount(int $amount): self
17 | {
18 | $this->params['amount'] = $amount;
19 | return $this;
20 | }
21 |
22 | public function setCurrency(string $currency): self
23 | {
24 | $this->params['currency'] = $currency;
25 | return $this;
26 | }
27 |
28 | public function setSource(string $source): self
29 | {
30 | $this->params['source'] = $source;
31 | return $this;
32 | }
33 |
34 | public function setDescription(string $description): self
35 | {
36 | $this->params['description'] = $description;
37 | return $this;
38 | }
39 |
40 | public function call(): StripeCharge
41 | {
42 | return parent::call();
43 | }
44 |
45 | protected function class(): string
46 | {
47 | return \Stripe\Charge::class;
48 | }
49 |
50 | protected function method(): string
51 | {
52 | return 'create';
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Requests/CreateSession.php:
--------------------------------------------------------------------------------
1 | null,
9 | 'payment_method_types' => ['card'],
10 | 'line_items' => [],
11 | 'locale' => 'auto',
12 | 'submit_type' => 'pay',
13 | 'success_url' => '',
14 | 'cancel_url' => '',
15 | ];
16 |
17 | public function setCustomerEmail(string $email): self
18 | {
19 | $this->params['customer_email'] = $email;
20 | return $this;
21 | }
22 |
23 | public function setCustomer(string $identifier): self
24 | {
25 | $this->params['customer'] = $identifier;
26 | return $this;
27 | }
28 |
29 | /**
30 | * @param string|array $methods
31 | * @return self
32 | */
33 | public function setPaymentMethods($methods = 'card'): self
34 | {
35 | $this->params['payment_method_types'] = is_array($methods) ? $methods : [$methods];
36 | return $this;
37 | }
38 |
39 | public function setLocale(string $locale = 'auto'): self
40 | {
41 | $this->params['locale'] = $locale;
42 | return $this;
43 | }
44 |
45 | public function setSubmit(string $submit): self
46 | {
47 | $this->params['submit_type'] = $submit;
48 | return $this;
49 | }
50 |
51 | public function setSuccessUrl(string $succes_url): self
52 | {
53 | $this->params['success_url'] = $succes_url;
54 | return $this;
55 | }
56 |
57 | public function setCancelUrl(string $cancel_url): self
58 | {
59 | $this->params['cancel_url'] = $cancel_url;
60 | return $this;
61 | }
62 |
63 | public function setReturnUrls(string $success_url, string $cancel_url)
64 | {
65 | return $this->setSuccessUrl($success_url)->setCancelUrl($cancel_url);
66 | }
67 |
68 | /**
69 | * @param string $name
70 | * @param int $amount
71 | * @param string $currency
72 | * @param int $quantity
73 | * @param string|string[] $images
74 | * @return CreateSession
75 | */
76 | public function setProduct(string $name, int $amount, string $currency, int $quantity, $images): self
77 | {
78 | $this->params['line_items'] = [];
79 | return $this->addProduct($name, $amount, $currency, $quantity, $images);
80 | }
81 |
82 | /**
83 | * @param string $name
84 | * @param int $amount
85 | * @param string $currency
86 | * @param int $quantity
87 | * @param string|string[] $images
88 | * @return CreateSession
89 | */
90 | public function addProduct(string $name, int $amount, string $currency, int $quantity, $images): self
91 | {
92 | $this->params['line_items'][] = [
93 | 'name' => $name,
94 | 'quantity' => $quantity,
95 | 'amount' => $amount,
96 | 'currency' => $currency,
97 | 'images' => is_array($images) ? $images : [$images],
98 | ];
99 | return $this;
100 | }
101 |
102 | protected function class(): string
103 | {
104 | return \Stripe\Checkout\Session::class;
105 | }
106 |
107 | protected function method(): string
108 | {
109 | return 'create';
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/Requests/Events.php:
--------------------------------------------------------------------------------
1 | 'all',
11 | 'created' => [],
12 | ];
13 |
14 | public function __construct(string $type, int $hours = 24)
15 | {
16 | $this->setType($type)
17 | ->setHours($hours);
18 | }
19 |
20 | public function setType(string $type): self
21 | {
22 | $this->params['type'] = $type;
23 | return $this;
24 | }
25 |
26 | public function setHours(int $hours): self
27 | {
28 | $this->params['created'] = [
29 | 'gte' => time() - abs($hours) * 60 * 60
30 | ];
31 | return $this;
32 | }
33 |
34 | public function call(): Collection
35 | {
36 | $response = parent::call();
37 |
38 | return collect($response->data)->transform(function ($item) {
39 | return $item->data->object;
40 | });
41 | }
42 |
43 | protected function class(): string
44 | {
45 | return \Stripe\Event::class;
46 | }
47 |
48 | protected function method(): string
49 | {
50 | return 'all';
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Requests/PaymentIntent.php:
--------------------------------------------------------------------------------
1 | params = $id;
12 | return $this;
13 | }
14 |
15 | protected function class(): string
16 | {
17 | return StripePaymentIntent::class;
18 | }
19 |
20 | protected function method(): string
21 | {
22 | return 'retrieve';
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Stripe.php:
--------------------------------------------------------------------------------
1 | key = $key;
24 | $this->secret = $secret;
25 |
26 | StripeCore::setApiKey($this->secret);
27 | }
28 |
29 | public function redirectSession(string $session_id): View
30 | {
31 | return view('stripe-server::redirector')->with([
32 | 'session_id' => $session_id,
33 | ]);
34 | }
35 |
36 | public function registerCheckout(\Stripe\Checkout\Session $session, Model $model): Model
37 | {
38 | $class = Config::get('stripe-server.model');
39 |
40 | $checkout = new $class([
41 | 'payment_intent_id' => $session->payment_intent,
42 | 'checkout_session_id' => $session->id,
43 | ]);
44 |
45 | if ($model->exists) {
46 | $checkout->chargeable_type = get_class($model);
47 | $checkout->chargeable_id = $model->getKey();
48 | }
49 |
50 | $checkout->save();
51 |
52 | return $checkout;
53 | }
54 |
55 | public function requestCreateCharge(): CreateCharge
56 | {
57 | return new CreateCharge();
58 | }
59 |
60 | public function requestCreateSession(): CreateSession
61 | {
62 | return new CreateSession();
63 | }
64 |
65 | public function requestPaymentIntent(string $id): PaymentIntent
66 | {
67 | return (new PaymentIntent())->setId($id);
68 | }
69 |
70 | public function requestEvents(string $type, int $hours = 24): Events
71 | {
72 | return new Events($type, $hours);
73 | }
74 |
75 | public function requestSessionCheckoutCompletedEvents(int $hours = 24): Events
76 | {
77 | return $this->requestEvents('checkout.session.completed', $hours);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/StripeServerServiceProvider.php:
--------------------------------------------------------------------------------
1 | mergeConfig();
19 |
20 | $this->app->singleton(Stripe::class, function () {
21 | return new Stripe(
22 | Config::get('services.stripe.key'),
23 | Config::get('services.stripe.secret')
24 | );
25 | });
26 |
27 | $this->app->alias(Stripe::class, 'stripe');
28 |
29 | if ($this->app->runningInConsole()) {
30 | $this->commands([
31 | Events::class,
32 | StripeCompletedCheckout::class,
33 | Purge::class,
34 | ]);
35 | }
36 | }
37 |
38 | public function boot()
39 | {
40 | $this->publishConfig();
41 | $this->loadMigrationsFrom(__DIR__ . '/../migrations');
42 | $this->loadViewsFrom(__DIR__ . '/../views', $this->configName);
43 | }
44 |
45 | protected function mergeConfig()
46 | {
47 | $configPath = __DIR__ . '/../config/' . $this->configName . '.php';
48 | $this->mergeConfigFrom($configPath, $this->configName);
49 | }
50 |
51 | protected function publishConfig()
52 | {
53 | $configPath = __DIR__ . '/../config/' . $this->configName . '.php';
54 | $this->publishes([$configPath => config_path($this->configName . '.php')], 'config');
55 | }
56 | }
--------------------------------------------------------------------------------
/views/redirector.blade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ $title ?? config('app.name') }}
7 |
8 |
34 |
35 |
36 |
37 |
38 |
39 | {{ $message ?? 'Redirecting to payment...' }}
40 |
41 |
42 |
43 |
44 |
52 |
53 |
--------------------------------------------------------------------------------