Webhook Setup and Verification Guide
Setting Up a Webhook
To set up a webhook, follow these steps:
-
Create an HTTP POST endpoint in your application that accepts JSON notification payloads in the format shown below. The endpoint must return a successful status code (200) as quickly as possible, before performing any complex logic that could cause a timeout.
{ "id": 123, "type": "PAYMENT_OBJECT", "state": "PROCESSED" }
-
Understand the notification payload:
- id: The unique identifier of the object.
- type:
PAYMENT_OBJECT
. - state: The current state of the object (see more information below). Possible states include:
-PENDING_COMPLIANCE_CHECKS
-REJECTED_COMPLIANCE
-PENDING_APPROVAL
-REJECTED_APPROVAL
-PENDING_SIGNING
-REJECTED_SIGNING
-PENDING_PAYMENT
-INITIATED_PAYMENT
-PROCESSING_PAYMENT
-PROCESSED
-FAILED
-REVERSED
-
Register your endpoint with ZTLment using the Create Payment Webhook endpoint.
Note: If the state is PENDING_COMPLIANCE_CHECKS
, it indicates that a new object has been created and is pending compliance checks.
Webhook Signatures
ZTLment signs every webhook notification it sends to your endpoint by including an X-Payload-Signature
header with the payload's signature. It is recommended to use these signatures to verify that the webhook request is legitimate and was generated by ZTLment.
Steps to Verify a Webhook Request
- Retrieve the
X-Payload-Signature
header from the request. - Retrieve the webhook HTTP body as bytes.
- Generate a signature by signing the body from step 2 with the secret key generated when creating the webhook. Use the
HmacSHA512
algorithm for signing. - Verify that the
X-Payload-Signature
header matches the signature generated in step 3.
Below is an example implementation in Java:
@ResponseBody
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, value = "https://yourcompany.com/payment-webhook-consume", consumes = MediaType.APPLICATION_JSON_VALUE)
public void consumeData(@Valid @RequestBody byte[] body, @RequestHeader(name = "X-Payload-Signature") String signature) throws NoSuchAlgorithmException, InvalidKeyException {
String ALGORITHM = "HmacSHA512";
String SECRET = "<YOUR_WEBHOOK_SECRET_KEY>";
SecretKey key = new SecretKeySpec(SECRET.getBytes(StandardCharsets.UTF_8), ALGORITHM);
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(key);
byte[] calculatedSignature = mac.doFinal(body);
String calculatedSignatureString = Base64.getEncoder().encodeToString(calculatedSignature);
boolean isValid = calculatedSignatureString.equals(signature);
if (isValid) {
// Process the webhook payload
} else {
// Handle the invalid signature
}
}
By following these instructions, you can ensure that your application receives and verifies webhook notifications securely and efficiently.
Payment Object States
You can set up webhooks to receive notifications in your application whenever a PaymentObject changes state, or when new ones are created.
PENDING_COMPLIANCE_CHECKS - Payment object created but not approved by our compliance provider (in rare cases it requires manual approval).
REJECTED_COMPLIANCE - Rejected via our compliance provider.
PENDING_APPROVAL - Payment awaiting customer signoff via the dashboard.
REJECTED_APPROVAL - Payment was rejected via the dashboard.
PENDING_SIGNING - Payment awaiting signing via the ZTLment authenticator native app.
REJECTED_SIGNING - Payment has been rejected via the ZTLment authenticator native app.
PENDING_PAYMENT - Signing of payment is complete and payment is being sent for initiation .
INITIATED_PAYMENT - The ZTLment backend has registered the payment in our internal system.
PROCESSING_PAYMENT - Payment has been sent for processing via bank partner.
PROCESSED - Payment is confirmed processed from our banking partner.
FAILED - Payment has failed.
REVERSED - In very rare scenarios payments that have been PROCESSED can be reversed. In this case the funds will be returned to your account.
Below is the flow of all payment object states.
![](https://files.readme.io/fc63610-image.png)