Integrate with vexpay/vexpay-php
Official framework-agnostic PHP 8.1+ SDK with typed responses, safe retries, webhook verification, and an in-memory test client.
Install
composer require vexpay/vexpay-php| Requirement | Supported |
|---|---|
| PHP | 8.1 or later |
| HTTP client | Guzzle 7 or 8 (default), or any PSR-18 client |
| Frameworks | None required — works in plain PHP, Symfony, Slim, WordPress, and others |
| Package | vexpay/vexpay-php on Packagist (packagist.org/packages/vexpay/vexpay-php) |
use VexPay\VexPayClient;
$vexpay = new VexPayClient(getenv('VEXPAY_API_KEY'));
// new VexPayClient(['api_key' => ..., 'base_url' => 'http://localhost:3010']) for a local gateway
$quote = $vexpay->quotes->retrieve(['usdAmount' => 25]);Request bodies are arrays with the API field names (usdAmount, debtorBankCode, …). Responses are typed readonly objects; enum fields hold a backed enum, or the raw string when the API sends a value newer than your SDK. Call ->toArray() for the raw response. Using Laravel? Install vexpay/laravel instead (see Laravel).
C2P payment
$payer = [
'usdAmount' => 12.5,
'debtorId' => 'V12345678',
'debtorCellPhone' => '584121234567',
'debtorBankCode' => 102,
'externalRef' => 'order_1042',
];
$intent = $vexpay->payments->c2p->request($payer);
$receipt = $vexpay->payments->c2p->execute($payer + [
'intentId' => $intent->intentId,
'token' => $customerToken,
]);Checkout session
$session = $vexpay->checkout->sessions->create([
'amountUsd' => 25,
'reference' => 'order-1042',
'allowedOrigins' => ['https://shop.example'],
]);
// Redirect to $session->url, or give $session->clientSecret to @vexpay/js in the browser.
// Confirm fulfillment with GET or payment.* webhooks — never from browser events alone.Verify webhooks
use VexPay\Exception\SignatureVerificationException;
use VexPay\Webhook;
try {
$event = Webhook::constructEvent(
file_get_contents('php://input'),
$_SERVER['HTTP_VEXPAY_SIGNATURE'] ?? null,
getenv('VEXPAY_WEBHOOK_SECRET'),
);
} catch (SignatureVerificationException) {
http_response_code(400);
exit;
}
if ($event->event === 'payment.completed') {
$payment = $event->payment();
// fulfill from $payment — then respond 2xx
}Test without the network
VexPay\Testing\FakeHttpClient answers every operation with a valid response (echoing the fields you sent), records requests, and accepts stubs keyed by operationId.
use VexPay\Testing\FakeHttpClient;
use VexPay\VexPayClient;
$http = new FakeHttpClient(['Payouts_create' => FakeHttpClient::error(409, 'external_ref_conflict')]);
$vexpay = new VexPayClient(['api_key' => 'vk_test', 'http_client' => $http]);
$vexpay->checkout->sessions->create(['amountUsd' => 25, 'reference' => 'order-1042']);
$http->recorded('CheckoutSessions_create')[0]->body['amountUsd']; // 25