Connect to PayAPI
BBMSL Online Payment Service provides various APIs, which are named PayAPI for processing payment requests from the merchant. The APIs allow sensitive payment data to be exchanged between the merchant's backend and BBMSL accurately and securely.
While there are number of APIs available under different integration models, they are all standardized with the following characteristics,
Identification
Every onboarded merchant will be assigned to a merchant account with a unique merchant ID. The merchant is required to provide the merchant ID in every PayAPI request.
Connection Security
All APIs are protected by Transport Layer Security (TLS) protocol and whitelisting strategy. The request can only function properly over HTTPS connection, HTTP connection should not work.
Authentication and Message Security
Each message request to PayAPI is signed by the RSA key pair for verification. BBMSL authenticates the integrity of the merchant request by its digital signature. The signing details are included in the next section.
Signing PayAPI request
Each PayAPI request should include a signature signed by the merchant. Before performing any API request, the merchant needs to generate its own RSA key pairs (public and private key) and share the public key with BBMSL. The merchant should use the private key to sign the request message, and BBMSL will verify the signature with the shared public key.
Signature is not an independent API. It is a cryptographic measure to ensure integrity and non-repudiation.
About the signing
- Signing algorithm: 2048 bits RSA
- Hashing algorithm: SHA256
Key Generation using OpenSSL
You are not limited to use OpenSSL, you can use any tools to generate the key pair.
- Generate a new RSA keys pair
$ openssl genrsa -out rsa_private_key.pem 2048
- Export public key
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
Exchange Public Key
After the RSA key pair is generated, you must exchange the public key with the BBMSL for signature verification by completing the following steps:
- Remove the public key header, footer and all line break
\n
from the following key string.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxm/VrrMFmczDa+l+21Uc
wYU+wDdL074DnIRsaLCVqcVRPMPrQiq1og3N1Li9rneMWALHAhXKyH101BNOGYW2
uiZgWLPkz6dcYgd1WiCKsOcks7E8Kn9jH0PB+1issv9qk8aLHysiscIajWU69pho
GhGcsJu9uk2GdW0zo6I+9vBSE2l8wfG0Sy3sVZeYzm/nmCC9UgI1oWMCLrO3Y43l
896dItR9z8SAo3Ao77gz6UmJs32zHRM6UA5lv+ssYAZiS8OkVLCTx/DVcKyNvFAK
aoBDYvy1wOX+2o62cANrj0J7ybQ9M1VurQuEVeOuKFjT8GCO9DcvCcUaj3WxNlf3
/QIDAQAB
-----END PUBLIC KEY-----
- Upload the processed key string below to BBMSL Merchant Portal and activate the key.
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxm/VrrMFmczDa+l+21UcwYU+wDdL074DnIRsaLCVqcVRPMPrQiq1og3N1Li9rneMWALHAhXKyH101BNOGYW2uiZgWLPkz6dcYgd1WiCKsOcks7E8Kn9jH0PB+1issv9qk8aLHysiscIajWU69phoGhGcsJu9uk2GdW0zo6I+9vBSE2l8wfG0Sy3sVZeYzm/nmCC9UgI1oWMCLrO3Y43l896dItR9z8SAo3Ao77gz6UmJs32zHRM6UA5lv+ssYAZiS8OkVLCTx/DVcKyNvFAKaoBDYvy1wOX+2o62cANrj0J7ybQ9M1VurQuEVeOuKFjT8GCO9DcvCcUaj3WxNlf3/QIDAQAB
- Obtain BBMSL public key. Use the BBMSL public key to verify the notification signature. See Verify notification signature.
note
Please contact your relationship manager for the public key
Signing the Request
Prepare the request parameters in JSON format, and perform the following steps to sign the message,
- Prepare the content to be signed like the following,
{
"merchantId": "111",
"amount": 11.5,
"merchantReference": "OnlineReference1649431783807",
"callbackUrl": {
"success": "https://yourDomain/online-test/success",
"fail": "https://yourDomain/online-test/fail",
"cancel": "https://yourDomain/online-test/cancel",
"notify": "https://yourBackendApiEndpoint/online-test/notify"
},
"isRecurring": false,
"lineItems": [
{
"quantity": 1,
"priceData": {
"unitAmount": 1.5,
"name": "Test online"
}
},
{
"quantity": 1,
"priceData": {
"unitAmount": 10,
"name": "Ten dollars"
}
}
]
}
Hash the JSON content by using SHA256withRSA algorithm. Then use the merchant's RSA private key to sign it as the signature. The length of the RSA key must be 2048 bits.
Base64 encode the signature, a sample result is shown below,
mRcV8hQPP60VVPtve3Zwkvxt0lLuAEwKaheuNypq6u4mXkJN1LTiJ9xoZcO1rIba8q94Lsp1yDTkpjWWz964uYKSxhSw0CqFaXVz77zTeltWa59d6GpEyHwJBrzLKN5GhcVIYibbehd4805Z/nnomwteQuuCyBHbD5HNcodj3VAoNxvNuw8QeVKin81umpKl/bx9XRumUtLcTJ92E+Ob+d1Y75r9Xd4OT3WEU6XfaLau/1oAb33Jxvcj4r1cxyEXPnx+SUF/nNZHQPPSyfpdnS5pf8Ew55mAIXt1eCZQF0LKXtS10QstBfT3RDXPmugPiy0JXtX8HJ9s7hDsfdFocQ==
- Use the obtained string as the value of the
signature
parameter. The following sample shows a whole API request,
{
"request": "{\"merchantId\":\"111\",\"amount\":11.5,\"merchantReference\":\"OnlineReference1649431783807\",\"callbackUrl\":{\"success\":\"https://yourDomain/online-test/success\",\"fail\":\"https://yourDomain/online-test/fail\",\"cancel\":\"https://yourDomain/online-test/cancel\",\"notify\":\"https://yourBackendApiEndpoint/online-test/notify\"},\"isRecurring\":false,\"lineItems\":[{\"quantity\":1,\"priceData\":{\"unitAmount\":1.5,\"name\":\"Test online\"}},{\"quantity\":1,\"priceData\":{\"unitAmount\":10,\"name\":\"Ten dollars\"}}]}",
"signature": "mRcV8hQPP60VVPtve3Zwkvxt0lLuAEwKaheuNypq6u4mXkJN1LTiJ9xoZcO1rIba8q94Lsp1yDTkpjWWz964uYKSxhSw0CqFaXVz77zTeltWa59d6GpEyHwJBrzLKN5GhcVIYibbehd4805Z/nnomwteQuuCyBHbD5HNcodj3VAoNxvNuw8QeVKin81umpKl/bx9XRumUtLcTJ92E+Ob+d1Y75r9Xd4OT3WEU6XfaLau/1oAb33Jxvcj4r1cxyEXPnx+SUF/nNZHQPPSyfpdnS5pf8Ew55mAIXt1eCZQF0LKXtS10QstBfT3RDXPmugPiy0JXtX8HJ9s7hDsfdFocQ=="
}
signing the request
The value of request
key must be in JSON string with backslash \
instead of JSON object.
Example Code
Code Snippet for signing
- Java
- PHP
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "SHA256WithRSA";
public String sign(String content, String privateKey) throws GeneralSecurityException {
final Base64.Encoder encoder = Base64.getEncoder();
final Base64.Decoder decoder = Base64.getDecoder();
byte[] keyBytes = decoder.decode(privateKey);
byte[] data = content.getBytes(StandardCharsets.UTF_8);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encoder.encodeToString(signature.sign());
}
To use above Java code, you need to perform same public key manual edit on the private key PEM file.
Method Usage
String request = "{\"merchantId\":\"3000001\",\"amount\":100.2,\"isRecurring\":0,\"callbackUrl\":{\"fail\":\"https://www.bbmsl.com/fail\",\"success\":\"https://www.bbmsl.com/success\",\"cancel\":\"https://www.bbmsl.com/cancel\"},\"merchantReference\":\"Martin0331\",\"lineItems\":[{\"quantity\":1,\"priceData\":{\"unitAmount\":1.22,\"name\":\"Book\"}}]}";
String privateKey = "Your private key (remove header, footer and line breaks)";
String signature = sign(request, privateKey);
<?php
// 1. if you put your key in the code
$privateKey = "YOUR_PRIVATE_KEY";
$privateKeyPem = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($privateKey, 64, "\n", true). "\n-----END RSA PRIVATE KEY-----";
$key = openssl_get_privatekey($privateKeyPem);
// 2. if you include the .pem file
$key = openssl_pkey_get_private(file_get_contents('./key.pem'));
if (!$key) {
echo "Invalid key format".PHP_EOL;
exit;
}
echo '==========================='.PHP_EOL;
echo 'sign request'.PHP_EOL;
echo '==========================='.PHP_EOL;
openssl_sign($request_content, $encrypted, $key, OPENSSL_ALGO_SHA256);
$signature = base64_encode($encrypted);
?>