Refund Webhooks

Refund webhooks can be configured to receive automated notifications for refunds when either they are successfully processed or are cancelled. Merchants can build their own downstream systems like auto-updating their refund status, and sending a communication to customers by consuming refund webhooks.

The webhook notification will be sent on all the URLs added and enabled under the refund webhook. Merchants can add new URLs and enable or disable existing URLs for refund webhook at any point in time and it will be reflected instantaneously.

Click here to know how to configure webhooks.

Sample Payload


{
   "data":{
"refund":{
         "cf_refund_id":11325632,
         "cf_payment_id":789727431,
         "refund_id":"refund_sampleorder0413",
         "order_id":"sampleorder0413",
         "refund_amount":2.00,
         "refund_currency":"INR",
         "entity":"Refund",
         "refund_type":"MERCHANT_INITIATED",
         "refund_arn":"205907014017",
         "refund_status":"SUCCESS",
         "status_description":"Refund processed successfully",
         "created_at":"2022-02-28T12:54:25+05:30",
         "processed_at":"2022-02-28T13:04:27+05:30",
         "refund_charge":0,
         "refund_note":"Test",
         "refund_splits":[
            {
               "merchantVendorId":"sampleID12345",
               "amount":1,
               "percentage":null
            },
            {
               "merchantVendorId":"otherVendor",
               "amount":1,
               "percentage":null
            }
         ],
         "metadata":null,
         "refund_mode":"STANDARD"
      }
   },
   "event_time":"2022-02-28T13:04:28+05:30",
   "type":"REFUND_STATUS_WEBHOOK"
}

Payload Field Description

FieldDescriptionExample
cf_refund_idCashfree Payments ID for a refund.11325632
cf_payment_idCashfree Payments ID of the payment for which refund is initiated.789727431
refund_idMerchant’s refund ID of the refundrefund_sampleorder0413
order_idMerchant’s order Id of the order for which refund is initiated.sampleorder0413
refund_amountAmount that was refunded2.00
refund_currencyCurrency of the refund amount.INR
entityType of object (refund always)Refund
refund_typeType of refund (for webhook it will always be MERCHANT_INITIATED)MERCHANT_INITIATED
refund_arnThe bank reference number for refund205907014017
refund_statusStatus of the refund (either SUCCESS or CANCELLED in refund webhook)SUCCESS
status_descriptionDescription of refund statusRefund processed successfully
created_atTime of refund creation2022-02-28T12:54:25+05:30
processed_atTime when refund was processed successfully2022-02-28T13:04:27+05:30
refund_chargeCharges in INR for processing refund0
refund_noteNote added by merchant for the refundCancelled Order
refund_splitsRefund split details[]
metadataAdditional refund metadatanull
refund_modeMethod or speed of processing refund (INSTANT or STANDARD)STANDARD
event_timeTime at which refund webhook was initiated.2022-02-28T13:04:28+05:30
typeType of webhook. REFUND_STATUS_WEBHOOK alwaysREFUND_STATUS_WEBHOOK

Signature Verification

The signature must be used to verify if the request has not been tampered with. To verify the signature at your end, you will need your Cashfree PG secret key along with the payload.

timestamp is present in the header x-webhook-timestamp

timestamp := 1617695238078;  
signedPayload := $timestamp.$payload;
expectedSignature := Base64Encode(HMACSHA256($signedPayload, $merchantSecretKey));

Compute Signature and Verify

function verify(ts, rawBody){
    const body = ts + rawBody
    const secretKey = "<your secret key>";
    let genSignature = crypto.createHmac('sha256',secretKey).update(body).digest("base64");
    return genSignature
}
func VerifySignature(expectedSig string, ts int64, body string) (string, error) {
	t := time.Now()
	currentTS := t.Unix()
	if currentTS-ts > 1000*300 {
		return "", errors.New("webhook delivered too late")
	}
	signStr := strconv.FormatInt(ts, 10) + body
	fmt.Println("signing String: ", signStr)
	key := ""
	h := hmac.New(sha256.New, []byte(key))
	h.Write([]byte(signStr))
	b := h.Sum(nil)
	return base64.StdEncoding.EncodeToString(b), nil
}
function computeSignature($ts, $rawBody){
    $signStr = $ts . $rawBody;
    $key = "";
    $computeSig = base64_encode(hash_hmac('sha256', $signStr, $key, true));
    return $computeSig;
}
public String generateSignature() {
 	String payload = "json payload in string";
  String timestamp = "x-webhook-timestamp";
  String data = timestamp+payload;

  String secretKey = "SECRET-KEY"; // Get secret key from Cashfree Merchant Dashboard;
  Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
  SecretKeySpec secret_key_spec = new SecretKeySpec(secretKey.getBytes(),"HmacSHA256");
  sha256_HMAC.init(secret_key_spec);
  String computed_signature = Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(data.getBytes()));
  return computed_signature; // compare with "x-webhook-signature"
}
import base64
import hashlib
import hmac

def generateSignature():    
    timestamp = "timestamp data"
    payload = 'json data in string'
    signatureData = timestamp+payload
    message = bytes(signatureData, 'utf-8')
    secretkey=bytes("Secret_Key",'utf-8') #Get Secret_Key from Cashfree Merchant Dashboard.
    signature = base64.b64encode(hmac.new(secretkey, message, digestmod=hashlib.sha256).digest())
    computed_signature = str(signature, encoding='utf8')
    return computed_signature #compare with "x-webhook-signature"