Configure Webhook

  • Write to [email protected] to add your Webhook endpoint.
  • Ensure you do not process duplicate events.

Webhook will be sent to your configured endpoint as a POST request with the body containing the various parameters specifying the details of each event. Each request contains an event parameter that identifies its type.

Below are the various events that can be sent to your webhook endpoint.

  • SUBSCRIPTION_STATUS_CHANGE
  • SUBSCRIPTION_NEW_PAYMENT
  • SUBSCRIPTION_PAYMENT_DECLINED
  • SUBSCRIPTION_AUTH_STATUS

SUBSCRIPTION_STATUS_CHANGE

Parameter

Type

Description

cf_event

String

This event is triggered whenever the subscription status changes. The value for this event is SUBSCRIPTION_STATUS_CHANGE.

cf_subReferenceId

Integer

A unique Id which was generated when the subscription was created.

cf_status

String

The new status of the subscription. Click here for information on subscription statuses.

cf_lastStatus

String

The old status of the subscription. Click here for information on subscription statuses.

cf_eventTime

String [format - yyyy-MM-dd HH:mm:ss]

The time when the event was dispatched.

signature

String

A unique string which helps distinguish that the request is genuine and initiated by Cashfree. Click here for more information.


SUBSCRIPTION_NEW_PAYMENT

Parameter

Type

Description

cf_event

String

This event is triggered whenever there is a successful new payment for an authorized subscription. The value for this event is SUBSCRIPTION_NEW_PAYMENT.

cf_subReferenceId

Integer

A unique Id which was generated when the subscription was created.

cf_eventTime

String [format - yyyy-MM-dd HH:mm:ss]

The time when the event was dispatched.

cf_paymentId

Integer

The unique paymentId for the payment

cf_amount

Float

The amount charged for payment.

cf_referenceId

Integer

The unique txnId for the payment.

retryAttempts

Integer

The number of payment retries. This is applicable for failed payments.

signature

String

A unique string which helps distinguish that the request is genuine and initiated by Cashfree. Click here for more information.


SUBSCRIPTION_PAYMENT_DECLINED

Parameter

Type

Description

cf_event

String

This event is triggered whenever a payment fails for an authorized subscription. The value for this event is SUBSCRIPTION_PAYMENT_DECLINED.

cf_subReferenceId

Integer

A unique Id which was generated when the subscription was created.

cf_eventTime

String [format - yyyy-MM-dd HH:mm:ss]

The time when the event was dispatched.

cf_paymentId

Integer

The unique paymentId for the payment.

cf_amount

Float

The amount charged for payment.

cf_referenceId

Integer

The unique txnId for the payment.

retryAttempts

Integer

The number of payment retries. This is applicable for failed payments.

cf_reasons

String

A possible reason for failure.

signature

String

A unique string which helps distinguish that the request is genuine and initiated by Cashfree. Click here for more information.


SUBSCRIPTION_AUTH_STATUS

This event is triggered when the checkout fails. The customer can do multiple checkouts through the same subscription, and you will be notified of every checkout failure.

This event will not be triggered for an active, or bank approval pending subscription.

This is just for eMandate authorisation, not applicable for other payment modes.

Parameter

Type

Description

cf_event

String

The event is triggered when the checkout fails The value for this event is SUBSCRIPTION_AUTH_STATUS.

cf_subReferenceId

Integer

A unique Id which was generated when the subscription was created.

cf_eventTime

String [format - yyyy-MM-dd HH:mm:ss]

The time when the event was dispatched.

cf_subscriptionStatus

String

The status of the subscription. Click here for information on subscription statuses.

cf_authStatus

String

Checkout status. Allowed value: FAILED

cf_authTimestamp

String [format - yyyy-MM-dd HH:mm:ss]

Checkout initiated timestamp.

cf_authFailureReason

String

Possible checkout failure. It will be empty for successFul authStatus change.

signature

String

A unique string which helps distinguish that the request is genuine and initiated by Cashfree. Click here for more information.


Verify Signature

Verifying the signature (passed along with the POST parameters) is mandatory before you process any response. We also recommend whitelisting only our IP address on your webhook endpoint.

Follow the steps below to calculate & verify the signature on the webhook payload:

  1. Please sort the webhook payload in alphabetical order based on fields which are starting with field cf_.
  2. Append the key-value pair w/o using any delimiter and create a string.
  3. Hash the string using the secret key which will be provided to you.
  4. Encode the hashed string using base64 and generate the signature.

