Payment Result Notification API
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.
• 2. 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's system must perform signature verification for the payment result notification, and verify whether the returned order amount is consistent with that of the merchant side, to prevent any possible capital loss caused by "false notifications" due to data leakage.
1. API intro
Applicable object: Common mode Institutional mode
Request URL: The URL is set by the parameter notify_url submitted in [Order Placement 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 user completes the payment, WeChat will send both the payment result and the user information to the merchant. The merchant needs to receive and process the information, and return the successful response. Notification will only be sent if the payment is successful.
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 payment 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 payment result.
The procedure of how to decrypt the notification data is described as follows.
1、Obtain APIv3 Secret from the merchant platform and record it as key.
2、For the algorithm described in `resource.algorithm` (which is AEAD_AES_256_GCM), obtain the corresponding `parameters nonce` and `associated_data`.
3、Decrypt the `resource.ciphertext` with `key`, `nonce`, and `associated_data` to obtain the resource object in JSON form.
Note
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. For example, 2018-06-08T10:34:56+08:00 represents BJT 10:34:56 June 8, 2018.
Example: 2018-06-08T10:34:56+08:00 |
Notification type |
event_type |
string[1,32] |
Yes |
Notification type. The type of a successful payment notification is TRANSACTION.SUCCESS.
Example: TRANSACTION.SUCCESS |
Notification data type |
resource_type |
string[1,32] |
Yes |
The type of the notification resource data. The type of resource data for a successful payment notification is encrypt-resource.
Example: encrypt-resource |
Brief description of notice |
summary |
string[1,16] |
Yes |
Brief description of notice
Example: payment succeeded |
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 payment result data. Only AEAD_AES_256_GCM is supported.
Example: AEAD_AES_256_GCM |
Data ciphertext |
ciphertext |
string[1,1048576] |
Yes |
The ciphertext of the payment result encoded with Base64 |
Additional data |
associated_data |
string[1,16] |
No |
Additional data used for encryption |
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. Callback 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":"TRANSACTION.SUCCESS",
"summary": "payment succeeded",
"resource": {
"algorithm": "AEAD_AES_256_GCM",
"ciphertext": "...",
"associated_data": "",
"nonce": "..."
}
}
List of decrypted resource objects:
{
"id": "1008450740201411110005820873",
"sp_appid": "wx2421b1c4370ec43b",
"sp_mchid": "10000100",
"sub_mchid": "20000100",
"out_trade_no": "20150806125346",
"payer": {
"sp_openid": "oUpF8uN95-Ptaags6E_roPHg7AG0"
},
"amount": {
"total": 528800,
"currency": "HKD",
"payer_total": 518799,
"payer_currency": "CNY",
"exchange_rate": {
"type": "SETTLEMENT_RATE",
"rate": 8000000
}
},
"trade_type": "MICROPAY",
"trade_state": "SUCCESS",
"trade_state_desc": "Payment successful",
"bank_type": "CCB_DEBIT",
"attach": "Payment test",
"success_time": "2018-06-08T10:34:56+08:00",
"promotion_detail": [{
"promotion_id": "109519",
"name": "Single-item discount-6",
"scope": "SINGLE",
"type": "DISCOUNT",
"amount": 1,
"currency": "HKD",
"activity_id": "931386",
"wechatpay_contribute_amount": 1,
"merchant_contribute_amount": 0,
"other_contribute_amount": 0,
"goods_detail": [{
"goods_id": "iphone6s_16G",
"goods_remark": "Product remarks",
"quantity": 1,
"price": 528800
}]
}]
}
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 |
APPID |
appid |
string[1,32] |
Yes |
APPID corresponding to the mobile app applied for by the merchant on the WeChat Open Platform
Note: Only forCommon mode
Example: wx8888888888888888 |
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 |
Organization APPID |
sp_appid |
string[1,32] |
Yes |
APPID corresponding to the Service Account applied for by the institution on the WeChat Official Accounts Platform
Note: Only forInstitutional mode
Example: wx8888888888888888 |
Contracted merchant APPID |
sub_appid |
string[1,32] |
No |
APPID corresponding to the mobile app applied for by the sub-merchant on the WeChat Open Platform
Note: Only forInstitutional mode
Example: wx8888888888888888 |
Merchant order No. |
out_trade_no |
string[1,32] |
Yes |
Returned merchant's order No.
Example: 1217752501201407033233368018 |
WeChat Pay order No. |
id |
string[1,32] |
Yes |
WeChat Pay order No.
Example: 1217752501201407033233368018 |
Merchant data |
attach |
string[1,127] |
No |
Additional data, which will be returned unchanged in the query API and payment notifications. This field is mainly used for the custom data in the orders of the merchant.
Example: Custom data |
Transaction type |
trade_type |
string[1,16] |
Yes |
In-APP Pay
Example: APP |
Paying bank |
bank_type |
string[1,32] |
Yes |
Bank type, which is the bank ID in string format. See Bank Type for the list of values.
Example: CMC |
Payment completion time |
success_time |
string[1,64] |
Yes |
Payment completion time, in RFC3339 format. For example, 2018-06-08T10:34:56+08:00 represents BJT 10:34:56 June 8, 2018.
Example: 2018-06-08T10:34:56+08:00 |
Transaction status |
trade_state |
string[1,32] |
Yes |
SUCCESS: Payment successful
Note: Only orders with successful payment will push the payment result notification, so the return of this field is SUCCESS only
Example: SUCCESS |
Transaction status description |
trade_state_desc |
string[1,256] |
Yes |
Descriptions on the current order status and instructions for the next operation.
Example: Payment failed. Place another order and pay it again. |
Payer |
payer |
object |
Yes |
Payer information. For more information, see the description below. |
Name |
Variable Name |
Type |
Required |
Description |
User ID |
openid |
string[1,128] |
No |
The unique user ID corresponding to the merchant's appid. It is returned only when appid is passed.
Note: Only forCommon mode
Example: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o |
User ID (contracted merchant] |
sp_openid |
string[1,128] |
No |
The unique user ID corresponding to the merchant's sp_appid. It is returned only when sp_appid is passed.
Note: Only forInstitutional mode
Example: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o |
User ID (contracted merchant] |
sub_openid |
string[1,128] |
No |
The unique user ID corresponding to the acquiring bank's sub_appid. It is returned only when sub_appid is passed.
Note: Only forInstitutional mode
Example: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o |
|
Order amount |
amount |
object |
Yes |
Information on the order 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. See Transaction amount for details.
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.See Transaction amount for details.
Example: 888 |
Priced currency |
currency |
string[1,16] |
Yes |
Three-letter code in accordance with ISO 4217.
Example: CNY |
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,32] |
No |
SETTLEMENT_RATE, which is the exchange rate between the priced currency and the settlement 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 priced currency is the same as the settlement currency, then the exchange rate is 1, and the exchange rate value is 100,000,000.
If the priced currency is different from the settlement currency, for example, the exchange rate between USD and CNY is 6.5, then the exchange rate value is 650,000,000.
Example: 80000000 |
|
|
Discount feature |
promotion_detail |
array |
No |
Discount feature info. For more information, see the description below. |
Name |
Variable Name |
Type |
Required |
Description |
Voucher ID |
promotion_id |
string[1,32] |
Yes |
Voucher or discount ID
Example: 109519 |
Discount name |
name |
string[1,64] |
No |
Discount name
Example: Single-item discount-6 |
Discount range |
scope |
string[1,32] |
No |
GLOBAL- All-item voucher
SINGLE- Single-item discount
Example: SINGLE |
Discount type |
type |
string[1,32] |
No |
COUPON - Vouchers, which are a kind of top-up vouchers that require fund settlement (the voucher currency of overseas merchants is the same as the payment currency).
DISCOUNT - Discount vouchers, which are a kind of top-up-free discount vouchers that require no fund settlement (the voucher currency of overseas merchants is the same as the priced currency).
Example: DISCOUNT |
Discount voucher price |
amount |
int |
Yes |
The discount amount
Example: 5 |
Discount currency |
currency |
string[1,16] |
Yes |
Three-letter code in accordance with ISO 4217.
Example: HKD |
Activity ID |
activity_id |
string[1,32] |
No |
Batch ID set up by the backend of the WeChat merchant
Example: 931386 |
Contribution by WeChat |
wxpay_contribute_amount |
int |
No |
It is the discount provided by the WeChat Pay Merchant Platform, and the total contribution is equal to the total amount of this discount.
Example: 0 |
Contribution by the merchant |
merchant_contribute_amount |
int |
No |
It is the discount provided by the merchant, and the total contribution is equal to the total amount of this discount.
Example: 0 |
Other contributions |
other_contribute_amount |
int |
No |
The contributions made by other contributors
Example: 5 |
Product details |
goods_detail |
Array |
No |
Product information submitted in JSON format |
Name |
Variable Name |
Type |
Required |
Description |
Product code |
goods_id |
string[1,32] |
Yes |
It consists of a combination of uppercase and lowercase letters, numbers, hyphens and underscores.
Example: Product code |
Product remarks |
goods_remark |
string[1,128] |
No |
goods_remark is a remark field that is returned unchanged. It is set when the voucher is configured in the WeChat backend.
Example: 1001 |
Product discount amount |
discount_amount |
int |
Yes |
Total discount amount of a single item
Example: 100 |
Number of products |
quantity |
int |
Yes |
Number of products purchased by a user
Example: 1 |
Product price |
price |
int |
Yes |
Unit: 0.01 CNY. If the merchant provides a discount, the discounted unit price should be transferred (for example, if the user has applied a paper voucher of 50 CNY Off 100 CNY issued by the shop to an order of 100 CNY, the discounted price should be the original price 100 CNY minus 50 CNY).
Example: 528800 |
|
|
8. Response Result
Response for successful request: The HTTP response status code needs to return 200 or 204, there's no need to return the response message.
Response for failed request:The HTTP response status code needs to return 5XX or 4XX, the response message needs to be returned.
The format is as follows:
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 |
200
{
"code": "SUCCESS",
"message": "OK"
}
{
"code": "SYSTEM_ERROR",
"message": "ERROR"
}