Webhooks

Webhooks are events that notify you about the payment status. All Cashgram integrations should establish a webhook to listen for cashgram events, like status changes on payments. Webhooks are HTTP callbacks that receive notification messages for events.

Webhooks help you receive automatic updates and are significant for completing the integration with Cashfree. Webhooks are triggered with a request from your side, for example, when a transfer fails or when a daily report is available. Requests get processed both synchronously and asynchronously. In rare scenarios, for some payment methods, the outcome may take a longer duration to confirm. Cashfree notifies you once we get updates from the bank about the payment status.

Do not go live without signature verification if you are using webhooks.

Webhook Events

​Cashfree Cashgram API enables you to receive updates about all event-driven activities originating from your account. Below is the list of Cashgram webhooks:

CASHGRAM_REDEEMED - Cashgram redeemed by the customer
CASHGRAM_TRANSFER_REVERSAL - Cashgram transfer reversed by the bank
CASHGRAM_EXPIRED - Cashgram is inactive

Cashfree gets a response from the bank with the status of the transfer. At times the notifications may get delayed due to various reasons, and the transaction status will be marked as Pending, till Cashfree gets a response.

Cashfree polls the transaction status from the bank for the next 72 hours. In case we do not receive the status of a transaction after 72 hours, the transaction will be marked as Failed.

CASHGRAM_REDEEMED

Sent whenever a Cashgram is redeemed.

ParameterDescription
eventIt contains the name of the event which just occurred. Value = CASHGRAM_REDEEMED
cashgramidId of the cashgram passed by the merchant
referenceIdId of the transfer generated by Cashfree
eventTimeTransfer initiation time
utrUnique transaction reference number provided by the bank
signatureA unique string which helps distinguish that the request is genuine and initiated by Cashfree.

CASHGRAM_TRANSFER_REVERSAL

Sent whenever the bank reverses a Cashgram.

ParameterDescription
eventIt contains the name of the event which just occurred. Value = CASHGRAM_TRANSFER_REVERSAL
cashgramidId of the cashgram passed by the merchant
referenceIdId of the transfer generated by Cashfree
eventTimeTransfer initiation time
signatureA unique string which helps distinguish that the request is genuine and initiated by Cashfree.

CASHGRAM_EXPIRED

Cashgram can become inactive for various reasons. An inactive Cashgram cannot be re-activated. You need to create a new Cashgram to send to your customer. A Cashgram gets reversed if one of the following events occurs:

  1. Redeeming post Expiry time: If the customer does not redeem the Cashgram before the expiration time (set by the Merchant while creating the Cashgram), the Cashgram gets deactivated.

  2. Reaching the maximum number of retries: A maximum of three attempts is allowed to redeem the Cashgram. If the customer enters incorrect details more than three times, the Cashgram gets deactivated.

  3. OTP verification attempts exceeded: A maximum of three attempts is allowed to verify the OTP. If the customer fails to verify the OTP successfully, the Cashgram gets deactivated.

ParameterDescription
eventIt contains the name of the event which just occurred. Value = CASHGRAM_EXPIRED
cashgramidId of the cashgram passed by the merchant
reasonReason for reversal
signatureA unique string which helps distinguish that the request is genuine and initiated by Cashfree.

Signature Verification

Cashfree sends a signature alongside every webhook, verifying this signature ( passed along with the POST parameters ) is mandatory before processing any response. It helps authenticate that the webhook is from Cashfree.

We strongly recommend whitelisting Cashfree's production IP to help make your communication with Cashfree more secure.

Following are the steps to verify Cashfree's signature:

  1. Get all the POST parameters except ‘signature’ and assign it to an array as key-value pair
  2. Sort the array based on keys
  3. Concatenate all the values in this array and the resultant is the post data (say, postData)
  4. postData needs to be encrypted using SHA-256, and then base64 encoded
  5. Now verify if both the signature calculated and the signature received match
  6. Proceed further if it matches, else discards the request

Cashfree's libraries also support signature verification. To verify the signature returned by Cashfree call the following methods from the library.

Below code snippets can help you verify Cashfree Signature:

<?php
  $data = $_POST;
  $signature = $_POST["signature"];
  unset($data["signature"]); // $data now has all the POST parameters except signature
  ksort($data); // Sort the $data array based on keys
  $postData = "";
  foreach ($data as $key => $value){
    if (strlen($value) > 0) {
      $postData .= $value;
    }
  }
  $hash_hmac = hash_hmac('sha256', $postData, $clientSecret, true) ;
  
  // Use the clientSecret from the oldest active Key Pair.
  $computedSignature = base64_encode($hash_hmac);
  if ($signature == $computedSignature) {
    // Proceed based on $event
  } else {
    // Reject this call
  }
?>
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;
import org.apache.commons.codec.binary.Base64;

public class ComputedSignature {
  public static String generateHMAC(String clientSecret, String data) {
    String hash = null;
    try {
      String secret = clientSecret;
      String message = data;
      Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
      SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(),"HmacSHA256");
      sha256_HMAC.init(secret_key);
      hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
    }
    catch (Exception e){
      //Log it
    }
    return hash;
  }
}
const Cashfree = require("cashfree-sdk");
//convert post response recived in the notification end point to json
//and pass that to the SDK.
Cashfree.Payouts.VerifySignature(webhookPostDataJson);
from cashfree_sdk import verification

#webhook_data = response.content
webhook_data = '{"cashgramId": "5b8283182e0711eaa4c531df6a4f439b-28", "event": "CASHGRAM_EXPIRED", "eventTime": "2020-01-03 15:01:06", "reason": "OTP_ATTEMPTS_EXCEEDED", "signature": "TBpM+4nr1DsWsov7QiHSTfRJP4Z9BD8XrDgEhBlf9ss="}'
verification.verify_webhook(webhook_data, 'JSON')

Webhook Retries

Cashfree webhooks service does its best to deliver events to your webhook endpoint. It is best practice for your application to respond to the callback. Our webhook service may send many payloads to a single endpoint in quick succession. You will need to build an application and configure your server to receive the response we send when events get triggered during the process.

Your server should return a 200 HTTP status code to acknowledge that you received the webhook without any issues. Any other information you return in the request headers or request body gets ignored. Any response code outside the 200 range, including 3xx codes, indicates that you did not receive the webhook.

When Cashfree does not get the acknowledgement due to any reason, we retry to establish the communication at regular intervals. If we do not receive the response after a few attempts, we gradually decrease the rate of retries. Based on this count, the service is disabled if it fails more than five times.

If you are not receiving notifications from Cashfree as expected, please reach out to our support team at [email protected].