收藏
回答

小程序虚拟支付 query_order 按官方文档实现仍返回“签名字段[pay_sig]为空”?

当前请求方式

请求 URL 形如:

https://api.weixin.qq.com/xpay/query_order?access_token=ACCESS_TOKEN&pay_sig=PAY_SIG&signature=SIGNATURE

请求体最小化为:

{
  "openid": "o_nN816_S2uN94viQe-pzZTb_efc",
  "env": 0,
  "order_id": "VIP202605301756083777"
}

签名算法

我们按文档实现:

pay_sig = to_hex(hmac_sha256(appKey, uri + '&' + post_body))
signature = to_hex(hmac_sha256(session_key, post_body))

对应本次请求:

  • uri/xpay/query_order
post_body:{"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605301756083777"}

关键日志

获取小程序access_token成功 { expiresIn: 7200, tokenLength: 137 }

构造官方示例顺序query_order请求体
payload: {
  openid: 'o_nN816_S2uN94viQe-pzZTb_efc',
  env: 0,
  order_id: 'VIP202605301756083777'
}
keys: [ 'openid', 'env', 'order_id' ]

生成虚拟支付pay_sig
uri: '/xpay/query_order'
signSource: '/xpay/query_order&{"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605301756083777"}'
signSourceLength: 102
bodyTextLength: 84
hasAppKey: true
appKeyLength: 32

发起虚拟支付请求
uri: '/xpay/query_order'
hasAccessToken: true
accessTokenLength: 137
paySigLength: 64
signatureLength: 64
bodyText: '{"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605301756083777"}'
requestUrl: 'https://api.weixin.qq.com/xpay/query_order?access_token=***&pay_sig=e2b5362b9c8fe044d9a46fe788e8ffe9fdee65dca5a1117e90571bae5c7d388a&signature=1897331e8fde216e84a5d272b046f8528d4943dc4d0ae3f9c1c78066f711a71e'

虚拟支付请求已发送
hostname: 'api.weixin.qq.com'
path: '/xpay/query_order?access_token=104_Qc725U-7C3nA17LI6vraJf8yFkl0ozzMHVcY0zXTHRIGcVVoawe_-cZtRtGfOFMWKOLwHQsLoIBcf2vX7T5npMl2DLylk90aQd0NhzerV21wWNGgFbUXkcHgvnwPTDfAFAXBL&pay_sig=e2b5362b9c8fe044d9a46fe788e8ffe9fdee65dca5a1117e90571bae5c7d388a&signature=1897331e8fde216e84a5d272b046f8528d4943dc4d0ae3f9c1c78066f711a71e'
method: 'POST'

最终返回:
签名字段[pay_sig]为空 rid: 6a1b24c4-3601a5f6-02083b3a

最新 rid

6a1b24c4-3601a5f6-02083b3a

已排除项

我们已排除以下可能性:

  • pay_sig 未放在 query 中
  • pay_sig 大小写问题当前为小写 hex
  • signature 缺失已补充 signature
  • query_order 请求体字段过多已最小化为 openid + env + order_id
  • wx_order_id 空字符串影响已测试不传 wx_order_id
  • URL 拼装方式问题已测试不同 https.request 写法
  • post_body 与签名原文不一致日志确认参与签名的 body 与实际发送 body 一致
  • uri 带 query 参与签名当前签名只使用 /xpay/query_order

参考文档

我们当前实现依据以下官方文档:

  • api_query_order
  • 虚拟支付签名详解
  • 文档中“支付签名加在 query 后面”的说明

希望微信侧协助确认

  1. /xpay/query_order 在当前能力下,是否确实只需要 pay_sig,还是还存在未文档化的隐藏要求
  2. 当 query 中已经实际带有 pay_sig 时,为什么接口仍返回“签名字段[pay_sig]为空”
  3. 是否可根据 rid 协助核查平台侧实际收到的 query 参数及验签失败原因
  4. 是否存在当前小程序/虚拟支付商户配置状态异常导致该接口无法正确识别 pay_sig


回答关注问题邀请回答
收藏

2 个回答

  • Memory (私信不回复)
    Memory (私信不回复)
    05-31

    这报错是你自己代码写的有问题,你可以直接在https://developers.weixin.qq.com/console/devtools/debug 查你的rid请求信息

    通过API也可以查https://developers.weixin.qq.com/miniprogram/dev/server/API/openApi-mgnt/api_getridinfo.html


    05-31
    有用
    回复
  • 智能回答 智能回答 本次回答由AI生成
    05-31
    有用
    回复 1
    • 陈高
      陈高
      05-31
      补充排查信息如下,请协助进一步核查平台侧实际收到的 query 参数及验签链路:
      1. 接口信息
      调用接口:
      POST https://api.weixin.qq.com/xpay/query_order
      2. 最新错误信息
      接口返回错误:
      签名字段[pay_sig]为空
      rid:
      6a1b24c4-3601a5f6-02083b3a
      另外还有一条最新 rid:
      6a1b6a32-7cbb2a35-2aff685e
      3. access_token 有效性
      服务端日志显示 access_token 获取成功:
      {
        "expiresIn": 7200,
        "tokenLength": 137
      }
      4. 服务端实际请求参数
      服务端实际发起请求时,query 中明确带有 pay_sig 和 signature:
      https://api.weixin.qq.com/xpay/query_order?access_token=***&pay_sig=e2b5362b9c8fe044d9a46fe788e8ffe9fdee65dca5a1117e90571bae5c7d388a&signature=1897331e8fde216e84a5d272b046f8528d4943dc4d0ae3f9c1c78066f711a71e
      另一条请求日志:
      https://api.weixin.qq.com/xpay/query_order?access_token=***&pay_sig=19f2f7733cf19e3d73a81ba06e256ef5493f5ce270c2921cd18d2fc93aaceca5&signature=e6c6f9527226a3a443f9a41b979b7a9c7d4917a20e1331fa121f6bc611d6448a
      5. 请求体
      当前已按最小请求体调用:
      {"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605301756083777"}
      另一条请求体:
      {"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605302252211520"}
      6. pay_sig 生成方式
      按照文档中的 HMAC-SHA256 规则生成:
      pay_sig = HMAC_SHA256(appKey, uri + '&' + post_body)
      签名前原文示例:
      /xpay/query_order&{"openid":"o_nN816_S2uN94viQe-pzZTb_efc","env":0,"order_id":"VIP202605302252211520"}
      服务端实现已使用小写 hex 输出,且已用文档给出的 Python 样例做过本地对照验签,算法结果一致。
      7. 已排除项
      - pay_sig 未放在 query 中:已排除
      - access_token 获取失败:已排除
      - body 与签名原文不一致:已排除
      - 大小写问题:已排除
      - 未传 signature:已补充 signature 仍报同样错误
      - 请求体字段过多:已最小化为 openid/env/order_id
      烦请协助根据上述 rid 核查:
      1)平台侧实际收到的 query 参数中是否包含 pay_sig
      2)若已收到,为什么会返回“签名字段[pay_sig]为空”
      3)当前 /xpay/query_order 是否存在未文档化的额外要求
      05-31
      回复
登录 后发表内容