Developer guide
VEXPay siteAPI reference
Browse documentation

Integrate with vexpay/laravel

Laravel 12/13 package: facade, verified webhooks as events, Billable checkouts with a synced payment record, marketplace sellers, Blade checkout, and test fakes.

Install

Composerbash
composer require vexpay/laravel
php artisan vexpay:install
php artisan migrate
RequirementSupported
Laravel12 or 13 (every release still receiving security fixes)
PHP8.2 or later (Laravel 13 needs 8.3)
HTTP clientThe Guzzle 7 or 8 your app already has
Packagevexpay/laravel on Packagist (packagist.org/packages/vexpay/laravel); installs vexpay/vexpay-php
.envbash
VEXPAY_API_KEY=vk_test_replace_me
VEXPAY_WEBHOOK_SECRET=whsec_replace_me

Register https://your-app.example/vexpay/webhook as a webhook endpoint in the portal, then check delivery with php artisan vexpay:webhook-test. The VexPay facade (or an injected VexPay\VexPayClient) exposes the full PHP SDK.

Accept payments with Billable

PHPphp
use VexPay\Laravel\Billable;

class Order extends Model
{
    use Billable;
}

// In a controller: redirects (303) to the hosted checkout, or returns
// { id, url, clientSecret } for JSON requests.
return $order->checkout($order->total_usd, [
    'description' => "Pedido #{$order->number}",
    'successUrl' => route('orders.thanks', $order),
]);

checkout() creates a checkout session and stores a PENDING row in vexpay_payments linked to the model. Embed instead of redirecting with <x-vexpay-checkout :checkout="$checkout" />, which sends only the session client secret to the browser.

Fulfill from billing events

Verified payment.* webhooks update the local record. Status only moves forward (PENDING → COMPLETED / FAILED / CANCELED, COMPLETED → REVERSED), so retries and out-of-order deliveries are harmless and billing events fire exactly once per transition.

PHPphp
use VexPay\Laravel\Events\Billing\PaymentSucceeded;

Event::listen(function (PaymentSucceeded $event) {
    $event->billable()->markPaid($event->payment->payment_id);
});

Marketplace sellers

PHPphp
use VexPay\Laravel\HasVexPayMerchant;

class Seller extends Model
{
    use HasVexPayMerchant;
}

$seller->createAsVexPayMerchant([
    'name' => 'María Pérez',
    'identification' => 'V12345678',
    'contactEmail' => 'maria@example.com',
    'contactPhone' => '04141234567',
]);
$seller->payout(1523.40, 'Venta #991', 'order-991'); // same reference never pays twice

Testing

PHPphp
use VexPay\Laravel\Facades\VexPay;
use VexPay\Laravel\Testing\InteractsWithVexPay;

VexPay::fake();
$this->post(route('orders.pay', $order))->assertRedirect();
VexPay::assertCheckoutCreated(25.00);

$this->postVexPayPaymentWebhook($order->vexpayPayments()->first(), 'payment.completed')
    ->assertNoContent();