Refund Notification API
After completing refund, the WeChat payment system will send the refund result to the Merchant.
Tips:
• The same notification may be sent to the merchant system for multiple times. The merchant system must be able to process repeated notifications properly. It is recommended that when a notification is received and processed, check the status of the corresponding business data first, and then analyze whether it is processed. If not, then process it; if yes, return the processed result. Before the status check and process of business data, perform concurrent control of these data with data locks to avoid data corruption caused by reentrant functions.
• If the wechat pay callback is not received after all notification frequencies (4 hours), the merchant need to call the 【Query Order API】to confirm the order status.
Note:The merchant system must perform signature verification for the refund result notification, and verify whether the returned refund amount is consistent with that on the merchant side to prevent any possible capital loss caused by "false notifications" due to data leakage.
1. API intro
Applicable object:Common modeInstitutional mode
Request URL: The URL is set by the parameter notify_url submitted in [Submit Refund API] and the https protocol is required. If the URL cannot be accessed, the merchant will not receive any WeChat notifications. The URL must be directly accessible without any parameters. For example: notify_url: http://pay.weixin.qq.com/wxpay/123456789
2. Notification Rules
After the refund status changes, WeChat will send the refund results to the merchant.
When notifying the interaction to the backend, if the response received by WeChat is unsuccessful or timeout, WeChat considers it as a notification failure and will send it again by following certain strategies to maximize the success rate, but WeChat does not guarantee a successful notification. (Notification frequency:15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - in total 24h4m).
3. Notification Message
For refund result notifications, access the notification URL set up by the merchant with the `POST` method, and the notification data is transmitted through the request body (BODY) in the `JSON` format. The notification data contains the details of the encrypted refund result.
The procedure of how to decrypt the notification data is described as follows.
1、Obtain the merchant's notification key from the merchant platform, and record it as `key`.
2、Obtain the corresponding parameters `nonce` and `associated_data` for the algorithm described in `resource.algorithm` (which is `AEAD_AES_256_GCM`).
3、Decrypt the ciphertext `resource.ciphertext` with `key`, `nonce`, and `associated_data`, to obtain the resource objects in the Json format.
Notice
For the information on the API of the algorithm `AEAD_AES_256_GCM`, see rfc5116. The length of the `key` used for WeChat Pay is 32 bytes, the length of the random string `nonce` is 12 bytes, and the length of the `associated_data` is less than 16 bytes or may be zero.
4. Request Parameters
Name |
Variable Name |
Type |
Required |
Description |
Notification ID |
id |
string[1,36] |
Yes |
The unique notification ID
Example: f7c34059-0f2d-5b32-ba33-a42dks0597c5 |
Notification creation time |
create_time |
string[1,64] |
Yes |
Notification creation time, in RFC3339 format
Example: 2018-06-08T10:34:56+08:00 |
Notification type |
event_type |
string[1,32] |
Yes |
Notification type:
REFUND.SUCCESS: Notification on a successful refund
REFUND.CLOSED:Notification on a closed refund
Example: REFUND.SUCCESS |
Brief description of notice |
summary |
string[1,16] |
Yes |
Brief description of notice
Example value: refund succeeded |
Notification data type |
resource_type |
string[1,32] |
Yes |
The type of the notification resource data. The type of resource data for the refund notification is encrypt-resource.
Example: encrypt-resource |
Notification data |
resource |
object |
Yes |
Resource data of a notification |
Name |
Variable Name |
Type |
Required |
Description |
Encryption algorithm type |
algorithm |
string[1,32] |
Yes |
The algorithm that encrypts the refund result data. Only AEAD_AES_256_GCM is supported.
Example: AEAD_AES_256_GCM |
Object type before encryption |
original_type |
string[1,32] |
Yes |
Object type before the encryption. The type of refund notification is refund.
Example: refund |
Data ciphertext |
ciphertext |
string[1,1048576] |
Yes |
The ciphertext of the refund result encoded with Base64 |
Additional data |
associated_data |
string[1,16] |
No |
Additional data |
Random string |
nonce |
string[1,32] |
Yes |
The random string used for encryption |
|
5. Notification Signature
Encryption does not guarantee that the notification request comes from wechat pay. Wechat pay will sign the notification sent to the merchant and put the signature value in the Wechatpay-Signature of Notification's HTTP header. The merchant should verify the signature to confirm that the request is from wechat pay, not other third parties. For the algorithm of signature verification, please refer to《Wechat Pay API V3 Signature Scheme》。
6. Notification example
Payment Success Result Notification
{
"id": "f7c34059-0f2d-5b32-ba33-a42dks0597c5",
"create_time": "2018-06-08T10:34:56+08:00",
"resource_type": "encrypt-resource",
"event_type": "REFUND.SUCCESS",
"summary": "Refunded",
"resource": {
"original_type": "refund",
"algorithm": "AEAD_AES_256_GCM",
"ciphertext": "...",
"associated_data": "",
"nonce": "..."
}
}
List of decrypted resource objects:
{
"sp_mchid": "1900000100",
"sub_mchid": "1900000109",
"transaction_id": "1008450740201411110005820873",
"out_trade_no": "20150806125346",
"refund_id": "50200207182018070300011301001",
"out_refund_no": "7752501201407033233368018",
"refund_status": "SUCCESS",
"success_time": "2018-06-08T10:34:56+08:00",
"recv_account": "China Merchants Bank Credit Card 0403",
"fund_source": "REFUND_SOURCE_UNSETTLED_FUNDS",
"amount" : {
"total": 528800,
"currency": "HKD",
"refund": 528800,
"payer_total": 528800,
"payer_refund": 528800,
"payer_currency": "HKD",
"exchange_rate" : {
"type": "SETTLEMENT_RATE",
"rate": 100000000
}
}
}
7. List of decrypted resource objects
Name |
Variable Name |
Type |
Required |
Description |
Merchant ID |
mchid |
string[1,32] |
Yes |
Merchant ID assigned by WeChat Pay
Note: Only forCommon mode
Example: 1900000109 |
Institution's Merchant ID |
sp_mchid |
string[1,32] |
Yes |
Institution's Merchant ID assigned by WeChat Pay
Note: Only forInstitutional mode
Example: 1900000100 |
Sub-merchant ID |
sub_mchid |
string[1,32] |
Yes |
Merchant ID assigned to sub-merchants by WeChat Pay
Note: Only forInstitutional mode
Example: 1900000109 |
Merchant order No. |
out_trade_no |
string[1,32] |
Yes |
Returned merchant's order No.
Example: 1217752501201407033233368018 |
WeChat Pay order No. |
transaction_id |
string[1,32] |
Yes |
WeChat Pay order No.
Example: 1217752501201407033233368018 |
Merchant refund No. |
out_refund_no |
string[1,64] |
Yes |
Merchant refund No.
Example: 1217752501201407033233368018 |
WeChat refund No. |
refund_id |
string[1,32] |
Yes |
WeChat refund No.
Example: 1217752501201407033233368018 |
Refund status |
refund_status |
string[1,16] |
Yes |
Refund status:
SUCCESS:Refund successful
CLOSED:Refund closed
Example: SUCCESS |
Refund completion time |
success_time |
string[1,64] |
No |
Refund completion time, which is returned when the refund status is successful in RFC3339 format.
Example: 2018-06-08T10:34:56+08:00 |
Refund receiving account |
recv_account |
string[1,64] |
Yes |
Refund receiving party of the current refund order
1)Refund to bank cards:
{Bank name}{Card type}{Last numbers of the bank card}
2) Refund to the balance of the paying user:
The balance of the paying user
3)Refund to the merchant:
Merchant's basic account
Merchant's settlement bank account
4)Refund to the Mini Fund of the paying user:
The Mini Fund of the paying user
Example: China Merchants Bank Credit Card 0403 |
Refund source |
fund_source |
string[1,30] |
No |
REFUND_SOURCE_UNSETTLED_FUNDS: Refund with unsettled funds (default)
REFUND_SOURCE_RECHARGE_FUNDS:Refund with available balance
Example: REFUND_SOURCE_UNSETTLED_FUNDS |
Amount information |
amount |
object |
Yes |
Information on the amount. For more information, see the description below. |
Name |
Variable Name |
Type |
Required |
Description |
Order amount |
total |
int |
Yes |
The total order amount. The minimum unit of the currency can only be an integer.
Example: 888 |
Priced currency |
currency |
string[1,16] |
Yes |
Three-letter code in accordance with ISO 4217.
Example: CNY |
Refund amount |
refund |
int |
Yes |
Refund amount. The minimum unit of the currency can only be an integer. The refund amount cannot exceed the original order amount. If a voucher was used, the backend will refund proportionally.
Example: 888 |
User's payment amount |
payer_total |
int |
Yes |
The actual amount paid by the user. The minimum unit of the currency can only be an integer.
Example: 888 |
Refund amount to user |
payer_refund |
int |
Yes |
The amount refunded to the user, excluding voucher amount
Example: 888 |
User payment currency |
payer_currency |
string[1,16] |
Yes |
Three-letter code in accordance with ISO 4217.
Example: HKD |
Exchange rate information |
exchange_rate |
object |
No |
The object of the exchange rate information. For more information, see the description below. |
Name |
Variable Name |
Type |
Required |
Description |
Exchange rate type |
type |
string[1,16] |
No |
When the priced currency and the payment currency are the same, type="SETTLEMENT_RATE", i.e. the exchange rate between the [real-time] priced currency and the settlement currency.
When the priced currency and the payment currency are different, type="USERPAYMENT_RATE", i.e. the exchange rate between the [original payment] priced currency and the payment currency.
Example: SETTLEMENT_RATE |
Exchange rate value |
rate |
int |
No |
The rate value is the exchange rate multiplied by the 8th power of 10.
If the exchange rate is 1, then the exchange rate value is 100,000,000;
if the exchange rate is 6.5, then the exchange rate value is 650,000,000.
Example: 80000000 |
|
|
8. Response Result
After the merchant's backend has properly processed the notification, HTTP status code 200 or 204 needs to be returned. No specific content is required for 204.For other HTTP status codes, WeChat Pay will deem the notification as a failure, and will send the notification regularly by following the aforesaid policies.
Notice
If the merchant's backend fails to process a response, WeChat Pay will record the response message. It is recommended to return in the following format.
Name |
Variable Name |
Type |
Required |
Description |
Returned status code |
code |
string[1,32] |
Yes |
For more information, see the returned status code description below.
Example: SUCCESS |
Returned message |
message |
string[1,256] |
No |
Returned message, which presents the cause of the error.
Example: System error |
{
"code": "SUCCESS",
"message": "Processed successfully"
}