LET'S ROCK!
Integration and Decryption
Notification content and structure
The notification body contains the type of notification and its payload.
{ "type": [notification_type], "action": [status], "payload": [content] }
ParameterDescriptionFormatRequiredtypeType of the notification
- PAYMENT This type of notification is sent when a payment is created or updated in the system.
- REGISTRATION This type of notification is sent when a registration is created or deleted.
- RISK This type of notification is sent when a risk transaction is created or deleted.
(PAYMENT|REGISTRATION|RISK)requiredactionIndicator of status change. This field is available only if the type is REGISTRATION.
- CREATED when registration has been created.
- UPDATED when registration has been updated.
- DELETED when registration has been deleted.
(CREATED|UPDATED|DELETED)conditionalpayloadContent of the notification. If the notification type is payment or registration, the payload's content will be identical to the response you received on the payment or registration.JSONrequired
Encryption
The content of notification is encrypted to protect data from fraud attempts. When converting human-readable string to hexadecimal format, we use UTF-8.
Parameter | Description |
---|---|
Encryption algorithm | AES |
Key | [secret of listener] (64-character-long hexadecimal string in configuration) |
Key length | 256 bits (32 bytes) |
Block mode | GCM |
Padding | None |
Initialization vector | In HTTP header (X-Initialization-Vector) |
Authentication tag | In HTTP header (X-Authentication-Tag) |
Format of body: Hexadecimal
Format of Initialization Vector: Hexadecimal
Payload {"type": "PAYMENT"} Payload in Hexadecimal (after getting bytes in UTF-8) 7B2274797065223A20225041594D454E54227D Key in Hexadecimal 000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F Initialization-Vector (Hexadecimal) 3D575574536D450F71AC76D8 Authentication-Tag (Hexadecimal) 19FDD068C6F383C173D3A906F7BD1D83 Encrypted value in Hexadecimal F8E2F759E528CB69375E51DB2AF9B53734E393
Responding to Notifications
When your service receives a webhook notification, it must return a 2xx HTTP status code. Otherwise, the webhook service considers the notification delivery as failed, and will retry to send the notification later.
Protocol Details
Protocol | HTTPS (HTTP is allowed on test systems only) |
HTTP method | POST |
Content type | text(text/plain) |
Decryption Example
import com.google.common.base.Charsets; import org.apache.commons.lang3.ArrayUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; import java.security.Security; // For Java and JVM-based languages, you might need to install unrestricted policy file for JVM, // which is provided by Sun. Please refer BouncyCastle FAQ if you get // java.lang.SecurityException: Unsupported keysize or algorithm parameters or // java.security.InvalidKeyException: Illegal key size. // If you cannot install unrestricted policy file for JVM because of some reason, you can try with reflection: See here. public class Decryption { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); // Data from configuration String keyFromConfiguration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; // Data from server String ivFromHttpHeader = "000000000000000000000000"; String authTagFromHttpHeader = "CE573FB7A41AB78E743180DC83FF09BD"; String httpBody = "0A3471C72D9BE49A8520F79C66BBD9A12FF9"; // Convert data to process byte[] key = DatatypeConverter.parseHexBinary(keyFromConfiguration); byte[] iv = DatatypeConverter.parseHexBinary(ivFromHttpHeader); byte[] authTag = DatatypeConverter.parseHexBinary(authTagFromHttpHeader); byte[] encryptedText = DatatypeConverter.parseHexBinary(httpBody); // Unlike other programming language, We have to append auth tag at the end of encrypted text in Java byte[] cipherText = ArrayUtils.addAll(encryptedText, authTag); // Prepare decryption SecretKeySpec keySpec = new SecretKeySpec(key, 0, 32, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv)); // Decrypt byte[] bytes = cipher.doFinal(cipherText); System.out.println(new String(bytes, Charsets.UTF_8)); } }
<?php /* Please refer Using Libsodium in PHP Projects */ $key_from_configuration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"; $iv_from_http_header = "000000000000000000000000"; $auth_tag_from_http_header = "CE573FB7A41AB78E743180DC83FF09BD"; $http_body = "0A3471C72D9BE49A8520F79C66BBD9A12FF9"; $key = hex2bin($key_from_configuration); $iv = hex2bin($iv_from_http_header); $cipher_text = hex2bin($http_body . $auth_tag_from_http_header); $result = \Sodium\crypto_aead_aes256gcm_decrypt($cipher_text, NULL, $iv, $key); print($result); ?>
require("openssl") # Convert hexadecimal string def convert(hex) return [hex].pack("H*") end # Create new decipher def new_decipher(key, iv) cipher = OpenSSL::Cipher.new("aes-256-gcm") cipher.decrypt cipher.key = key cipher.iv = iv return cipher end # Data from configuration key_from_configuration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f" # Data from server iv_from_http_header = "000000000000000000000000" auth_tag_from_http_header = "CE573FB7A41AB78E743180DC83FF09BD" http_body = "0A3471C72D9BE49A8520F79C66BBD9A12FF9" # Convert data to process key = convert(key_from_configuration) iv = convert(iv_from_http_header) auth_tag = convert(auth_tag_from_http_header) cipher_text = convert(http_body) # Prepare decryption decipher = new_decipher(key, iv) decipher.auth_tag = auth_tag # Decrypt result = decipher.update(cipher_text) + decipher.final puts result