Example :

  1. Sample web hook payload -

    
    {
       "cf_retryAttempts":0,
       "cf_amount":1,
       "cf_event":"SUBSCRIPTION_NEW_PAYMENT",
       "cf_eventTime":"2022-01-10 10:03:50",
       "cf_paymentId":1,
       "cf_referenceId":2,
       "cf_subReferenceId":3,
       "signature":"tT9pXZkT2LuDzXacYDUaur7EX3dJgNKcITHQng44tns="
    }
    
  2. Sorted web hook payload -

    cf_amount1cf_eventSUBSCRIPTION_NEW_PAYMENTcf_eventTime2022-01-10 10:51:02cf_paymentId1cf_referenceId2cf_retryAttempts0cf_subReferenceId3

  3. Signature generated using encoding with secret key -

    tT9pXZkT2LuDzXacYDUaur7EX3dJgNKcITHQng44tns=

  4. Generated signature should match the signature present in the webhook payload.

Following code snippets show you how to generate and verify the signature. This should not be assumed production-ready, kindly consider adding necessary validation before processing.

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class WebhookHandler {

  private static final String MAC_SHA256_ALGO = "HmacSHA256";
  
  public boolean verifySignature(Map <String, Object> payload) {
    final String signature = payload.get("signature");
    final String computedSignature = generateSignature(payload);
    return signature.equals(computedSignature);
  }

  public String generateSignature(Map <String, Object> payload) {
    try {
      String secretKey = "ac7960e7995536f0177fd210f3b3937fc2d974a4"; // merchant will have this.
      SortedSet<String> keys = new TreeSet<String>(payload.keySet());
      for (String key : keys) {
        if ((key.length() > 3) && (key.substring(0, 3).equals("cf_"))) {
          data = data + key + ((String[])postData.get(key))[0];
        }
      }
      Mac mac = Mac.getInstance(MAC_SHA256_ALGO);
      SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), MAC_SHA256_ALGO);
      mac.init(secretKeySpec);
      final byte[] encrypted = mac.doFinal(data.getBytes());
      return Base64.getEncoder().encodeToString(encrypted);
    }
    catch (Exception ex) {
      // handle
    }
  }
}
<?php

class WebhookHandler {

  public static function triggerHook ($data) {
    $signature = $data["signature"];
    $secretKey = "ac7960e7995536f0177fd210f3b3937fc2d974a4"; // merchant will have this.
    $computedSignature = static::generateSignature($data, $secretKey);
    return $signature == $computedSignature;
  }

  private static function generateSignature ($data, $clientSecret) {
  ksort($data); // Sort the $data array based on keys
  $signatureData = "";
  foreach ($data as $key => $value) {
    if (strlen($key) > 0 && substr($key, 0, 3) == "cf_") {
      $signatureData .= $key . $value;
    }
  }
  $hash_hmac = hash_hmac('sha256', $signatureData, $secretKey, true);
  
  $computedSignature = base64_encode($hash_hmac);
  return $computedSignature;
  } 

?>

Failure Reasons

Code

Reason

AP01

Account Blocked

AP02

Account Closed

AP03

Account Frozen

AP04

Account Inoperative

AP05

No Such Account

AP06

Not a SBS accoountnumber or old account number represent with CBS number

AP07

Refer to the branch KYC not completed

AP11

Authentication Failed

AP14

Invalid user credentials

AP15

Mandate not registered_ not maintaining required balance

AP16

Mandate not registered_ minor account

AP17

Mandate not registerd_ NRE Account

AP18

Mandate registration not allowed for CC account

AP19

Mandate registration not allowed for PF account

AP20

Mandate registraction not allowed for PPF account

AP23

Transaction rejected or canceleed by customer

AP24

Account not in regular Status

AP25

Withdrawal stopped due to insolvency of account

AP28

Mandate registration failed. Please contact your home branch

AP29

Technical errors or connectivity issues as bank

AP30

Browser closed by customer in mid-transaction

AP31

Mandate registration not allowed for joint account

AP32

Mandate registration not allowed for wallet account

AP33

User rejected the transaction on pre-login page

AP34

Account number not registered with net-banking facility

AP35

Debit card validation failed due to_ Invalid card number

AP36

Debit card validation failed due to_ Invalid expiry date

AP37

Debit card validation failed due to_ Invalid PIN

AP38

Debit card validation failed due to_ Invalid CVV

AP39

OTP invalid

AP40

Maximum retries exceeded for OTP

AP41

Time expired for OTP

AP42

Debit card not activated

AP43

Debit card blocked

AP44

Debit card hot listed

AP45

Debit card expired

AP46

No response received from customer while preforming transaction

AP47

Account number registered for only view rights in net banking facility.


Did this page help you?