Search by

phpcorelab / payment-gateways

PHPCoreLab

Provider-agnostic PHP payment gateway library. Unified API for Razorpay, PhonePe, PayU, Paytm, Juspay and Cashfree.

Package info

github.com/PHPCoreLab/payment-gateways

pkg:composer/phpcorelab/payment-gateways

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.2 2026-09-06 14:16 UTC

This package is auto-updated.

Last update: 2026-09-30 22:09:32 UTC


README

Latest Version PHP Version License Tests

Provider-agnostic PHP payment gateway library.
A unified, strongly-typed API for Indian payment gateways: Razorpay, Cashfree, PhonePe, PayU, Juspay, and Paytm.
Switch payment gateways instantly with a single configuration line — zero changes to your checkout flow or business logic.

Table of Contents

Key Features

  • Unified Interface: Same methods (createOrder, verifyPayment, refund, handleWebhook) work identically across all supported gateways.
  • Zero Heavy SDKs: Lightweight implementation built directly on Guzzle 7 and native cryptography without bulky vendor SDK dependencies.
  • Strictly Typed & DTO Driven: Typed data transfer objects (OrderPayload, OrderResult, PaymentResult, RefundResult, PaymentEvent, PaymentStatus) for clean, predictable code and IDE autocompletion.
  • Provider Hot-Swapping: Switch active providers dynamically in runtime or per request based on customer preference, routing rules, or gateway health.
  • Secure Webhook Verification: Built-in HMAC-SHA256 and checksum verification per provider to secure your webhook endpoints against replay and tampering attacks.
  • Extensible Registry: Register proprietary gateways or custom in-house aggregators without modifying library core.
  • PSR-3 Logging: Plug in Monolog, Laravel Log, or any PSR-3 logger to track orders, provider switches, and transaction events.

Requirements

  • PHP: ^8.1
  • Extensions: json, curl, hash, openssl
  • Dependencies: guzzlehttp/guzzle: ^7.0, psr/log: ^3.0

Installation

composer require phpcorelab/payment-gateways

Supported Providers

Provider Integration Type Create Order Verify Payment Refund Webhook Verification API Version / Spec
Razorpay SDK Modal / Standard ✅ ✅ (HMAC-SHA256) ✅ ✅ (HMAC-SHA256) Orders & Payments API v1
Cashfree SDK / Web Checkout ✅ ✅ (API Poll / ID match) ✅ ✅ (HMAC-SHA256) PG API v2023-08-01
PhonePe Hosted / Custom ✅ ✅ (Checksum SHA256) ✅ ✅ (Checksum SHA256) Standard PG v1
PayU Form POST / Hosted ✅ ✅ (Reverse SHA512) ✅ ✅ (Reverse SHA512) Web Checkout / PostService
Juspay Express Checkout / SDK ✅ ✅ (Order Status API) ✅ ✅ (HTTP Basic Auth) Express Checkout / Session
Paytm All-in-One SDK 🚧 (Stub ready) 🚧 🚧 🚧 JWT / Transaction API

Architecture & How It Works

The library isolates gateway-specific quirks behind a clean unified sequence:

[ Frontend ]                     [ Backend (Your App) ]              [ Payment Provider ]
     |                                      |                                  |
     |--- 1. POST /checkout/order --------->|                                  |
     |                                      |--- gateway->createOrder() ------>|
     |                                      |<-- OrderResult ------------------|
     |<-- 2. Return { sdkPayload / url } ---|                                  |
     |                                                                         |
     |--- 3. Launch SDK Modal / Redirect to Provider ------------------------->|
     |<-- 4. User completes payment on Provider UI <---------------------------|
     |                                                                         |
     |--- 5. POST /checkout/verify (data) ->|                                  |
     |                                      |--- gateway->verifyPayment() ---->|
     |                                      |<-- PaymentResult ----------------|
     |<-- 6. Confirmed ({ status: SUCCESS })|                                  |
     |                                                                         |
     |                                      |<=== Inbound Webhook Event ========|
     |                                      |--- gateway->handleWebhook() -----|
     |                                      |    (Verifies signature & parses) |

Configuration

Environment Variables (.env)

Copy the required keys to your .env file:

# Active Gateway & Environment ('sandbox' or 'live')
ACTIVE_PROVIDER=razorpay
ENVIRONMENT=sandbox

