Hosted Checkout
Hosted checkout is the simplest integration. PayElect renders the payment page — your customer is redirected to a PayElect-hosted URL, selects a provider, authenticates, and completes payment. You receive the result via a return redirect and a webhook.
You do not need to build or style a payment form. PCI scope is minimal because no card data transits your servers.
Flow overview
| # | Actor | Action |
|---|---|---|
| 1 | Your server | POST /authentication/token → receive access_token |
| 2 | Your server | POST /payment/create with amount, currency, return_url, cancel_url → receive payment_url |
| 3 | Your server | HTTP 302 redirect the customer to payment_url |
| 4 | Customer | Selects provider on PayElect checkout page, authenticates with wallet, confirms payment |
| 5 | PayElect | Processes the payment, fires payment.succeeded webhook to your endpoint |
| 6 | PayElect | Redirects customer browser to your return_url with result params in query string |
| 7 | Your server | Webhook handler verifies HMAC signature, fulfils the order |
Return URL params are not authoritative.
Always fulfil the order from the webhook, not from the return redirect. A malicious user could craft a fake success redirect.
Creating the payment
A minimal payment create request:
curl -X POST https://api.payelecthq.com/pay/api/v1/payment/create \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"amount": "150000",
"currency": "GNF",
"country": "GN",
"return_url": "https://shop.example.com/orders/8821/confirm",
"cancel_url": "https://shop.example.com/orders/8821/cancel",
"custom": "order_8821",
"idempotency_key": "ord-8821-v1"
}'
Response:
{
"status": "success",
"data": {
"token": "pymt_01J4ABCDEFGHIJKLMNOPQRSTU",
"payment_url": "https://api.payelecthq.com/pay/v1/user/authentication/form/pymt_01J4ABCDEFGHIJKLMNOPQRSTU"
}
}
Handling the return URL
After payment completes (success, failure, or cancellation), the customer's browser is redirected to your return_url or cancel_url. Query string params are appended:
GET /orders/8821/confirm
?type=success
&data[token]=pymt_01J4ABCDEFGHIJKLMNOPQRSTU
&data[trx_id]=TRX0000012345678
&data[amount]=150000
&data[custom]=order_8821
&message[code]=200
GET /orders/8821/confirm
?type=error
&data[token]=pymt_01J4ABCDEFGHIJKLMNOPQRSTU
&message[code]=402
&message[error][0]=Payment+was+declined
Recommended return URL handler (PHP/Laravel):
public function paymentReturn(Request $request, $orderId): Response
{
// Show a "processing" page immediately; rely on webhook for fulfilment.
// Never fulfil the order here — webhook hasn't been verified yet.
$type = $request->query('type');
return match ($type) {
'success' => view('orders.processing', ['orderId' => $orderId]),
'pending' => view('orders.pending', ['orderId' => $orderId]),
default => view('orders.failed', ['orderId' => $orderId,
'error' => $request->input('message.error.0')]),
};
}