Incident Service Webhook
Incident Service
Cashfree Payments will notify you whenever we create an incident at our end. An incident implies that the issuing bank is facing high failure rates or has scheduled a maintenance activity during that time. The former could be due to many reasons and until the failure rates go down, we would recommend customers to use alternative payment instruments.
There are two channels through which we notify. You can subscribe to either of the channels by adding your email address and webhook endpoint in the merchant dashboard.
Email - Cashfree Payments will send an email alert when an issuer is facing downtime or a scheduled incident.
Webhooks - Cashfree Payments will invoke a server to server call whenever an incident is created. You can use this webhook and update your payment page accordingly.
Click here to know how to configure webhooks.
Webhook Schema
Sample Payload for Creation of Incident
{
"data": {
"incident": {
"end_time": null,
"id": "INCIDENT_MEDIUM_KarurVysyaBank_a7259c79-25a8-4b86-bcab-71562a85c386",
"impact": "MEDIUM",
"message": "We are facing issues with KVB bank UPI payments. ",
"start_time": "2021-04-16T14:00:00+05:30",
"status": "OPEN",
"type": "UNSCHEDULED"
},
"instruments": {
"upi": {
"issuers": [
"Karur Vysya Bank"
]
}
}
},
"event_time": "2021-04-16T14:10:36+05:30",
"type": "HEALTH_ALERT",
"version": 1
}
Sample Payload When Incident is Resolved
{
"data": {
"incident": {
"end_time": "2021-04-16T18:20:24+05:30",
"id": "INCIDENT_MEDIUM_KarurVysyaBank_a7259c79-25a8-4b86-bcab-71562a85c386",
"impact": "MEDIUM",
"message": "Payment mode up",
"start_time": "2021-04-16T14:00:00+05:30",
"status": "RESOLVED",
"type": "UNSCHEDULED"
},
"instruments": {
"upi": {
"issuers": [
"Karur Vysya Bank"
]
}
}
},
"event_time": "2021-04-16T18:20:24+05:30",
"type": "HEALTH_ALERT",
"version": 1
}
Payload
Field | Description | Example | Mandatory |
---|---|---|---|
end_time | Null when an incident is created. Or end time when incident is resolved | 2021-04-16T15:10:36+05:30 | N |
start_time | Time since we have seen this incident | 2021-04-16T14:10:36+05:30 | Y |
id | Incident id | Alphanumeric with special characters - _,-, | Y |
impact | Impact of the downtime | HIGH, MEDIUM, LOW | Y |
message | Human readable message | N | |
status | Status of the incident. OPEN when the incident is created. RESOLVED once the incident is resolved. UPDATE once we update the incident with any more details. | OPEN, UPDATE, RESOLVED | Y |
type | Is this a scheduled or an unscheduled downtime? | SCHEDULED, UNSCHEDULED | Y |
instruments | Refers to the payment mode. This will contain a nested object. One of the following - upi, net_banking, card, wallet | Y | |
upi.issuers | Issuers which are impacted | Array | N |
net_banking.issuers | Net banking banks which are impacted | Array | N |
wallet.issuers | Wallets which are impacted | Array | N |
card.type | Card types which are impacted | CREDIT_CARD, DEBIT_CARD, ALL | N |
card.scheme | Card schemes which are impacted | MASTER, VISA, RUPAY, MAESTRO, AMEX, ALL | N |
card.issuers | Banks which are impacted | Array | N |
event_time | Time when this webhook was created | Y | |
type | Type of webhook | HEALTH_ALERT | Y |
version | Version of webhook | You should build your parsing logic wrt to this version. | Y |
Children | Optional | Type | Possible Values |
---|---|---|---|
wallet | Y* | Child attributes | Available below |
net_banking | Y* | Child attributes | Available below |
upi | Y* | Child attributes | Available below |
card | Y* | Child attributes | Available below |
- At least one of the children needs to be present
Wallet
Children | Optional | Type | Possible Values |
---|---|---|---|
issuers | N | Text | See list of wallet issuers below. |
Net Banking
Children | Optional | Type | Possible Values |
---|---|---|---|
issuers | N | Array | See list of issuers below. |
UPI
Children | Optional | Type | Possible Values |
---|---|---|---|
issuers | N | Array | See list of issuers below. |
Card
Children | Optional | Type | Possible Values |
---|---|---|---|
type | N | Text | CREDIT_CARD, DEBIT_CARD, ALL |
scheme | N | Text | MASTER, VISA, RUPAY, MAESTRO, AMEX, ALL |
issuers | N | Array | See list of issuers below. |
Payload Headers
Cashfree Payments will send two custom headers for every webhook being invoked by our system.
Name | Description | Example |
---|---|---|
x-cashfree-timestamp | Timestamp for this event. Used to generate signature | 1618562436364 |
x-cashfree-signature | Cashfree Payments signature for this webhook | ke+K3gR8GssH9AMfJm+0+8jGIL1Mq7hOheP9w36/hL0= |
Signature Generation
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 Payment Gateway secret key along with the payload.
//The payload here refers to the raw request sent by
Cashfree to your endpoint. No modifications need to be
done to this payload.
payload := {"data":{"bank_name":"Test Bank",
"card_type":"Visa","health":"DEGRADED",
"incident_end_time":"2021-04-07T00:20:30",
"incident_id":"INCIDENT_HIGH_Test Bank_954b95zz-f11a-test-abcd-0eb0e8608847",
"incident_impact":"High",
"incident_start_time":"2021-04-06T00:20",
"incident_type":"Scheduled",
"is_resolved":false,
"issuers":[],
"message":"We are facing high failure issues in Payment gateway at the moment and will keep you updated about the issue.",
"payment_gateway":null,"payment_mode":"DEBIT_CARD",
"scope":"PaymentMode"},
"type":"HEALTH_ALERT","version":1}
# timestamp is present in the header x-cashfree-timestamp
timestamp := 1617695238078
signedPayload := $timestamp.$payload
expectedSignature := Base64Encode(HMACSHA256($signedPayload, $merchantSecretKey))
Bank Names
- Bank Name
- Axis Bank
- Bank of Baroda - Retail Banking
- Bank of India
- Bank of Maharashtra
- Canara Bank
- Catholic Syrian Bank
- Central Bank of India
- City Union Bank
- Deutsche Bank
- DBS Bank Ltd
- DCB Bank - Personal
- Dhanlakshmi Bank
- Federal Bank
- HDFC Bank
- ICICI Bank
- IDBI Bank
- IDFC Bank
- Indian Bank
- Indian Overseas Bank
- IndusInd Bank
- Jammu and Kashmir Bank
- Karnataka Bank Ltd
- Karur Vysya Bank
- Kotak Mahindra Bank
- Laxmi Vilas Bank - Retail Net Banking
- Punjab & Sind Bank
- Punjab National Bank - Retail Net Banking
- RBL Bank
- Saraswat Bank
- South Indian Bank
- Standard Chartered Bank
- State Bank Of India
- Tamilnad Mercantile Bank Ltd
- UCO Bank
- Union Bank of India
- Yes Bank Ltd
- Bank of Baroda - Corporate
- Bank of India - Corporate
- DCB Bank - Corporate
- Lakshmi Vilas Bank - Corporate
- Punjab National Bank - Corporate
- State Bank of India - Corporate
- Union Bank of India - Corporate
- Axis Bank Corporate
- Dhanlaxmi Bank Corporate
- ICICI Corporate Netbanking
- Ratnakar Corporate Banking
- Shamrao Vithal Bank Corporate
- Equitas Small Finance Bank
- Yes Bank Corporate
- Bandhan Bank- Corporate banking
- Barclays Corporate- Corporate Banking - Corporate
- Indian Overseas Bank Corporate
- City Union Bank of Corporate
- HDFC Corporate
- Shivalik Bank
- AU Small Finance
- Bandhan Bank - Retail Net Banking
- Shamrao Vitthal Co-operative Bank
- Tamil Nadu State Co-operative Bank
All Banks (Note: This parameter will be sent when all banks are having a downtime)
Wallet Names
- Name of the wallet
- FreeCharge
- MobiKwik
- Ola Money
- Reliance Jio Money
- Airtel Money
- Paytm
- Amazon Pay
- PhonePe
Compute Signature and Verify
Sample Code
Verify Signature using SDK
var express = require('express')
import { Cashfree } from "cashfree-pg";
var app = express()
Cashfree.XClientId = "<x-client-id>";
Cashfree.XClientSecret = "<x-client-secret>";
Cashfree.XEnvironment = Cashfree.Environment.SANDBOX;
app.post('/webhook', function (req, res) {
try {
Cashfree.PGVerifyWebhookSignature(req.headers["x-webhook-signature"], req.rawBody, req.headers["x-webhook-timestamp"]))
} catch (err) {
console.log(err.message)
}
})
import (
cashfree "github.com/cashfree/cashfree-pg/v4"
)
// Route
e.POST("/webhook", _this.Webhook)
// Controller
func (_this *WebhookRoute) Webhook(c echo.Context) error {
clientId := "<x-client-id>"
clientSecret := "<x-client-secret>"
cashfree.XClientId = &clientId
cashfree.XClientSecret = &clientSecret
cashfree.XEnvironment = cashfree.SANDBOX
signature := c.Request().Header.Get("x-webhook-signature")
timestamp := c.Request().Header.Get("x-webhook-timestamp")
body, _ := ioutil.ReadAll(c.Request().Body)
rawBody := string(body)
webhookEvent, err := cashfree.PGVerifyWebhookSignature(signature, rawBody, timestamp)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(webhookEvent.Object)
}
}
<?php
$inputJSON = file_get_contents('php://input');
$expectedSig = getallheaders()['x-webhook-signature'];
$ts = getallheaders()['x-webhook-timestamp'];
if(!isset($expectedSig) || !isset($ts)){
echo "Bad Request";
die();
}
\Cashfree\Cashfree::$XClientId = "<x-client-id>";
\Cashfree\Cashfree::$XClientSecret = "<x-client-secret>";
$cashfree = new \Cashfree\Cashfree();
try {
$response = cashfree->PGVerifyWebhookSignature($expectedSig, $inputJSON, $ts);
} catch(Exception $e) {
// Error if signature verification fails
}
?>
from cashfree_pg.api_client import Cashfree
@app.route('/webhook', methods = ['POST'])
def disp():
# Get the raw body from the request
raw_body = request.data
# Decode the raw body bytes into a string
decoded_body = raw_body.decode('utf-8')
#verify_signature
timestamp = request.headers['x-webhook-timestamp']
signature = request.headers['x-webhook-signature'
cashfree = Cashfree()
cashfree.XClientId = "<app_id>"
cashfree.XClientSecret = "<secret_key>"
try:
cashfreeWebhookResponse = cashfree.PGVerifyWebhookSignature(signature, decoded_body, timestamp)
except:
# If Signature mis-match
import com.cashfree.*;
@PostMapping("/my-endpoint")
public String handlePost(HttpServletRequest request) throws IOException {
Cashfree.XClientId = "<x-client-id>";
Cashfree.XClientSecret = "<x-client-secret>";
Cashfree.XEnvironment = Cashfree.SANDBOX;
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
bufferedReader = request.getReader();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append('\n');
}
String rawBody = stringBuilder.toString();
String signature = request.getHeader("x-webhook-signature");
String timestamp = request.getHeader("x-webhook-timestamp");
Cashfree cashfree = new Cashfree();
PGWebhookEvent webhook = cashfree.PGVerifyWebhookSignature(signature, rawBody, timestamp);
} catch (Exception e) {
// Error if verification fails
} finally {
if (bufferedReader != null) {
bufferedReader.close();
}
}
}
using cashfree_pg.Client;
using cashfree_pg.Model;
[Route("api/[controller]")]
[ApiController]
public class YourController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Post()
{
// Read the raw body of the POST request
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string requestBody = await reader.ReadToEndAsync();
var headers = Request.Headers;
var signature = headers["x-webhook-signature"];
var timestamp = headers["x-webhook-timestamp"];
Cashfree.XClientId = "<x-client-id>";
Cashfree.XClientSecret = "<x-client-secret>";
Cashfree.XEnvironment = Cashfree.SANDBOX;
var cashfree = new Cashfree();
try {
var response = cashfree.PGVerifyWebhookSignature(signature, requestBody, timestamp);
} catch(Exception e) {
// Error if signature mis matches
}
}
}
}
Compute Signature and Verify manually
function verify(ts, rawBody){
const body = req.headers["x-webhook-timestamp"] + req.rawBody;
const secretKey = "<your secret key>";
let genSignature = crypto.createHmac('sha256',secretKey).update(body).digest("base64");
return genSignature
}
func VerifySignature(expectedSig string, ts string, 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
}
timestamp := c.Request().Header.Get("x-webhook-timestamp")
body, _ := ioutil.ReadAll(c.Request().Body)
rawBody := string(body)
signature := c.Request().Header.Get("x-webhook-signature")
VerifySignature(signature, timestamp, rawBody)
function computeSignature($ts, $rawBody){
$rawBody = file_get_contents('php://input');
$ts = getallheaders()['x-webhook-timestamp'];
$signStr = $ts . $rawBody;
$key = "";
$computeSig = base64_encode(hash_hmac('sha256', $signStr, $key, true));
return $computeSig;
}
public String generateSignature() {
bufferedReader = request.getReader();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append('\n');
}
String payload = stringBuilder.toString();
String timestamp = request.getHeader("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():
# Get the raw body from the request
raw_body = request.data
# Decode the raw body bytes into a string
payload = raw_body.decode('utf-8')
#verify_signature
timestamp = request.headers['x-webhook-timestamp']
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"
Subscribe to Developer Updates
Updated 4 months ago