import {
CallbackVerificationError,
InvoiceNotPaidError,
} from '@billions-works/sdk-ts';
try {
const verifiedInvoice = await api.verifyInvoicePaid({
id: request.body.id,
status: request.body.status,
paid_amount: request.body.paid_amount,
});
// Find the order by verifiedInvoice.order_no.
// Transition it to paid exactly once.
return response.status(200).send('OK');
} catch (error) {
if (
error instanceof InvoiceNotPaidError ||
error instanceof CallbackVerificationError
) {
// Reject or postpone processing. Do not mark the order as paid.
return response.status(202).send('Payment is not verified');
}
throw error;
}
<?php
use Billions\Exception\CallbackVerificationException;
use Billions\Exception\InvoiceNotPaidException;
try {
$verifiedInvoice = $api->verifyInvoicePaid([
'id' => $_POST['id'],
'status' => $_POST['status'],
'paid_amount' => $_POST['paid_amount'],
]);
// Find the order by $verifiedInvoice['order_no'].
// Transition it to paid exactly once.
} catch (InvoiceNotPaidException | CallbackVerificationException $exception) {
// Reject or postpone processing. Do not mark the order as paid.
}
curl --request GET \
--url "https://api.billions.works/public/v1/invoices/$BILLIONS_INVOICE_ID" \
--header "Content-Type: application/json" \
--header "x-api-key: $BILLIONS_API_KEY"
Add callback schema validation, order matching, and transactional idempotency
before using these illustrative handlers in production. With cURL, your
backend must also require
completed status and compare the API response with
the callback before marking the order as paid.