Result Notification
After an order completes, the BBMSL Online Payment Gateway sends the payment result to your backend via a POST callback. Your backend must handle the result and reply with an acknowledgement.
Set up your API credentials and understand how signing works before implementing notifications. See Integration Setup.
Acknowledge notifications
Your notification endpoint must return a plain-text OK response with an HTTP 2XX status code to acknowledge receipt. The BBMSL Online Payment Gateway treats any other response as a failed delivery and schedules a retry.
Always use the query API alongside callback notifications to reconcile transaction results. Notifications may be delayed or lost due to network conditions. See Query API for details.
Retry schedule
If the gateway does not receive a successful acknowledgement, it retries delivery at the following intervals:
| Attempt | Delay |
|---|---|
| 1 | 15 s |
| 2 | 15 s |
| 3 | 30 s |
| 4 | 1 min |
| 5 | 2 min |
| 6 | 5 min |
| 7 | 5 min |
| 8 | 10 min |
| 9 | 20 min |
| 10 | 30 min |
| 11 | 30 min |
| 12 | 60 min |
| 13 | 60 min |
| 14 | 2 h |
| 15 | 4 h |
Retries stop when the gateway receives a successful acknowledgement or when the maximum of 15 attempts is reached. The gateway cannot guarantee successful delivery even after all retry attempts.
Design for idempotency
The gateway may deliver the same notification more than once due to network fluctuations or other transient errors. Your backend must implement idempotent processing — deduplicate incoming notifications by orderId or merchantReference and always return HTTP 2XX even for duplicate deliveries.
Receive a notification
Provide a REST API endpoint for the gateway to POST payment results to. Configure the URL using the callbackUrl.notify or notifyUrl parameter when creating a payment request.
- Request method:
POST - Expected response:
OK(plain text, HTTP 2XX)
Payment success notification (Hosted Model / Direct Model)
{
"amount": "15.00",
"maskedPan": "411111XXXXXX1111",
"orderId": "534027",
"signature": "a6+r+VKPlerOFkIFB5El5zXYsIIKGYtul1l/RMGQwf6DJtOe1DPxejffj5iSGhlAqyEJlAontp2EwNpIJ0mdl79RaTfxFvF1rkvNM2tQpQLPMr5+Bqb3YeVN2W7Un/yWQgkHCkFkEhJFx//BLAqkde+xHCnl9fkOxok/3UVBiM6pPbgE0BbLutsFGJ9I511cMS4zPTT4nW3Tet4NNvIelSDNoYjaE8eeoG+v34+9y7Oo/2mtz7maus0suLVCG/juAytPCAdFqijsAdrojSs3p5k1zTm737hpusJh3LiInTkh8lNF8elRmJkhiAN0s7UzpFiHx2nwWnwP3V+qm/D2BA==",
"cardType": "VISA",
"updateTime": "2025-05-13T03:46:06+0000",
"merchantReference": "merRef1747107896496",
"status": "SUCCESS"
}
Add token success notification
{
"userId": "userName",
"tokenId": "12541",
"type": "AddToken",
"maskedPan": "4325xxxxxxxx2654",
"signature": "c1hTR2RBNHRSNEIwd25GNk5yOFNocGZOTXRISVNXdXpMcGRLb05Xc2tJZ0Njc3BNVkZGemdrZXo0QnJtdFlYa01xWmgxdHl6LzhzTk5VM0YyVlR1MGZPeCtaUDRDbm1Wak51OGJjaXU0aFR0bnl0QTNZMUdaL3lYQVVEK21WWUdYZXlETzNmSHJxRGRJN2szeFYvUThGQ09kMGN1bFRzTjZSUk14TVpxK29xUjJ4K0VqT1hWb2ZwN0JaSndoUUU4VXM0QWw1NzNGUXo1RUhEdkNMeDM1bHEyaG9NaFhMQ1ZMVkRCSGNwQ2dvdHVZNG1nOTFNWGgvcXFjRkdZL2hRS2hHZFdBYlo5dGNwMlE1czJFU2gzN3JxeG5Pd1pycmVwSzhOQzZ2TUJQVWlTUHhRZWZwZXYybkcwSnpBSE9qUlBiQlhZdzFYQlM2UkJZS0FtdWZaWmlRPT0="
}
Verify notification signature
Each notification includes a signature field. Verify it using the BBMSL public key to confirm the message was sent by BBMSL and has not been tampered with.
Use the BBMSL public key obtained during Integration Setup to verify notification signatures.
Follow these steps to verify the signature:
- Remove the
signaturefield from the notification payload. - Sort the remaining fields alphabetically by key.
- Join all key-value pairs with
&to form the pre-verify string:amount=15.00&cardType=VISA&maskedPan=411111XXXXXX1111&merchantReference=merRef1747107896496&orderId=534027&status=SUCCESS&updateTime=2025-05-13T03:46:06+0000 - Verify the signature against the pre-verify string using SHA256WithRSA and the BBMSL public key.
The BBMSL test environment public key for verifying notifications:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkDecXu4GFMxCqp4pjfwtN1nSQiV9kmdcBMnKq5IeLB6BYWOENqeY+JFftnNaxHOgnhOrbrl71D6G57G7rhNLClgBNerB7mINDBwvENkEVq6zNbJsjOJekJtTVkxs7KoBip44odCBmElCFrUsr0qOr10kzUzYHXXEUpTqQon3jDGm+EkFoNv3RLwn0ZWuwid5kuk6tZ0Xj3OxiKTrzXK2STjzJ8Q25e9CKbO03fpaMSpBRrkuA1NHRQoSO0ew6lGE4swQ+dseVbh+z7YFVUWqDyjJ6pB+F3p4vDniw4r9/rE+ikP0eLMg99vWDjuQbPtUHYaQtMYNSzrmcTkBCGkt6QIDAQAB
Code samples
Build the pre-verify string:
- Java
- PHP
public static String createPreVerifyString(Map<String, String> params) {
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
<?php
function createPreVerifyString($params){
ksort($params);
$str = json_encode($params);
$prestr = '';
$index = 0;
foreach($params as $key => $value) {
echo "{$key} => {$value} ";
if ($index == count($params) - 1) {
$prestr = $prestr . $key . "=" . $value;
} else {
$prestr = $prestr . $key . "=" . $value . "&";
}
$index++;
}
return $prestr;
}
?>
Verify the signature:
- Java
- PHP
private static final String KEY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";
private static final String DEFAULT_CHARSET = "UTF-8";
public static boolean verify(String content, String publicKey, String sign) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
return signature.verify(Base64.decode(sign));
}
<?php
$publicKey = "BBMSL public key";
$publicKeyPem = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publicKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
$signature = "Signature in notification";
$signature = base64_decode($signature);
$result = openssl_verify($content, $signature, $publicKeyPem, OPENSSL_ALGO_SHA256);
?>