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.

PROD
Base Url: https://mercury-t2.phonepe.com
Cancel Request API: https://mercury-t2.phonepe.com/v3/charge/{merchantId}/{transactionId}/cancel

<html-block html=”

Request Headers

“>

Header NameHeader Value
Content-Typeapplication/json
X-VERIFYSHA256(“/v3/charge/{merchantId}/{transactionId}/cancel” +
salt key) + ### + salt index
X-PROVIDER-IDUsed for the cases where the merchants are getting onboarded via their Providers
X-CALLBACK-URLMerchants need to pass their Callback URL to receive automated callbacks/ webhooks from Phonepe post performing transactions

<html-block html=”

Path Parameters

“>

Parameter NameTypeDescriptionMandatory
merchantIdSTRINGUnique Merchant ID assigned to the merchant by PhonePeYes
transactionIdSTRINGUnique Transaction ID generated by the merchant to track this request to PhonePeYes

<html-block html=”

Response Parameters

“>

Parameter NameTypeDescription
successBOOLEANSuccess status of the request
codeENUMSee below section for list of codes
messageSTRINGShort message about status
dataOBJECTEmpty object

<html-block html=”

Response Codes

“>

The code in the above API response could be.

  • SUCCESS
  • INTERNAL_SERVER_ERROR : There can be internal server error. Merchant should retry the cancel API request.
  • INVALID_TRANSACTION_ID
  • PAYMENT_ALREADY_COMPLETED : Payment has been succesful hence can’t cancel the request. For this case merchant should trigger successful transaction, generating the bill.
{
  "success":true,
 "code":"SUCCESS",
 "message":"Your request has been successfully completed."
}
{
  "success":false,
  "code":"PAYMENT_ALREADY_COMPLETED",
  "message":"Payment is already complete."
}
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;
    }
}

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)
{“method”:”post”,”url”:”/v3/charge/{merchantId}/{transactionId}/cancel”,”auth”:”required”,”results”:{“codes”:[{“name”:””,”code”:”{ \”success\”: true,\n \”code\”: \”SUCCESS\”,\n \”message\”:\”Your request has been successfully completed.\”,\n \”data\”:{}\n}”,”language”:”json”,”status”:200},{“name”:””,”code”:”{}”,”language”:”json”,”status”:400}]},”params”:[{“name”:”merchantId”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”Unique Merchant ID assigned to the merchant by PhonePe”,”required”:false,”in”:”path”,”ref”:””,”_id”:”5f310bd19c236501368dbec5″},{“name”:”transactionId”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”Unique Transaction ID generated by the merchant to track this request to PhonePe”,”required”:false,”in”:”path”,”ref”:””,”_id”:”5f310bd19c236501368dbec4″},{“name”:”Content-Type”,”type”:”string”,”enumValues”:””,”default”:”application/json”,”desc”:””,”required”:false,”in”:”header”,”ref”:””,”_id”:”5f310bd19c236501368dbec3″},{“name”:”X-VERIFY”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”SHA256(\”/v3/charge/{merchantId}/{transactionId}/cancel\” + salt key) + ### + salt index”,”required”:false,”in”:”header”,”ref”:””,”_id”:”5f310bd19c236501368dbec2″}],”examples”:{“codes”:[]},”apiSetting”:”64c244096688b200429110a5″}
https://mercury-uat.phonepe.com/enterprise-sandbox