Integra con vexpay/vexpay-php
SDK oficial de PHP 8.1+, independiente de framework, con respuestas tipadas, reintentos seguros, verificación de webhooks y un cliente de pruebas en memoria.
Instalación
composer require vexpay/vexpay-php| Requisito | Compatible |
|---|---|
| PHP | 8.1 o superior |
| Cliente HTTP | Guzzle 7 u 8 (predeterminado), o cualquier cliente PSR-18 |
| Frameworks | Ninguno requerido — funciona en PHP puro, Symfony, Slim, WordPress y otros |
| Paquete | vexpay/vexpay-php en 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']) para un gateway local
$quote = $vexpay->quotes->retrieve(['usdAmount' => 25]);Los cuerpos de solicitud son arrays con los nombres de campo de la API (usdAmount, debtorBankCode, …). Las respuestas son objetos readonly tipados; los campos enum contienen un enum respaldado, o el string crudo cuando la API envía un valor más nuevo que tu SDK. Llama ->toArray() para la respuesta cruda. ¿Usas Laravel? Instala vexpay/laravel (ver Laravel).
Pago C2P
$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,
]);Sesión de checkout
$session = $vexpay->checkout->sessions->create([
'amountUsd' => 25,
'reference' => 'order-1042',
'allowedOrigins' => ['https://shop.example'],
]);
// Redirige a $session->url, o entrega $session->clientSecret a @vexpay/js en el navegador.
// Confirma el cumplimiento con GET o webhooks payment.* — nunca solo con eventos del navegador.Verificar 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();
// cumple desde $payment — luego responde 2xx
}Pruebas sin red
VexPay\Testing\FakeHttpClient responde cada operación con una respuesta válida (repitiendo los campos que enviaste), registra las solicitudes y acepta stubs por 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