Integrating Multiple Third-Party Services with the Strategy Pattern in Laravel

Support the development of the website

This website was created to provide useful and free information to the community. To maintain and develop it, we need support from you.

If you find the website valuable, you can contribute any amount, whether it's $1 or $2, to help keep it running. Your contribution will help cover operating costs, maintenance, and content improvement. Every donation is greatly appreciated and will help us grow sustainably.

Thank you sincerely for your support!
Integrating Multiple Third-Party Services with the Strategy Pattern in Laravel
This blog post demonstrates how to effectively integrate multiple third-party services into a Laravel application using the Strategy Pattern. The Strategy Pattern provides a flexible and maintainable solution for handling different service implementations while maintaining a consistent interface. The post covers the general steps involved, a detailed implementation example, and an alternative approach using a factory pattern.

General Steps

  • Identify the third-party services to integrate
  • Define a common interface for all services
  • Implement the interface for each service
  • Create a context class to manage the services
  • Use dependency injection to select the appropriate service

Strategy Pattern Implementation

Define the strategy interface:

interface PaymentGatewayInterface
{
    public function processPayment(array $paymentDetails): bool;
}

Implement concrete strategies:

class StripePayment implements PaymentGatewayInterface
{
    public function processPayment(array $paymentDetails): bool
    {
        // Stripe-specific implementation
    }
}
class PayPalPayment implements PaymentGatewayInterface
{
    public function processPayment(array $paymentDetails): bool
    {
        // PayPal-specific implementation
    }
}

Create a context class:

class PaymentProcessor
{
    private $gateway;

    public function __construct(PaymentGatewayInterface $gateway)
    {
        $this->gateway = $gateway;
    }

    public function pay(array $paymentDetails): bool
    {
        return $this->gateway->processPayment($paymentDetails);
    }
}

Laravel Implementation Example

Install required packages:

composer require stripe/stripe-php
composer require paypal/rest-api-sdk-php

Create service providers:

php artisan make:provider StripeServiceProvider
php artisan make:provider PayPalServiceProvider

Implement service providers:

// app/Providers/StripeServiceProvider.php
public function register()
{
    $this->app->bind(PaymentGatewayInterface::class, function ($app) {
        return new StripePayment(config('services.stripe.secret'));
    });
}
// app/Providers/PayPalServiceProvider.php
public function register()
{
    $this->app->bind(PaymentGatewayInterface::class, function ($app) {
        return new PayPalPayment(config('services.paypal.client_id'), config('services.paypal.secret'));
    });
}

Update config/app.php:
The choice between these providers is typically made in the config/app.php file or through environment variables. You would enable one provider and comment out or remove the other:

'providers' => [
    // ...
    App\Providers\StripeServiceProvider::class,
    // App\Providers\PayPalServiceProvider::class,
],

Use in controller:

class PaymentController extends Controller
{
    private $paymentProcessor;

    public function __construct(PaymentProcessor $paymentProcessor)
    {
        $this->paymentProcessor = $paymentProcessor;
    }

    public function processPayment(Request $request)
    {
        $paymentDetails = $request->validated();
        $result = $this->paymentProcessor->pay($paymentDetails);

        return $result ? response()->json(['status' => 'success']) : response()->json(['status' => 'failure'], 400);
    }
}

This implementation allows easy switching between payment gateways and the addition of new gateways without modifying existing code.

Use Factory - Another implementation

The payment method is sent from the front end as 'payment_method'.
The controller retrieves this value using $request->input('payment_method').

// In your controller
public function processPayment(Request $request)
{
    $gatewayName = $request->input('payment_method');
    $paymentDetails = $request->input('payment_details');

    try {
        $gateway = PaymentGatewayFactory::create($gatewayName);
        $result = $gateway->processPayment($paymentDetails);
        // Handle successful payment
    } catch (\Exception $e) {
        // Handle errors
    }
}

The PaymentGatewayFactory creates the appropriate gateway object based on the payment method.

// PaymentGatewayFactory.php
class PaymentGatewayFactory
{
    public static function create($gatewayName)
    {
        switch ($gatewayName) {
            case 'paypal':
                return new PayPalGateway();
            case 'stripe':
                return new StripeGateway();
            default:
                throw new \Exception("Unsupported gateway");
        }
    }
}

The controller then uses this gateway object to process the payment.
This approach allows you to easily add new payment gateways by creating new classes that implement the PaymentGatewayInterface and adding them to the factory method.

Support the development of the website

This website was created to provide useful and free information to the community. To maintain and develop it, we need support from you.

If you find the website valuable, you can contribute any amount, whether it's $1 or $2, to help keep it running. Your contribution will help cover operating costs, maintenance, and content improvement. Every donation is greatly appreciated and will help us grow sustainably.

Thank you sincerely for your support!