# ─── Razorpay ───────────────────────────────────────────────
RAZORPAY_SANDBOX_KEY_ID=rzp_test_xxxxxxxxxxxxxx
RAZORPAY_SANDBOX_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
RAZORPAY_LIVE_KEY_ID=rzp_live_xxxxxxxxxxxxxx
RAZORPAY_LIVE_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# ─── Cashfree ───────────────────────────────────────────────
CASHFREE_SANDBOX_APP_ID=TESTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CASHFREE_SANDBOX_SECRET_KEY=cfsk_ma_test_xxxxxxxxxxxxxxxxxxxxxxxx
CASHFREE_LIVE_APP_ID=your-live-app-id
CASHFREE_LIVE_SECRET_KEY=your-live-secret-key

# ─── PhonePe ────────────────────────────────────────────────
PHONEPE_SANDBOX_MERCHANT_ID=PGTESTPAYUAT
PHONEPE_SANDBOX_SALT_KEY=099eb0cd-02cf-4dc2-a4f3-4b12a1d9d5e5
PHONEPE_SANDBOX_SALT_INDEX=1
PHONEPE_LIVE_MERCHANT_ID=YOUR_LIVE_MERCHANT_ID
PHONEPE_LIVE_SALT_KEY=your-live-salt-key
PHONEPE_LIVE_SALT_INDEX=1

# ─── PayU ───────────────────────────────────────────────────
PAYU_SANDBOX_MERCHANT_KEY=gtKFFx
PAYU_SANDBOX_MERCHANT_SALT=eCwWELxi
PAYU_LIVE_MERCHANT_KEY=your-live-key
PAYU_LIVE_MERCHANT_SALT=your-live-salt

# ─── Paytm ──────────────────────────────────────────────────
PAYTM_SANDBOX_MID=YOUR_SANDBOX_MID
PAYTM_SANDBOX_MERCHANT_KEY=your-sandbox-key
PAYTM_LIVE_MID=YOUR_LIVE_MID
PAYTM_LIVE_MERCHANT_KEY=your-live-key

# ─── Juspay ─────────────────────────────────────────────────
JUSPAY_SANDBOX_API_KEY=your-sandbox-api-key
JUSPAY_SANDBOX_MERCHANT_ID=your-sandbox-merchant-id
JUSPAY_SANDBOX_WEBHOOK_USERNAME=your-webhook-user
JUSPAY_SANDBOX_WEBHOOK_PASSWORD=your-webhook-pass
JUSPAY_LIVE_API_KEY=your-live-api-key
JUSPAY_LIVE_MERCHANT_ID=your-live-merchant-id
JUSPAY_LIVE_WEBHOOK_USERNAME=your-webhook-user
JUSPAY_LIVE_WEBHOOK_PASSWORD=your-webhook-pass

GatewayConfig Setup

Create a GatewayConfig instance using array configuration:

use PHPCoreLab\PaymentGateways\Core\GatewayConfig;
use PHPCoreLab\PaymentGateways\PaymentGateway;

