Skip to main content

Refund API Guide

tip

Only transactions with the return code 0000 (transaction successful) can be refunded.

note

For credit card payments, QFPay performs automatic capture. If a refund is submitted on the same day, it will be treated as a void and handled by this same refund API.

API Endpoint

Endpoint : /trade/v1/refund

Method : POST

Request Headers

Content-Type: application/x-www-form-urlencoded
X-QF-APPCODE: <your-app-code>
X-QF-SIGN: <signature>

Request Parameters

ParameterMandatoryTypeDescription
syssnYesString(128)QFPay transaction number of the original transaction to be refunded
out_trade_noYesString(128)Unique refund transaction ID (must not repeat across refund requests)
txamtYesInt(11)Refund amount in cents (e.g. 100 = $1). Suggest > 200 to avoid risk control.
txdtmYesString(20)Refund request time. Format: YYYY-MM-DD hh:mm:ss
mchidConditionalString(16)Merchant ID. Required only if one is issued.
udidNoString(40)Unique transaction device ID

Response Parameters

ParameterTypeDescription
syssnString(40)New refund transaction ID
orig_syssnString(128)Original transaction ID
txamtInt(11)Refunded amount in cents
sysdtmString(20)Refund system time (YYYY-MM-DD hh:mm:ss)
respcdString(4)Response code:
0000 = success
1143, 1145 = processing
other = failed
resperrString(128)Response message
cash_feeStringActual amount paid by user (after discounts)
cash_fee_typeStringPayment currency (e.g. CNY)
cash_refund_feeStringActual refunded amount
cash_refund_fee_typeStringRefund currency (e.g. CNY)

Sample HTTP Body

txamt=10&syssn=20191227000200020061752831&out_trade_no=12345678&txdtm=2019-12-27 10:39:39&mchid=ZaMVg*****

SDK Code Examples

import urllib.request, urllib.parse, urllib.error, urllib.request, urllib.error, urllib.parse, hashlib
import requests
from hashids import Hashids
import datetime
import string
import random

# Enter Client Credentials
environment = 'https://test-openapi-hk.qfapi.com'
app_code = 'D5589D2A1F2E42A9A60C37**********'
client_key = '0E32A59A8B454940A2FF39**********'


# Create parameter values for data payload
current_time = datetime.datetime.now().replace(microsecond=0)
random_string = ''.join(random.choices(string.ascii_uppercase + string.digits, k=32))


# Create signature
def make_req_sign(data, key):
keys = list(data.keys())
keys.sort()
p = []
for k in keys:
v = data[k]
p.append('%s=%s'%(k,v))
unsign_str = ('&'.join(p) + key).encode("utf-8")
s = hashlib.md5(unsign_str).hexdigest()
return s.upper()


# Body payload
txamt = '10' #Partial or full refund amount
syssn = '20191227000200020061752831' #Original transaction number
out_trade_no = random_string
txdtm = current_time
key = client_key
mchid = 'ZaMVg*****'


#data ={'txamt': txamt, 'syssn': syssn, 'out_trade_no': out_trade_no, 'txdtm': txdtm, 'udid': udid, 'mchid': mchid}
data ={'mchid': mchid, 'txamt': txamt, 'syssn': syssn, 'out_trade_no': out_trade_no, 'txdtm': txdtm}

r = requests.post(environment+"/trade/v1/refund",data=data,headers={'X-QF-APPCODE':app_code,'X-QF-SIGN':make_req_sign(data, key)})

print(r.json())

Sample JSON Response

{
"orig_syssn": "20191227000200020061752831",
"sysdtm": "2019-12-27 11:11:23",
"paydtm": "2019-12-27 11:11:26",
"txdtm": "2019-12-27 11:10:38",
"udid": "qiantai2",
"txcurrcd": "EUR",
"txamt": "10",
"resperr": "success",
"respmsg": "",
"out_trade_no": "RGNOEIVU9JZLNP9GGYXWXCW7OEMI720F",
"syssn": "20191227000300020061652643",
"respcd": "0000",
"chnlsn": "2019122722001411461404119764",
"cardcd": ""
}

Notes

  • Ensure refund amount does not exceed the original transaction value.
  • Some wallets may not support partial refunds.
  • Refund time limits vary by channel. Contact QFPay support for details.
  • For failed refunds (respcd not 0000), retry logic or query via Transaction Enquiry is advised.