Cancel Payment Request API
Cancel Payment Request API is used by merchants in order to cancel the raised dynamic requests like DQR, Collect Call, etc when the customer asks for the cancellation.
Request Headers
| Header Name | Header Value |
|---|---|
Content-Type | application/json |
X-VERIFY | SHA256(“/v3/charge/{merchantId}/{transactionId}/cancel” + salt key) + ### + salt index |
X-PROVIDER-ID | Used for the cases where the merchants are getting onboarded via their Providers |
X-CALLBACK-URL | Merchants need to pass their Callback URL to receive automated callbacks/ webhooks from Phonepe post performing transactions |
Path Parameters
| Parameter Name | Type | Description | Mandatory |
|---|---|---|---|
merchantId | STRING | Unique Merchant ID assigned to the merchant by PhonePe | Yes |
transactionId | STRING | Unique Transaction ID generated by the merchant to track this request to PhonePe | Yes |
Response Parameters
| Parameter Name | Type | Description |
|---|---|---|
success | BOOLEAN | Success status of the request |
code | ENUM | See below section for list of codes |
message | STRING | Short message about status |
data | OBJECT | Empty object |
Response Codes
The code in the above API response could be.
SUCCESSINTERNAL_SERVER_ERROR: There can be internal server error. Merchant should retry the cancel API request.INVALID_TRANSACTION_IDPAYMENT_ALREADY_COMPLETED: Payment has been succesful hence can’t cancel the request. For this case merchant should trigger successful transaction, generating the bill.
SampleResponseforSuccess
{
"success":true,
"code":"SUCCESS",
"message":"Your request has been successfully completed."
}SampleResponseforFailed
{
"success":false,
"code":"PAYMENT_ALREADY_COMPLETED",
"message":"Payment is already complete."
}C# SampleCode
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography;
using Newtonsoft.Json;
namespace Rextester
{
public class Program
{
private const string PHONEPE_STAGE_BASE_URL = "https://mercury-uat.phonepe.com/enterprise-sandbox";
private string merchantKey = "8289e078-be0b-484d-ae60-052f117f8deb";
private const string merchantId = "M2306160483220675579140";
public bool SendCancelRequest()
{
string headerString = String.Format("/v3/charge/{0}/{1}/cancel{2}", merchantId, transactionId, merchantKey);
Console.WriteLine("headerString: " + headerString);
string checksum = GenerateSha256ChecksumFromBase64Json("", headerString);
checksum = checksum + "###1";
Console.WriteLine(checksum);
bool result = CallCancelApi(checksum);
return result;
}
private bool CallCancelApi(String xVerify)
{
Console.WriteLine("CallPhonePeStatusApi()");
string txnURL = PHONEPE_STAGE_BASE_URL;
String urlSuffix = String.Format("/v3/charge/{0}/{1}/cancel", merchantId, transactionId);
txnURL = txnURL + urlSuffix;
Console.WriteLine("Url: " + txnURL);
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(txnURL);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("x-verify", xVerify);
string responseData = string.Empty;
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
responseData = responseReader.ReadToEnd();
if (responseData.Length > 0)
{
PhonePeCollectResponseBody responseBody = JsonConvert.DeserializeObject<PhonePeCollectResponseBody>(responseData);
Console.WriteLine(responseData);
Console.WriteLine(responseBody.message);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
return false;
}
return false;
}
// calculate SHA256
private string GenerateSha256ChecksumFromBase64Json(string base64JsonString, string jsonSuffixString)
{
string checksum = null;
SHA256 sha256 = SHA256.Create();
string checksumString = base64JsonString + jsonSuffixString;
byte[] checksumBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(checksumString));
//checksum = BitConverter.ToString(checksumBytes).Replace("-", string.Empty);
foreach (byte b in checksumBytes)
{
checksum += $"{b:x2}";
}
return checksum;
}
public static void Main(string[] args){
Program obj = new Program();
bool QRResponse = obj.SendCancelRequest();
Console.WriteLine(" Success");
}
}
public class PhonePeCollectResponseBody
{
public bool success;
public string code;
public string message;
public Data data;
}
public class Data
{
public string transactionId;
public int amount;
public string merchantId;
public string providerReferenceId;
}
}Python SampleCode
from django.shortcuts import render
from django.http import HttpResponse
import requests
import base64
import hashlib
from rest_framework.decorators import api_view
import json
from django.http import JsonResponse
import qrcode
import os
txnid = "TEST20231004021525T"
baseUrl = 'https://mercury-uat.phonepe.com/enterprise-sandbox'
MID = 'MERCHANTUAT'
saltkey = 'f1fed176-917c-4c1b-b5ae-1e1d39e1f8d5'
keyindex = '1'
def canceltransaction(request):
merchantId = MID
transactionId = txnid
url = baseUrl + '/v3/charge/' + merchantId + '/' + transactionId + '/cancel'
# for Sha256 calculation
api_saltkey = saltkey
str_forSha256 = '/v3/charge/' + merchantId + '/' + transactionId + '/cancel' + api_saltkey
sha_value = hashlib.sha256(str_forSha256.encode('UTF-8')).hexdigest()
x_verify = sha_value + '###' + keyindex
headers = {
"Content-Type": "application/json",
"X-VERIFY": x_verify,
"x-callback-url":"https://webhook.site/83892277-ac4f-4bc8"
}
print(headers)
print(url)
res = requests.post(url=url, headers=headers)
return HttpResponse(res)