$config = GatewayConfig::fromArray([
    'active_provider' => $_ENV['ACTIVE_PROVIDER'] ?? 'razorpay',
    'environment'     => $_ENV['ENVIRONMENT'] ?? 'sandbox', // 'sandbox' | 'live'
    'providers'       => [
        'razorpay' => [
            'sandbox_key_id'     => $_ENV['RAZORPAY_SANDBOX_KEY_ID'],
            'sandbox_key_secret' => $_ENV['RAZORPAY_SANDBOX_KEY_SECRET'],
            'live_key_id'        => $_ENV['RAZORPAY_LIVE_KEY_ID'],
            'live_key_secret'    => $_ENV['RAZORPAY_LIVE_KEY_SECRET'],
        ],
        'cashfree' => [
            'sandbox_app_id'     => $_ENV['CASHFREE_SANDBOX_APP_ID'],
            'sandbox_secret_key' => $_ENV['CASHFREE_SANDBOX_SECRET_KEY'],
            'live_app_id'        => $_ENV['CASHFREE_LIVE_APP_ID'],
            'live_secret_key'    => $_ENV['CASHFREE_LIVE_SECRET_KEY'],
            'api_version'        => '2023-08-01', // optional, defaults to 2023-08-01
        ],
        'phonepe' => [
            'sandbox_merchant_id' => $_ENV['PHONEPE_SANDBOX_MERCHANT_ID'],
            'sandbox_salt_key'    => $_ENV['PHONEPE_SANDBOX_SALT_KEY'],
            'sandbox_salt_index'  => (int) ($_ENV['PHONEPE_SANDBOX_SALT_INDEX'] ?? 1),
            'live_merchant_id'    => $_ENV['PHONEPE_LIVE_MERCHANT_ID'],
            'live_salt_key'       => $_ENV['PHONEPE_LIVE_SALT_KEY'],
            'live_salt_index'     => (int) ($_ENV['PHONEPE_LIVE_SALT_INDEX'] ?? 1),
        ],
        'payu' => [
            'sandbox_merchant_key'  => $_ENV['PAYU_SANDBOX_MERCHANT_KEY'],
            'sandbox_merchant_salt' => $_ENV['PAYU_SANDBOX_MERCHANT_SALT'],
            'live_merchant_key'     => $_ENV['PAYU_LIVE_MERCHANT_KEY'],
            'live_merchant_salt'    => $_ENV['PAYU_LIVE_MERCHANT_SALT'],
        ],
        'juspay' => [
            'sandbox_api_key'          => $_ENV['JUSPAY_SANDBOX_API_KEY'],
            'sandbox_merchant_id'      => $_ENV['JUSPAY_SANDBOX_MERCHANT_ID'],
            'sandbox_webhook_username' => $_ENV['JUSPAY_SANDBOX_WEBHOOK_USERNAME'],
            'sandbox_webhook_password' => $_ENV['JUSPAY_SANDBOX_WEBHOOK_PASSWORD'],
            'live_api_key'             => $_ENV['JUSPAY_LIVE_API_KEY'],
            'live_merchant_id'         => $_ENV['JUSPAY_LIVE_MERCHANT_ID'],
            'live_webhook_username'    => $_ENV['JUSPAY_LIVE_WEBHOOK_USERNAME'],
            'live_webhook_password'    => $_ENV['JUSPAY_LIVE_WEBHOOK_PASSWORD'],
        ],
        'paytm' => [
            'sandbox_mid'          => $_ENV['PAYTM_SANDBOX_MID'],
            'sandbox_merchant_key' => $_ENV['PAYTM_SANDBOX_MERCHANT_KEY'],
            'live_mid'             => $_ENV['PAYTM_LIVE_MID'],
            'live_merchant_key'    => $_ENV['PAYTM_LIVE_MERCHANT_KEY'],
        ],
    ],
]);

$gateway = new PaymentGateway($config);

Usage Guide

1. Create an Order

Amounts are always specified in paise (100 paise = 1 INR).

use PHPCoreLab\PaymentGateways\DTOs\OrderPayload;

$order = $gateway->createOrder(new OrderPayload(
    orderId:       'ORD-2026-001',
    amountPaisa:   49900,                    // ₹499.00 in paise
    currency:      'INR',
    customerName:  'Aman Roy',
    customerEmail: 'aman@example.com',
    customerPhone: '9876543210',
    returnUrl:     'https://yourdomain.com/payment/callback',
    cancelUrl:     'https://yourdomain.com/payment/cancel',
    description:   'Pro Membership Subscription',
    meta:          ['user_id' => '1029'],
));

// Send response to your frontend:
// $order->orderId         -> Merchant order ID ('ORD-2026-001')
// $order->providerOrderId -> Provider reference ID (e.g. 'order_MNV...' or '12345')
// $order->paymentUrl      -> Direct redirect URL (PhonePe, PayU, Juspay)
// $order->sdkPayload      -> Parameters for client-side SDKs (Razorpay, Cashfree, Juspay)

2. Frontend Checkout Flows

A. Razorpay (Standard Checkout Modal)

Include <script src="https://checkout.razorpay.com/v1/checkout.js"></script>:

const options = {
    ...sdkPayload,
    handler: function (response) {
        // Forward verification payload to backend
        fetch('/payment/confirm', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                order_id: response.razorpay_order_id,
                razorpay_order_id: response.razorpay_order_id,
                razorpay_payment_id: response.razorpay_payment_id,
                razorpay_signature: response.razorpay_signature,
            }),
        }).then(r => r.json()).then(handlePaymentResult);
    },
};

const rzp = new Razorpay(options);
rzp.open();

B. Cashfree (JS SDK v3 Checkout)

