第十四节 支付成功的回调通知

亮子 2021-08-25 09:55:59 17779 0 0 0

1、官方文档

https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_5.shtml

2、通知消息介绍

微信支付通过支付通知接口将用户支付成功消息通知给商户。

注意:

• 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

• 如果在所有通知频率后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。

特别提醒:商户系统对于开启结果通知的内容一定要做签名验证,并校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。

3、接口说明

  • 适用对象: 直连商户

  • 请求方式:POST

  • 回调URL:
    该链接是通过基础下单接口中的请求参数“notify_url”来设置的,要求必须为https地址。请确保回调URL是外部可正常访问的,且不能携带后缀参数,否则可能导致商户无法接收到微信的回调通知信息。回调URL示例: “https://pay.weixin.qq.com/wxpay/pay.action”

4、通知规则

用户支付完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理该消息,并返回应答。

对后台通知交互时,如果微信收到商户的应答不符合规范或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)

5、通知报文

支付结果通知是以POST 方法访问商户设置的通知url,通知的数据以JSON 格式通过请求主体(BODY)传输。通知的数据包括了加密的支付结果详情。
(注:由于涉及到回调加密和解密,商户必须先设置好apiv3秘钥后才能解密回调通知,apiv3秘钥设置文档指引详见APIv3秘钥设置指引)

6、参数解密

下面详细描述对通知数据进行解密的流程:

1、用商户平台上设置的APIv3密钥【微信商户平台—>账户设置—>API安全—>设置APIv3密钥】,记为key;
2、针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data;
3、使用key、nonce和associated_data,对数据密文resource.ciphertext进行解密,得到JSON形式的资源对象;

注: AEAD_AES_256_GCM算法的接口细节,请参考rfc5116。微信支付使用的密钥key长度为32个字节,随机串nonce长度12个字节,associated_data长度小于16个字节并可能为空。

  • 通知参数

图片alt

7、通知签名

加密不能保证通知请求来自微信。微信会对发送给商户的通知进行签名,并将签名值放在通知的HTTP头Wechatpay-Signature。商户应当验证签名,以确认请求来自微信,而不是其他的第三方。签名验证的算法请参考《微信支付API v3签名方案》

8、回调示例

  • 支付成功结果通知
{
    "id":"EV-2018022511223320873",
    "create_time":"2015-05-20T13:29:35+08:00",
    "resource_type":"encrypt-resource",
    "event_type":"TRANSACTION.SUCCESS",
    "resource":{
        "algorithm":"AEAD_AES_256_GCM",
        "ciphertext":"...",
        "nonce":"...",
        "original_type":"transaction",
        "associated_data":""
    },
    "summary":"支付成功"
}
  • 商户对resource对象进行解密后,得到的资源对象示例
{
    "transaction_id":"1217752501201407033233368018",
    "amount":{
        "payer_total":100,
        "total":100,
        "currency":"CNY",
        "payer_currency":"CNY"
    },
    "mchid":"1230000109",
    "trade_state":"SUCCESS",
    "bank_type":"CMC",
    "promotion_detail":[
        {
            "amount":100,
            "wechatpay_contribute":0,
            "coupon_id":"109519",
            "scope":"GLOBAL",
            "merchant_contribute":0,
            "name":"单品惠-6",
            "other_contribute":0,
            "currency":"CNY",
            "stock_id":"931386",
            "goods_detail":[
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                },
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                }
            ]
        },
        {
            "amount":100,
            "wechatpay_contribute":0,
            "coupon_id":"109519",
            "scope":"GLOBAL",
            "merchant_contribute":0,
            "name":"单品惠-6",
            "other_contribute":0,
            "currency":"CNY",
            "stock_id":"931386",
            "goods_detail":[
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                },
                {
                    "goods_remark":"商品备注信息",
                    "quantity":1,
                    "discount_amount":1,
                    "goods_id":"M1006",
                    "unit_price":100
                }
            ]
        }
    ],
    "success_time":"2018-06-08T10:34:56+08:00",
    "payer":{
        "openid":"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"
    },
    "out_trade_no":"1217752501201407033233368018",
    "appid":"wxd678efh567hg6787",
    "trade_state_desc":"支付成功",
    "trade_type":"MICROPAY",
    "attach":"自定义数据",
    "scene_info":{
        "device_id":"013467007045764"
    }
}

9、通知应答

支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx。

图片alt

注意:当商户后台应答失败时,微信支付将记录下应答的报文,建议商户按照以下格式返回。

{
    "code": "SUCCESS",
    "message": "成功"
}

参考文档