Checkout verification webhook
On this page
Payout sends the checkout.verification webhook when a bank payment is matched to a checkout during statement reconciliation. It carries the payer's name and IBAN from the bank statement, encrypted, so that you can verify the payer's identity.
The webhook is sent only for bank payment methods: bank transfer, bank button and PIS.
Note
To receive this webhook, ask support to enable the webhook_verification feature for your account.
Webhook payload
checkout.verification payload:
{
"external_id": "order-5001",
"object": "webhook",
"type": "checkout.verification",
"data": {
"object": "checkout",
"id": 141801,
"external_id": "order-5001",
"amount": 300,
"currency": "EUR",
"redirect_url": "https://eshop.example.com/payment/redirect",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "[email protected]",
"iban": null
},
"account_details": {
"name": "H24qnEt9A+haL5xh1Ljgc1gmpo22ULK5W+OIaKskz5w=",
"iban": "jD1ef5obLE1ujwobPF1+n0RKaiEIcFXcRgJZrCrUNz60s7X2m1SQ9OWLTm3suiRA"
},
"payment": {
"object": "payment",
"status": "successful",
"payment_method": "bank_transfer",
"failure_reason": "",
"created_at": 1759744800,
"fee": 8,
"net": 292
},
"metadata": {},
"status": "succeeded",
"is_status_final": true
},
"nonce": "Sk9RR2EycmIxOUZsWTBtRw",
"signature": "79be670c341f6acfb04cc1c8ac8f3a94ba296261b72a50c0770e658d82b78013"
}
account_details.name and account_details.iban hold the payer's name and IBAN, encrypted with AES-256-CBC. See Decrypting account details.
Signature verification
Verify signature as for every other webhook, see Simple payment:
Pattern: external_id|type|nonce|client_secret
Input: order-5001|checkout.verification|Sk9RR2EycmIxOUZsWTBtRw|q3dpHpYtDrH-KmGD4HMn5OTEx6IsZPBokQ8CqMONWqMSEePWy9bXd3Ua3KvO7f6C
SHA-256: 79be670c341f6acfb04cc1c8ac8f3a94ba296261b72a50c0770e658d82b78013
Note
The hash is in lowercase hex. Some libraries return uppercase hex; convert it to lowercase before you compare it.
Decrypting account details
Each encrypted value is decrypted with a key derived from the client_id of your API key:
-
Derive the key
Hash
client_idwith SHA-512, encode the hash as lowercase hex and take the first 32 characters. Use these 32 characters as the 32-byte key, as they are; don't hex-decode them. -
Split the value
Base64-decode the value. The first 16 bytes are the IV, the rest is the ciphertext.
-
Decrypt
Decrypt the ciphertext with AES-256-CBC and remove the PKCS#7 padding.
In Node.js:
const crypto = require("crypto");
function decryptAccountDetail(clientId, value) {
const key = crypto.createHash("sha512").update(clientId).digest("hex").slice(0, 32);
const data = Buffer.from(value, "base64");
const decipher = crypto.createDecipheriv("aes-256-cbc", Buffer.from(key, "utf8"), data.subarray(0, 16));
return Buffer.concat([decipher.update(data.subarray(16)), decipher.final()]).toString("utf8");
}
decryptAccountDetail("DC995618-7ED8-4070-9DA0-48B6F86551C3", "H24qnEt9A+haL5xh1Ljgc1gmpo22ULK5W+OIaKskz5w=");
// "John Doe"
With the client_id from the examples, DC995618-7ED8-4070-9DA0-48B6F86551C3, the key is 7d47c1ea4bafb442ea5a1ecf114b871c, and the payload above decrypts to John Doe and SK3112000000198742637541.
Retrieve checkout encrypts the payer details of bank payments the same way.
- Need help? Contact support.
- Questions? Contact sales.
- Service status? status.payout.one.
- LLM? Read llms.txt.