Include <script src="https://sdk.cashfree.com/js/v3/cashfree.js"></script>:

const cashfree = Cashfree({
    mode: sdkPayload.environment === "live" ? "production" : "sandbox",
});

cashfree.checkout({
    paymentSessionId: sdkPayload.payment_session_id,
    redirectTarget: "_modal", // or "_self" to redirect
}).then((result) => {
    if (result.error) {
        console.error("Cashfree checkout error:", result.error);
    }
    if (result.paymentDetails) {
        // Confirm payment status with your backend
        fetch('/payment/confirm', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                order_id: sdkPayload.order_id,
            }),
        });
    }
});

C. PhonePe / PayU / Juspay (Redirect Flow)

For redirect-based gateways, redirect the user directly to $order->paymentUrl:

if (paymentUrl) {
    window.location.href = paymentUrl;
}

3. Verify Payment

When the customer completes the payment and is redirected back to your returnUrl (or after client SDK completion), pass the response parameters to verifyPayment():

use PHPCoreLab\PaymentGateways\DTOs\PaymentStatus;

// Pass the merchant order ID and all payload parameters from request
$result = $gateway->verifyPayment($orderId, $_POST ?: json_decode(file_get_contents('php://input'), true));

if ($result->isSuccessful()) {
    // Payment confirmed!
    $providerPaymentId = $result->providerPaymentId; // Gateway payment ID
    $bankRef           = $result->providerRef;         // RRN / Bank UTR
    $amountPaisa       = $result->amountPaisa;         // Captured amount

    // Fulfill order in database...
} else {
    $reason = $result->failureReason;
    // Log failure or prompt user to retry...
}

4. Process Refunds

Initiate full or partial refunds:

// Pass gateway payment ID (or order ID depending on provider) and amount in paise
$refundResult = $gateway->refund($result->providerPaymentId, 49900);

if ($refundResult->success) {
    echo "Refund initiated successfully! Refund ID: " . $refundResult->refundId;
} else {
    echo "Refund failed: " . $refundResult->message;
}

5. Handle Webhooks

Webhooks notify your application asynchronously of payment completion, failures, and refunds. The library automatically validates cryptographic signatures:

use PHPCoreLab\PaymentGateways\DTOs\PaymentStatus;
use PHPCoreLab\PaymentGateways\Exceptions\WebhookVerificationException;

try {
    $rawBody = file_get_contents('php://input');
    $headers = getallheaders();

    $event = $gateway->handleWebhook($rawBody, $headers);

    switch ($event->status) {
        case PaymentStatus::Success:
            // Mark order as paid: $event->orderId, $event->providerPaymentId
            break;

        case PaymentStatus::Failed:
            // Mark order as failed: $event->failureReason
            break;

        case PaymentStatus::Refunded:
            // Record refund
            break;
    }

    http_response_code(200);
    echo json_encode(['status' => 'ok']);
} catch (WebhookVerificationException $e) {
    // Signature mismatch - reject request!
    http_response_code(400);
    echo json_encode(['error' => $e->getMessage()]);
}

Advanced Features

Runtime Provider Switching

Switch active gateways on the fly (e.g. for fallback routing, multi-currency routing, or customer selection) without reinstantiating the gateway:

// Switch to Cashfree dynamically
$gateway->switchProvider('cashfree');

// Now create order or verify with Cashfree
$order = $gateway->createOrder($payload);

// Switch back to Razorpay
$gateway->switchProvider('razorpay');

Custom & Mock Provider Registration

Easily register a custom provider or a test mock at runtime:

use PHPCoreLab\PaymentGateways\Contracts\PaymentProviderInterface;
use PHPCoreLab\PaymentGateways\DTOs\OrderPayload;
use PHPCoreLab\PaymentGateways\DTOs\OrderResult;
use PHPCoreLab\PaymentGateways\DTOs\PaymentResult;
use PHPCoreLab\PaymentGateways\DTOs\RefundResult;
use PHPCoreLab\PaymentGateways\DTOs\PaymentEvent;

class CustomGatewayAdapter implements PaymentProviderInterface
{
    public function createOrder(OrderPayload $payload): OrderResult { /* ... */ }
    public function verifyPayment(string $orderId, array $data): PaymentResult { /* ... */ }
    public function refund(string $providerPaymentId, int $amountPaisa): RefundResult { /* ... */ }
    public function parseWebhook(string $rawBody, array $headers): PaymentEvent { /* ... */ }
    public function getName(): string { return 'custom_gateway'; }
}

