Validating Payment Response with Signature
To check that a response actually came from Nimbbl, you validate the signature it carries. You do this by generating your own signature on your server using the same data, then comparing it to the one Nimbbl sent. If the two match, the response is authentic.
- This is a mandatory step to check the veracity of the response received
- It allows you to be protected from tampering frauds
- This should be performed on your server
Generating the HMAC Signature
Every version and surface uses the same reusable function below — it takes a signatureData string and your access_secret, and returns the signature. Only the input string differs by version and surface: see v3 Signature or v4 Signature for the attributes you need and the exact string to pass in as signatureData.
- Java
- C#
- PHP
- Python
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;
public class HmacUtils {
public static String hmacSha256(String signatureData, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] raw = mac.doFinal(signatureData.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : raw) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}
using System;
using System.Security.Cryptography;
using System.Text;
class HmacUtils
{
public static string HmacSha256(string signatureData, string secretKey)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] dataBytes = Encoding.UTF8.GetBytes(signatureData);
using (var hmac = new HMACSHA256(keyBytes))
{
byte[] hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
}
<?php
function hmac_sha256($signatureData, $secretKey) {
$raw = utf8_encode($signatureData);
$key = utf8_encode($secretKey);
return hash_hmac('sha256', $raw, $key);
}
?>
import hmac
import hashlib
def hmac_sha256(signature_data, access_secret):
raw = signature_data.encode("utf-8")
key = access_secret.encode("utf-8")
return hmac.new(key=key, msg=raw, digestmod=hashlib.sha256).hexdigest()
Validating the Signature by Surface
The signature you generate should match the one you received — but which field carries it, and what exactly you hash, depends on which surface you're integrating against. The rules are the same across every surface for a given version, so they're documented one page per version instead of one page per surface:
- v3 Signature — joins a fixed set of fields together, one tab per surface (Payment Callback, Checkout Callback, Webhook, Transaction Enquiry, Payment Link).
- v4 Signature — hashes the whole payload as one string, one tab per surface (Webhook, Payment Callback, Checkout Callback).
If the signature you generate doesn't match the signature returned to you, please mark the Order as failed on your end. You should also raise a request for an investigation of this order on [email protected]