API接口文档
首页
支付业务
首页
支付业务
  • 说明

    • 概述
    • 接口说明
  • JSAPI支付

    • 二维码支付
    • JSAPI支付
    • JSAPI调起支付
    • JSAPI支付通知
    • 付款码支付
  • 交易管理

    • 交易查询
    • 申请退款
    • 退款查询
    • 统一交易通知
  • 商户进件
    • 进件概述
    • 图片上传
    • 进件申请
    • 进件状态查询
    • 进件信息修改
    • 认证状态查询
    • MCC行业编码
    • 创建自定义表单定义
    • 申请固定二维码

JSAPI支付通知

适用范围说明

本支付通知接口仅适用于通过 JSAPI 接口调起支付的场景。当商户通过 JSAPI 支付接口发起支付请求并支付完成后,平台会通过本通知接口将支付结果和相关用户信息推送给商户系统。

其他支付方式(如付款码支付、扫码支付等)的通知机制可能不同,请参考对应的文档说明。

与统一交易通知的关系

  • 如果在 JSAPI 支付请求中传递了 notify_url 参数,支付完成后仅通知该 URL,不会再通知统一交易通知配置的 default_notify_url
  • 如果未传递 notify_url 参数,支付完成后将通知统一交易通知配置的 default_notify_url
  • 通知优先级:notify_url(订单级)> default_notify_url(全局级)

支付通知API

通知结果参数列表 通知URL 是请求接口中提交的参数 notify_url,支付完成后,平台会把相关支付和用户信息发送到该URL,商户需要接收处理信息。

对后台通知交互时,如果平台收到商户的应答不是纯字符串success或超过5秒后返回时,平台认为通知失败,平台会通过一定的策略(通知频率为0/15/15/30/180/1800/1800/1800/1800/3600,单位:秒)间接性重新发起通知,尽可能提高通知的成功率,但不保证通知最终能成功。 由于存在重新发送后台通知的情况, 因此同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是, 当收到通知进行处理时, 首先检查对应业务数据的状态, 判断该通知是否已经处理过, 如果没有处理过再进行处理, 如果处理过直接返回结果成功。 在对业务数据进行状态检查和处理之前, 要采用数据锁进行并发控制, 以避免函数重入造成的数据混乱。 特别注意:商户后台接收到通知参数后,要对接收到通知参数里的订单号out_trade_sn和订单金额total_amount和自身业务系统的订单和金额做校验,校验一致后才更新数据库订单状态 后台通知通过请求中的notify_url进行, post方式给商户系统(通知参数内容为json格式的字符串)

通知参数

参数必填类型说明示例值
code是String(32)支付结果 000000 FAILSUCCESS
out_trade_sn是String(32)商户自定义的交易订单号202401010001
sub_merchant_id是String(32)子商户的Id1234567890
platform_trade_no是String(32)平台的交易号123
transaction_id是String(32)微信或者支付宝支付单号420000202401010001
sub_merchant_id是String(32)子商户的Id1234567890
sub_appid是String(32)小程序的APPID
sub_openid否String(32)openid和sub_openid可以选传其中之一,如果传了sub_appid则sub_openid必传oABC1234567890
total_amount是String(32)订单总金额 单位为分100
pay_time否String(32)支付时间 yyyyMMddHHmmss20260502012256
trade_type是String(32)交易类型 JSAPI 公众号支付
MINIAPP公众号支付
NATIVE 扫码支付
APP APP支付
nonce_str是String(32)随机字符串
fee_type否String(32)支付货币类型 CNYCNY
cash_fee否String(32)使用零钱金额1
attach否String(32)附加信息商户附加信息,可做扩展参数
sign_type否String(32)签名类型RSA2
sign否String(32)签名使用平台提供的公钥进行签名验证

通知示例

{
  "code": "000000",
  "out_trade_sn": "202401010001",
  "platform_trade_no": "P202401010001",
  "transaction_id": "420000202401010001",
  "sub_merchant_id": "1234567890",
  "sub_appid": "wx1234567890",
  "sub_openid": "oABC1234567890",
  "total_amount": "100",
  "pay_time": "20260502012256",
  "trade_type": "JSAPI",
  "nonce_str": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
  "fee_type": "CNY",
  "cash_fee": "100",
  "attach": "商户附加信息",
  "sign_type": "RSA2",
  "sign": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
}

通知响应

商户接收到通知后,需要返回纯字符串 success 表示接收成功,否则平台会认为通知失败并重新发送。

成功响应

success

失败响应

fail

安全注意事项

1. 签名验证(必须)

所有通知都必须进行签名验证,以确保数据来自平台且未被篡改:

  1. 从通知参数中获取 sign_type 和 sign 字段
  2. 将除 sign 外的所有参数按字母顺序排序
  3. 使用平台提供的公钥验证签名
  4. 签名验证失败的通知必须拒绝处理

2. 金额校验(必须)

必须校验通知金额与业务订单金额是否一致:

  1. 提取通知中的 out_trade_sn 和 total_amount
  2. 从业务数据库查询对应订单的原始金额
  3. 金额不一致时拒绝处理并记录异常
  4. 金额单位为分,注意单位转换

3. 重复通知处理

平台可能会多次发送同一通知,必须实现幂等处理:

# 伪代码示例
def handle_notify(notify_data):
    # 1. 验证签名
    if not verify_sign(notify_data):
        return "fail"
    
    # 2. 查询订单状态
    order = get_order(notify_data['out_trade_sn'])
    
    # 3. 检查是否已处理
    if order.status == 'PAID':
        return "success"  # 已处理,直接返回成功
    
    # 4. 校验金额
    if order.amount != notify_data['total_amount']:
        log_error("金额不一致")
        return "fail"
    
    # 5. 使用数据库事务处理(防并发)
    with transaction:
        order = get_order_for_update(notify_data['out_trade_sn'])
        if order.status == 'PAID':
            return "success"  # 双重检查
        
        # 6. 更新订单状态
        order.status = 'PAID'
        order.transaction_id = notify_data['transaction_id']
        order.pay_time = notify_data['pay_time']
        order.save()
    
    return "success"

4. 并发控制

必须使用数据库锁或分布式锁防止并发处理同一通知:

  • 推荐使用数据库行锁(SELECT ... FOR UPDATE)
  • 或使用 Redis 分布式锁(锁 key 为 out_trade_sn)
  • 锁超时时间建议设置为 10-30 秒

5. 响应要求

  • 收到通知后必须尽快响应(建议 2 秒内)
  • 响应必须是纯字符串 success 或 fail
  • 不要返回 JSON 或 HTML,否则平台会认为通知失败
  • 业务处理可以异步进行,但响应必须同步返回
Prev
JSAPI调起支付
Next
付款码支付