php
45 lines · 7 steps
Binding a payment gateway in Laravel
A deferred service provider wires an interface to the right implementation based on environment and config.
Explained by
highlit
1<?php
2
3namespace App\Providers;
4
5use App\Contracts\PaymentGateway;
6use App\Services\Payments\FakePaymentGateway;
7use App\Services\Payments\StripePaymentGateway;
8use Illuminate\Contracts\Support\DeferrableProvider;
9use Illuminate\Support\ServiceProvider;
10use Stripe\StripeClient;
11
12class PaymentServiceProvider extends ServiceProvider implements DeferrableProvider
13{
14 public function register(): void
15 {
16 $this->app->bind(PaymentGateway::class, function ($app) {
17 $config = $app['config']['services.stripe'];
18
19 if ($app->environment('testing') || empty($config['secret'])) {
20 return new FakePaymentGateway();
21 }
22
23 return new StripePaymentGateway(
24 new StripeClient($config['secret']),
25 $config['webhook_secret'] ?? null,
26 );
27 });
28
29 $this->app->singleton(StripeClient::class, function ($app) {
30 return new StripeClient($app['config']['services.stripe.secret']);
31 });
32
33 $this->app->when(StripePaymentGateway::class)
34 ->needs('$currency')
35 ->giveConfig('services.stripe.currency', 'usd');
36 }
37
38 public function provides(): array
39 {
40 return [
41 PaymentGateway::class,
42 StripeClient::class,
43 ];
44 }
45}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Binding to an interface lets you swap implementations without touching the code that depends on it.
- 2Resolving the implementation inside a closure defers the decision until the service is actually needed.
- 3Deferred providers list what they provide so Laravel can skip booting them until something asks.
Related explainers
python
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status from pydantic import BaseModel, EmailStr from sqlalchemy.orm import Session
Building a signup endpoint in FastAPI
dependency-injection
request-validation
background-tasks
Intermediate
8 steps
java
public interface GitHubClient { @GetExchange("/users/{username}") GitHubUser getUser(@PathVariable String username);
Declarative HTTP clients in Spring
http-client
declarative-api
proxy
Intermediate
8 steps
php
<?php namespace App\Console\Commands;
Releasing stale document locks in Laravel
artisan-command
transactions
row-locking
Intermediate
6 steps
php
<?php namespace App\Providers;
Subdomain multi-tenancy routing in Laravel
multi-tenancy
service-container
route-binding
Advanced
7 steps
php
<?php namespace App\Broadcasting;
Authorizing presence channels in Laravel
broadcasting
authorization
presence-channels
Intermediate
3 steps
java
@RestController @RequestMapping("/api/products") public class ProductSearchController {
Binding collection query params in Spring
rest-api
query-parameters
dependency-injection
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/binding-a-payment-gateway-in-laravel-explained-php-781b/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.