// Register as an instance or closure factory
$gateway->registerProvider('custom_gateway', new CustomGatewayAdapter());

// Activate it
$gateway->switchProvider('custom_gateway');

PSR-3 Logging Support

Pass any PSR-3 compatible logger (e.g., Monolog, Laravel Log) to monitor payment events:

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('payment');
$logger->pushHandler(new StreamHandler(__DIR__ . '/payments.log'));

$gateway = new PaymentGateway($config, $logger);

Inspecting Available Providers

$providers = $gateway->availableProviders();
// ['razorpay', 'cashfree', 'phonepe', 'payu', 'paytm', 'juspay']

$currentProvider = $gateway->activeProvider()->getName();
// 'razorpay'

$env = $gateway->getEnvironment();
// Environment::Sandbox or Environment::Live

Framework Integrations

Laravel

1. Configuration (config/payment-gateways.php)

return [
    'active_provider' => env('ACTIVE_PROVIDER', 'razorpay'),
    'environment'     => env('ENVIRONMENT', 'sandbox'),
    'providers'       => [
        'razorpay' => [
            'sandbox_key_id'     => env('RAZORPAY_SANDBOX_KEY_ID'),
            'sandbox_key_secret' => env('RAZORPAY_SANDBOX_KEY_SECRET'),
            'live_key_id'        => env('RAZORPAY_LIVE_KEY_ID'),
            'live_key_secret'    => env('RAZORPAY_LIVE_KEY_SECRET'),
        ],
        'cashfree' => [
            'sandbox_app_id'     => env('CASHFREE_SANDBOX_APP_ID'),
            'sandbox_secret_key' => env('CASHFREE_SANDBOX_SECRET_KEY'),
            'live_app_id'        => env('CASHFREE_LIVE_APP_ID'),
            'live_secret_key'    => env('CASHFREE_LIVE_SECRET_KEY'),
        ],
        'phonepe' => [
            'sandbox_merchant_id' => env('PHONEPE_SANDBOX_MERCHANT_ID'),
            'sandbox_salt_key'    => env('PHONEPE_SANDBOX_SALT_KEY'),
            'sandbox_salt_index'  => env('PHONEPE_SANDBOX_SALT_INDEX', 1),
            'live_merchant_id'    => env('PHONEPE_LIVE_MERCHANT_ID'),
            'live_salt_key'       => env('PHONEPE_LIVE_SALT_KEY'),
            'live_salt_index'     => env('PHONEPE_LIVE_SALT_INDEX', 1),
        ],
        // ... other providers
    ],
];

2. Service Provider (app/Providers/AppServiceProvider.php)

use PHPCoreLab\PaymentGateways\PaymentGateway;
use PHPCoreLab\PaymentGateways\Core\GatewayConfig;
use Illuminate\Support\Facades\Log;

public function register(): void
{
    $this->app->singleton(PaymentGateway::class, function () {
        $config = GatewayConfig::fromArray(config('payment-gateways'));
        return new PaymentGateway($config, Log::channel('daily'));
    });
}

3. Controller (PaymentController.php)

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use PHPCoreLab\PaymentGateways\PaymentGateway;
use PHPCoreLab\PaymentGateways\DTOs\OrderPayload;
use PHPCoreLab\PaymentGateways\DTOs\PaymentStatus;

class PaymentController extends Controller
{
    public function __construct(private PaymentGateway $gateway) {}

    public function createOrder(Request $request)
    {
        $order = $this->gateway->createOrder(new OrderPayload(
            orderId:       'ORD-' . uniqid(),
            amountPaisa:   $request->integer('amount') * 100,
            customerName:  $request->user()->name,
            customerEmail: $request->user()->email,
            customerPhone: $request->user()->phone,
            returnUrl:     route('payment.callback'),
        ));

        return response()->json($order);
    }

    public function confirmPayment(Request $request, string $orderId)
    {
        $result = $this->gateway->verifyPayment($orderId, $request->all());

        if ($result->isSuccessful()) {
            return response()->json(['status' => 'success']);
        }

        return response()->json(['status' => 'failed', 'reason' => $result->failureReason], 422);
    }

