Integration Guide
The notification body contains the type of notification and its payload:
{
"type": [notification_type],
"action": [status],
"payload": [content]
}
Parameter | Description | Format | Required |
type | Type 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. | (PAYMENT|REGISTRATION) | required |
action | Indicator 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) | conditional |
payload | Content 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. | JSON | required |
Payment
Registration
"type":"PAYMENT",
"payload":{
"id":"8a829449515d198b01517d5601df5584",
"paymentType":"PA",
"paymentBrand":"VISA",
"amount":"92.00",
"currency":"EUR",
"descriptor":"3017.7139.1650 OPP_Channel ",
"result":{
"code":"000.100.110",
"description":"Request successfully processed in 'Merchant in Integrator Test Mode'"
},
"authentication":{
"entityId":"8a8294185282b95b01528382b4940245"
},
"card":{
"bin":"420000",
"last4Digits":"0000",
"holder":"Jane Jones",
"expiryMonth":"05",
"expiryYear":"2018"
},
"customer":{
"givenName":"Jones",
"surname":"Jane",
"merchantCustomerId":"jjones",
"sex":"F",
"email":"[email protected]"
},
"customParameters":{
"SHOPPER_promoCode":"AT052"
},
"risk":{
"score":"0"
},
"buildNumber":"[email protected] 12:20:39 +0000",
"timestamp":"2015-12-07 16:46:07+0000",
"ndc":"8a8294174b7ecb28014b9699220015ca_66b12f658442479c8ca66166c4999e78"
}
}
{
"type":"REGISTRATION",
"action": "CREATED",
"payload":{
"id":"8a82944a53e6a0150153eaf693584262",
"paymentBrand":"VISA",
"result":{
"code":"000.100.110",
"description":"Request successfully processed in 'Merchant in Integrator Test Mode'",
"randomField1315125026":"Please allow for new unexpected fields to be added"
},
"card":{
"bin":"420000",
"last4Digits":"0000",
"holder":"Jane Jones"
},
"authentication":{
"entityId":"8a8294174b7ecb28014b9699220015ca"
},
"redirect":{
"parameters":[
]
},
"risk":{
"score":""
},
"timestamp":"2016-04-06 09:45:41+0000",
"ndc":"8a8294174b7ecb28014b9699220015ca_b1539494024c411684b544574716e608"
}
}
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
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 | HTTPS (HTTP is allowed on test systems only) |
HTTP method | POST |
Content type | text(text/plain) |
C#
Java
PHP
Python
using System;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace DecryptionExample
{
// You need to install bccrypto-csharp from BouncyCastle. Please see BouncyCastle page.
class Program
{
static void Main(string[] args)
{
string keyFromConfiguration = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
// Data from server
string ivFromHttpHeader = "000000000000000000000000";
string authTagFromHttpHeader = "CE573FB7A41AB78E743180DC83FF09BD";
string httpBody = "0A3471C72D9BE49A8520F79C66BBD9A12FF9";
// Convert data to process
byte[] key = ToByteArray(keyFromConfiguration);
byte[] iv = ToByteArray(ivFromHttpHeader);
byte[] authTag = ToByteArray(authTagFromHttpHeader);
byte[] encryptedText = ToByteArray(httpBody);
byte[] cipherText = encryptedText.Concat(authTag).ToArray();
// Prepare decryption
GcmBlockCipher cipher = new GcmBlockCipher(new AesFastEngine());
AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, iv);
cipher.Init(false, parameters);
// Decrypt
var plainText = new byte[cipher.GetOutputSize(cipherText.Length)];
var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
cipher.DoFinal(plainText, len);
Console.WriteLine(Encoding.ASCII.GetString(plainText));
}
static byte[] ToByteArray(string HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
}
}
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);
?>
import os
import binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
# 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 = binascii.unhexlify(key_from_configuration)
iv = binascii.unhexlify(iv_from_http_header)
auth_tag = binascii.unhexlify(auth_tag_from_http_header)
cipher_text = binascii.unhexlify(http_body)
# Prepare decryption
decryptor = Cipher(algorithms.AES(key), modes.GCM(iv, auth_tag), backend = default_backend()).decryptor()
# Decrypt
result = decryptor.update(cipher_text) + decryptor.finalize()
print(result)