Web Payment Integration
Web Payment Integration
This document describes how to initiate a payment request and process the payment notification
after the payment has been executed by the payer.
Integration is a quick (I promise!) 2 step process :
1. Create a payment link
2. Handle instant payment notification (IPN)
Environment URLs
Name Console WebPay
Test https://dashboard.sandbox.centralbill.app https://pay.sandbox.centralbill.app
Production https://dashboard.centralbill.app https://pay.centralbill.app
Step 1: Create a payment link
The payment link is a URL that displays the web payment page. The base URL to invoke for
process payment depends of environment used.
Below is an example of a URL that allows you to start a payment by your customer :
https://pay.centralbill.app/?applicationId=fbab3ccc-719e-11ed-93ad-
02420a0003c1&invoice[id]=1&invoice[customerId]=johndoe%40example.com&invoice[tot
alAmount][amount]=100&invoice[totalAmount][currency]=XOF&invoice[issuedAt]=2022-
12-12T00%3A00%3A00%2B00%3A00&invoice[dueDate]=1970-01-
01T00%3A00%3A00%2B00%3A00&description=ACME+-
+Facture+%23107285&signature=9407f193b8a53f68e6184ef28cffc7a7524cff81d6e6dd7
6a4c624b990a3e1cf&callbackUrl=https%3A%2F%2Facme.net%2Fmodules%2Fgateway
s%2Fcallback%2Fcentralbill.php&redirectUrl=https%3A%2F%2Facme.net%2Fviewinvoic
e.php%3Fid%3D1
URL Query Fields
Include these fields in your URL query.
Name Type Description
applicationId string The identifier of the merchant application.
Name Type Description
invoice[id] string The invoice unique identifier.
invoice[customerId] string The invoice customer unique identifier.
invoice[totalAmount]
float The total amount to be paid for the invoice.
[amount]
invoice[totalAmount] The currency of the total amount to be paid for the
string
[currency] invoice. The currency must be in ISO 4217 format.
The date on which the invoice was issued. The date must
invoice[issuedAt] string
be in ISO 8601 format.
The date on which the invoice will be due. The date must
invoice[dueDate] string
be in ISO 8601 format.
Une description qui permettra à vos client de reconnaitre
description string
le paiment.
signature string The payment signature.
callbackUrl
string The callback URL where the payment notification is sent.
(Optional)
redirectUrl
string The URL where the customer is redirected after payment.
(Optional)
Generate payment signature
To generate a payment signature you must combine the following payment informations:
application.id , invoice.id , invoice.customerId , invoice.totalAmount.amount ,
invoice.totalAmount.currency and application.secret .
The identifier and secret of the application can be retrieved from your administration console.
Below is an example code in PHP to generate a signature :
$applicationId = 'fbab3ccc-719e-11ed-93ad-02420a0003c1';
$applicationSecret = 'app!secret';
$invoiceId = '1';
$invoiceCustomerId = 'johndoe@example.com';
$invoiceTotalAmountAmount = 1000;
$invoiceTotalAmountCurrency = 'XOF';
$signature = hash('sha256', sprintf(
'%s,%s,%s,%s,%s,%s',
$applicationId,
$invoiceId,
$invoiceCustomerId,
$invoiceTotalAmountAmount,
$currency,
$applicationSecret
));
Step 2: Handle instant payment notification (IPN)
A payment notification is sent after each payment to a callback url configured either in your
dashboard or defined in the payment link.
Instant Payment Notification request
POST callbackUrl Instant Payment Notification method
Response codes
Success
Code Reason
200 - Ok Request was successful.
204 - No Content Request was successful and has no content.
Error
Code Reason
400 - Bad Request Some content in the request was invalid.
401 - Unauthorized User must authenticate before making a request.
403 - Forbidden Policy does not allow current user to do this operation.
Request parameters
Name In Type Description
id body string The transaction unique identifier.
result body object The transaction result.
Name In Type Description
result.origin body object The transaction result originator.
The transaction result status. The
avalaible values are: COMPLETED ,
result.status body enum
NEEDS_MERCHANT_VALIDATION , CANCELED ,
REFUSED , FAILED , and REVERSED .
result.statusReason body string The transaction result status reason.
invoice body object The information of the invoice paid.
invoice.id body string The invoice unique identifier.
The invoice customer unique
invoice.customerId body string
identifier.
The total amount paid for the
invoice.totalAmount.amount body float
invoice.
The currency of the total amount
invoice.totalAmount.currency body string paid for the invoice. The currency
must be in ISO 4217 format.
The date on which the invoice was
invoice.issuedAt body string issued. The date must be in ISO
8601 format.
The date on which the invoice will be
invoice.dueDate body string due. The date must be in ISO 8601
format.
The amount of payment fees applied
paymentFee.amount body float
to the transaction.
The currency of payment fees
applied to the transaction. The
paymentFee.currency body string
currency must be in ISO 4217
format.
The request is secured by the HTTP
Authorization header string
Signature Authentication protocol.
Content-Type header string Set the MIME type for the request.
Transaction status
Name Description
The transaction was successful and the money is in
COMPLETED
the recipient’s account.
NEEDS_MERCHANT_VALIDATION Either you awaiting merchant validation.
You canceled your payment, and the money was
CANCELED
credited back to your account.
The recipient didn’t receive your payment. If you still
REFUSED want to make your payment, we recommend that
you try again.
Your payment didn’t go through. We recommend
FAILED
that you try your payment again.
REVERSED Either you canceled the transaction or we did.
Request example with password authentication
curl -X POST -i 'callbackUrl' \
-H 'Host: acme.org' \
-H 'Content-Type: application/json' \
-H 'Date: Thu, 01 Dec 2022 19:08:22 +0000' \
-H 'Digest: SHA-
256=NjQzMWNjYWMwNjdkYTA5ZWFiZTJiZDMyMDU3NmQxOWEyM2RmNTYyMzMyMDcyOTliMTJmMzAxYjY1ZDZkOT
YzMg==' \
-H 'Signature: keyId="fbab3ccc-719e-11ed-93ad-02420a0003c1",algorithm="hmac-
sha256",headers="(request-target) content-type date
digest",signature="fiFBCK8NWWhvk6fJul8ezzpVXSh9q30VRO8qn3XGxTQ="' \
-H 'Authorization: Signature keyId="2bc56634-673c-11ed-acf4-
0242ac13000e",algorithm="hmac-sha256",headers="(request-target) content-type date
digest",signature="fiFBCK8NWWhvk6fJul8ezzpVXSh9q30VRO8qn3XGxTQ="' \
-d '{
"id": "63a368858622d5ded108e4b3",
"payment": {
"id": "63a368858622d5ded108e4b2",
"type": "full",
"application": {
"id": "b3695b9c-816b-11ed-8083-32706358435f",
"name": "banking"
},
"invoice": {
"id": "1",
"customerId": "1",
"totalAmount": {
"amount": 1000,
"currency": "XOF"
},
"issuedAt": "2022-12-21T20:11:49+00:00"
},
"extras": [],
"totalAmountAlreadyPaid": {
"amount": 1000,
"currency": "XOF"
}
},
"invoice": {
"id": "1",
"customerId": "1",
"totalAmount": {
"amount": 1000,
"currency": "XOF"
},
"issuedAt": "2022-12-21T20:11:49+00:00"
},
"paymentFee": {
"amount": 0,
"currency": "XOF"
},
"result": {
"origin": "processor",
"status": "COMPLETED"
}'
How validate Payment Notification request?
The Instant Payment Notification (IPN) request is secured from HTTP Signature Authentication.
Below is an example code in PHP to handle payment notification request :
// Fetch application secret configuration parameters.
$applicationSecret = 'app!secret';
$body = json_decode(file_get_contents('php://input'), true);
$transactionId = $body['id'];
$transactionStatus = $body['result']['status'];
$invoiceId = $body['invoice']['id'];
$invoiceTotalAmount = $body['invoice']['totalAmount']['amount'];
$paymentFee = $body['paymentFee']['amount'];
/**
* Validate callback authenticity.
*/
$components = [];
$headers = array_change_key_case(getallheaders(), \CASE_LOWER);
foreach (explode(',', $headers['signature'] ?? '') as $value) {
if (!$component = explode('=', $value, 2)) {
continue;
$components[$component[0]] = trim($component[1], '"');
if (array_diff(['keyId', 'algorithm', 'headers', 'signature'],
array_keys($components))) {
die('Payment failed');
if ('hmac-sha256' !== $components['algorithm']) {
die('Payment failed');
$signature = [];
foreach (explode(' ', strtolower($components['headers'])) as $header) {
$signature[] = sprintf('%s: %s', $header, '(request-target)' !== $header ?
$headers[$header] : sprintf('%s %s', strtolower($_SERVER['REQUEST_METHOD']),
$_SERVER['REQUEST_URI']));
}
if (false === hash_equals(base64_encode(hash_hmac('sha256', implode(\PHP_EOL,
$signature), applicationSecret, true)), $components['signature'])) {
die('Payment failed');
}
/**
* Validate transaction status.
*/
if ('COMPLETED' !== transactionStatus) {
die('Payment failed');
}
// Busines Logic here
// ...
Transaction Status
The transaction status value and description
Value Description
We’re reviewing the transaction. We’ll send your payment to
PENDING
the recipient after your payment source has been verified.
We’re processing your payment and the transaction should be
PROCESSING
completed shortly.
You canceled your payment, and the money was credited
CANCELED
back to your account.
The transaction was successful and the money is in the
COMPLETED
recipient’s account.
The recipient didn’t receive your payment. If you still want to
REFUSED
make your payment, we recommend that you try again.
Your payment didn’t go through. We recommend that you try
FAILED
your payment again.
REVERSED Either you canceled the transaction or we did.
NEEDS_MERCHANT_VALIDATION Either you awaiting merchant validation.