›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-payrex
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Client and resources
  • Data objects and enums
  • Errors and retries
  • Pagination

Accepting payments

  • Payment intents
  • Checkout sessions
  • Setup intents
  • Payments and refunds

Customers and billing

  • Customers
  • Eloquent customers
  • Billing statements
  • Payouts

Webhooks

  • Receiving webhooks
  • Events and listeners
  • Managing endpoints

Advanced usage

  • Testing
  • Security and operations
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Client and resources
  • Data objects and enums
  • Errors and retries
  • Pagination

Accepting payments

  • Payment intents
  • Checkout sessions
  • Setup intents
  • Payments and refunds

Customers and billing

  • Customers
  • Eloquent customers
  • Billing statements
  • Payouts

Webhooks

  • Receiving webhooks
  • Events and listeners
  • Managing endpoints

Advanced usage

  • Testing
  • Security and operations
  • Troubleshooting

byrcsc/laravel-payrex · 1.x

Testing.

Test PayRex requests and webhooks without making network calls.

Laravel PayRex uses Laravel's HTTP client throughout, so Http::fake() prevents network calls and lets a test assert the exact request.

Fake a resource response

use ByRcsc\LaravelPayrex\Facades\Payrex;
use Illuminate\Support\Facades\Http;

it('creates a payment intent', function () {
    Http::fake([
        '*' => Http::response([
            'resource' => 'payment_intent',
            'id' => 'pi_test_1042',
            'amount' => 10_000,
            'currency' => 'PHP',
            'status' => 'awaiting_payment_method',
            'client_secret' => 'pi_test_1042_secret_test',
        ]),
    ]);

    $intent = Payrex::paymentIntents()->create(
        amount: 10_000,
        paymentMethods: ['card'],
        metadata: ['order_id' => '1042'],
    );

    expect($intent->id)->toBe('pi_test_1042');

    Http::assertSent(function ($request) {
        parse_str($request->body(), $body);

        return $request->method() === 'POST'
            && $request->url() === 'https://api.payrexhq.com/payment_intents'
            && $body['amount'] === '10000'
            && $body['payment_methods'] === ['card']
            && $body['metadata'] === ['order_id' => '1042'];
    });
});

Parameters are form-encoded, never JSON. POST and PUT send them as an application/x-www-form-urlencoded body; GET and DELETE send them in the query string, so assert those with $request->url() rather than $request->body(). Lists are encoded with empty brackets (payment_methods[]=card), nested associative keys are preserved (metadata[order_id]=1042), booleans become true/false, enums are unwrapped to their values, and nulls are dropped entirely.

Prevent unexpected network calls

Use Laravel's protection against un-faked requests in your test bootstrap:

use Illuminate\Support\Facades\Http;

Http::preventStrayRequests();

Then fake every PayRex call made by the behavior under test.

Test failures

Return a PayRex-shaped error document and assert the typed exception:

use ByRcsc\LaravelPayrex\Exceptions\InvalidRequestException;

Http::fake([
    '*' => Http::response([
        'errors' => [[
            'code' => 'parameter_invalid',
            'detail' => 'Amount is invalid.',
            'parameter' => 'amount',
        ]],
    ], 400),
]);

expect(fn () => Payrex::post('/payment_intents', ['amount' => 1]))
    ->toThrow(InvalidRequestException::class);

Use Http::failedConnection() to exercise an ApiConnectionException.

Test event listeners

The package command dispatches a synthetic generic and typed event:

php artisan payrex:webhook-test "payment_intent.succeeded"

It performs no network request and no signature check. Use it during local development to verify that event discovery, listener registration, and queues are wired correctly.

In automated tests, dispatch the typed event with a WebhookEvent:

use ByRcsc\LaravelPayrex\Data\WebhookEvent;
use ByRcsc\LaravelPayrex\Events\PaymentIntentSucceeded;
use Illuminate\Support\Facades\Event;

Event::fake();

$webhook = WebhookEvent::from([
    'id' => 'evt_test_1042',
    'type' => 'payment_intent.succeeded',
    'data' => [
        'resource' => [
            'resource' => 'payment_intent',
            'id' => 'pi_test_1042',
            'status' => 'succeeded',
        ],
    ],
]);

event(new PaymentIntentSucceeded($webhook));

Event::assertDispatched(PaymentIntentSucceeded::class);

Test your listener class directly when you want to assert domain changes.

Test the webhook route end to end

WebhookSignature::header() builds the same header PayRex sends, so a test can exercise the real route, middleware, and signature check:

use ByRcsc\LaravelPayrex\Events\PaymentIntentSucceeded;
use ByRcsc\LaravelPayrex\Support\WebhookSignature;
use Illuminate\Support\Facades\Event;

it('accepts a signed delivery', function () {
    config()->set('payrex.webhook_secret', 'whsk_test_signing_secret');

    Event::fake();

    $payload = json_encode([
        'id' => 'evt_test_1042',
        'resource' => 'event',
        'type' => 'payment_intent.succeeded',
        'data' => [
            'resource' => [
                'resource' => 'payment_intent',
                'id' => 'pi_test_1042',
                'status' => 'succeeded',
            ],
        ],
    ], JSON_THROW_ON_ERROR);

    $this->call(
        method: 'POST',
        uri: '/payrex/webhook',
        server: [
            'CONTENT_TYPE' => 'application/json',
            'HTTP_PAYREX_SIGNATURE' => WebhookSignature::header(
                $payload,
                'whsk_test_signing_secret',
            ),
        ],
        content: $payload,
    )->assertOk()->assertJson([
        'received' => true,
        'id' => 'evt_test_1042',
    ]);

    Event::assertDispatched(PaymentIntentSucceeded::class);
});

Pass timestamp: to produce a stale delivery and assert the 400, or livemode: true for a live-mode signature. This is the only way to cover signature verification; payrex:webhook-test deliberately skips it.

Test the Eloquent concern

The HasPayrexCustomer concern needs a model table with its configured ID column. Use an in-memory database or a test migration, fake the customer response, then assert both the remote request and persisted ID:

Http::fake([
    '*' => Http::response([
        'resource' => 'customer',
        'id' => 'cus_test_1042',
        'name' => 'Ada Lovelace',
        'email' => 'ada@example.com',
        'currency' => 'PHP',
    ]),
]);

$customer = $user->createAsPayrexCustomer();

expect($customer->id)->toBe('cus_test_1042')
    ->and($user->fresh()->payrex_customer_id)->toBe('cus_test_1042');

Test against a local stub

Override the base URL in a test environment when an integration test needs a local HTTP server:

PAYREX_BASE_URL=http://127.0.0.1:8787

Do not point automated tests at a real PayRex account unless the test is explicitly designed, isolated, and approved for that environment.

Contributing to the package

The package repository's own suite needs no external database, .env, or PayRex account:

composer install
composer test
composer analyse
vendor/bin/pint --test

What to read next

  • Client and resources to identify the request path a test should fake.
  • Receiving webhooks to understand the signature checks exercised by webhook tests.
  • Errors and retries to cover failure responses.
PreviousManaging endpointsNextSecurity and operations

Laravel PayRex is an unofficial community SDK and is not affiliated with PayRex.

View source

On this page

  1. Fake a resource response
  2. Prevent unexpected network calls
  3. Test failures
  4. Test event listeners
  5. Test the webhook route end to end
  6. Test the Eloquent concern
  7. Test against a local stub
  8. Contributing to the package
  9. What to read next