›
›
›
  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

Events and listeners.

Handle verified PayRex webhooks through typed, retry-safe Laravel listeners.

Every verified webhook dispatches PayrexWebhookReceived. When its type exists in config('payrex.webhooks.events'), the package also dispatches the mapped typed event.

Listen for a typed event

namespace App\Listeners;

use App\Models\Order;
use ByRcsc\LaravelPayrex\Events\PaymentIntentSucceeded;
use Illuminate\Contracts\Queue\ShouldQueue;

final class MarkOrderAsPaid implements ShouldQueue
{
    public function handle(PaymentIntentSucceeded $event): void
    {
        $intent = $event->event->paymentIntent();

        if ($intent === null) {
            return;
        }

        Order::query()
            ->where('payrex_payment_intent_id', $intent->id)
            ->whereNull('paid_at')
            ->update(['paid_at' => now()]);
    }
}

Laravel can discover the listener or you can register it explicitly in your application's event configuration.

Default event catalog

PayRex typeLaravel event
payment_intent.awaiting_capturePaymentIntentAwaitingCapture
payment_intent.succeededPaymentIntentSucceeded
setup_intent.succeededSetupIntentSucceeded
checkout_session.expiredCheckoutSessionExpired
refund.createdRefundCreated
refund.updatedRefundUpdated
payout.createdPayoutCreated
payout.depositedPayoutDeposited
billing_statement.createdBillingStatementCreated
billing_statement.updatedBillingStatementUpdated
billing_statement.deletedBillingStatementDeleted
billing_statement.finalizedBillingStatementFinalized
billing_statement.sentBillingStatementSent
billing_statement.marked_uncollectibleBillingStatementMarkedUncollectible
billing_statement.voidedBillingStatementVoided
billing_statement.paidBillingStatementPaid
billing_statement.will_be_dueBillingStatementWillBeDue
billing_statement.overdueBillingStatementOverdue
billing_statement_line_item.createdBillingStatementLineItemCreated
billing_statement_line_item.updatedBillingStatementLineItemUpdated
billing_statement_line_item.deletedBillingStatementLineItemDeleted

All typed events extend PayrexWebhookEvent.

Listen for every verified type

Use the generic event for audit logging or a PayRex type the installed package does not map yet:

use ByRcsc\LaravelPayrex\Events\PayrexWebhookReceived;

final class RecordPayrexEvent implements ShouldQueue
{
    public function handle(PayrexWebhookReceived $event): void
    {
        $event->type();
        $event->event->id;
        $event->event->type;
        $event->event->raw;
    }
}

The generic event fires even when a typed event fires.

Inspect the event envelope

$event->event is a readonly WebhookEvent:

$webhook = $event->event;

$webhook->id;
$webhook->type;
$webhook->livemode;
$webhook->pendingWebhooks;
$webhook->previousAttributes;
$webhook->resourceType();
$webhook->resourceData();
$webhook->resource();
$webhook->raw;

resource() hydrates a supported subject into PaymentIntent, Payment, PaymentMethod, Refund, CheckoutSession, SetupIntent, Customer, BillingStatement, BillingStatementLineItem, or Payout. It returns null for an unknown resource; the raw data remains available.

Convenience methods exist for common subjects:

$webhook->paymentIntent();
$webhook->payment();
$webhook->refund();
$webhook->checkoutSession();

Use resource() plus instanceof for the other resource types.

Match event types

is() accepts exact names and a trailing wildcard:

if ($webhook->is('refund.created', 'refund.updated')) {
    // ...
}

if ($webhook->is('billing_statement.*')) {
    // ...
}

Customize the map

Add an event type by mapping it to a class that extends PayrexWebhookEvent:

use App\Events\CustomerUpdatedByPayrex;

'events' => [
    // package defaults...
    'customer.updated' => CustomerUpdatedByPayrex::class,
],
namespace App\Events;

use ByRcsc\LaravelPayrex\Events\PayrexWebhookEvent;

final class CustomerUpdatedByPayrex extends PayrexWebhookEvent
{
}

The package validates this map during application boot. Keys must be non-empty strings and classes must extend PayrexWebhookEvent.

Idempotency

PayRex may deliver an event more than once. A listener should claim the event ID before performing one-time work:

if (! PayrexDelivery::query()->firstOrCreate([
    'event_id' => $event->event->id,
])->wasRecentlyCreated) {
    return;
}

// Perform the state transition once.

Back the event ID with a unique database index so two queue workers cannot claim it simultaneously. Also make the domain update itself conditional; this protects against retries that happen after the claim but before work finishes.

What to read next

  • Receiving webhooks to verify requests before these events are dispatched.
  • Managing endpoints to choose which event types PayRex sends.
  • Testing to fake typed events and signed deliveries.
PreviousReceiving webhooksNextManaging endpoints

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

View source

On this page

  1. Listen for a typed event
  2. Default event catalog
  3. Listen for every verified type
  4. Inspect the event envelope
  5. Match event types
  6. Customize the map
  7. Idempotency
  8. What to read next