    public function webhook(Request $request)
    {
        $event = $this->gateway->handleWebhook($request->getContent(), $request->headers->all());

        if ($event->status === PaymentStatus::Success) {
            // Update order status in database
        }

        return response()->json(['status' => 'ok']);
    }
}

Note: For Laravel, exclude /payment/webhook from CSRF protection in bootstrap/app.php (Laravel 11+) or app/Http/Middleware/VerifyCsrfToken.php (Laravel 10 and earlier).

Vanilla PHP

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PHPCoreLab\PaymentGateways\PaymentGateway;
use PHPCoreLab\PaymentGateways\Core\GatewayConfig;
use PHPCoreLab\PaymentGateways\DTOs\OrderPayload;

$config = GatewayConfig::fromArray([
    'active_provider' => 'cashfree',
    'environment'     => 'sandbox',
    'providers'       => [
        'cashfree' => [
            'sandbox_app_id'     => 'YOUR_APP_ID',
            'sandbox_secret_key' => 'YOUR_SECRET_KEY',
        ],
    ],
]);

$gateway = new PaymentGateway($config);

$result = $gateway->createOrder(new OrderPayload(
    orderId:     'ORDER_' . time(),
    amountPaisa: 19900,
));

header('Content-Type: application/json');
echo json_encode($result);

DTO Reference

OrderPayload

Property Type Default Description
orderId string required Your unique order reference ID
amountPaisa int required Amount in paise (100 paise = ₹1.00)
currency string 'INR' ISO currency code
customerName ?string null Customer's full name
customerEmail ?string null Customer's email address
customerPhone ?string null Customer's phone number
returnUrl ?string null URL redirected to after payment
cancelUrl ?string null URL redirected to if cancelled
description ?string null Note/description of the order
meta array [] Arbitrary custom metadata

OrderResult

Property Type Description
orderId string Your original order ID
providerOrderId string Gateway's order ID (e.g. order_abc or 12345)
amountPaisa int Order amount in paise
currency string Order currency code
paymentUrl ?string Hosted checkout/redirect URL (if applicable)
sdkPayload ?array Configuration payload for client SDKs
raw array Full raw gateway response

PaymentResult

Property Type Description
orderId string Your order reference ID
providerOrderId string Gateway's order identifier
providerPaymentId string Gateway's unique payment identifier
status PaymentStatus Enum: Success, Failed, Pending, Expired, Refunded, Cancelled
amountPaisa int Captured amount in paise
providerRef ?string Bank reference number (RRN, UTR)
failureReason ?string Failure message from provider if failed
raw array Complete raw verification response
isSuccessful() bool Helper method returns true if status is Success

RefundResult

Property Type Description
refundId string Unique refund reference ID
success bool Whether the refund was accepted
message ?string Provider status description or note
raw array Complete raw refund response

PaymentEvent (Webhook)

Property Type Description
orderId string Associated merchant order ID
providerOrderId string Associated gateway order ID
providerPaymentId string Associated gateway payment ID
status PaymentStatus Normalized transaction status
amountPaisa int Transaction amount in paise
providerRef ?string Bank reference number (UTR / RRN)
failureReason ?string Error or decline message if failed
raw array Full decoded webhook payload

Exceptions & Error Handling

All library exceptions extend PHPCoreLab\PaymentGateways\Exceptions\PaymentGatewayException:

PaymentGatewayException (RuntimeException)
├── ProviderException
├── WebhookVerificationException
└── ProviderNotFoundException
Exception Cause Properties
ProviderException Gateway API HTTP error or rejection $e->provider, $e->responseBody
WebhookVerificationException Invalid webhook signature or tampering detected $e->getMessage()
ProviderNotFoundException Specified provider is not registered in registry $e->getMessage()
use PHPCoreLab\PaymentGateways\Exceptions\ProviderException;
use PHPCoreLab\PaymentGateways\Exceptions\WebhookVerificationException;

try {
    $result = $gateway->verifyPayment($orderId, $data);
} catch (WebhookVerificationException $e) {
    // Signature manipulation or forged callback
} catch (ProviderException $e) {
    // API failure from provider
    echo "Gateway [{$e->provider}] returned error: " . $e->getMessage();
    print_r($e->responseBody);
}

Development & Testing

Running the Test Suite

composer test

Static Analysis (PHPStan Level 8)

composer analyse

Code Style (PSR-12)

composer cs

License

MIT License — Copyright (c) PHPCoreLab.
See LICENSE for details.