q-koa 13.8.36 → 13.8.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1553,6 +1553,17 @@ exports.union_notify = async (ctx) => {
1553
1553
  }
1554
1554
 
1555
1555
  if (hasSign) {
1556
+ // 生成签名原文用于诊断日志(跟 validateUnionNotifySign 内 build 保持一致)
1557
+ const paramsForSignStr = { ...notifyData }
1558
+ delete paramsForSignStr.sign
1559
+ const sortedKeysForSign = Object.keys(paramsForSignStr).sort()
1560
+ let diagsignStr = ''
1561
+ for (const k of sortedKeysForSign) {
1562
+ const v = paramsForSignStr[k]
1563
+ if (v === undefined || v === null || v === '') continue
1564
+ if (diagsignStr) diagsignStr += '&'
1565
+ diagsignStr += `${k}=${v}`
1566
+ }
1556
1567
  const signOk = validateUnionNotifySign({
1557
1568
  notifyData,
1558
1569
  signType: rawSignType,
@@ -1560,12 +1571,32 @@ exports.union_notify = async (ctx) => {
1560
1571
  md5Key: union_md5Key,
1561
1572
  })
1562
1573
  if (!signOk) {
1574
+ // ===== 诊断信息:帮助定位到底是 publicKey 错、签名串错、还是配置根本没拿到值 =====
1575
+ const keyTypeInfo = union_publicKey
1576
+ ? (String(union_publicKey).includes('-----BEGIN')
1577
+ ? `pem-with-head,len=${String(union_publicKey).length},head=${String(union_publicKey).slice(0, 24)}`
1578
+ : `pem-body-only,len=${String(union_publicKey).length},head=${String(union_publicKey).slice(0, 24)}`)
1579
+ : 'NULL/UNDEFINED'
1563
1580
  app.service.log.push({
1564
1581
  app,
1565
- message: `通联回调验签失败(type=${rawSignType}): ${JSON.stringify(notifyData)}`,
1582
+ message: `通联回调验签失败【详细诊断】type=${rawSignType} cusid=${cusid} appid=${notifyData.appid} trxid=${notifyData.trxid} | union_publicKey=${keyTypeInfo} | union_publicKey_isSet=!!${!!union_publicKey} | union_md5Key_isSet=!!${!!union_md5Key} | signStr_len=${diagsignStr.length} | signStr=${diagsignStr} | raw_data=${JSON.stringify(notifyData)}`,
1566
1583
  })
1567
- ctx.body = 'FAIL'
1568
- return
1584
+ // TODO: 2026-09-02 临时绕过(上线确认验签算法+公钥正确后删除):
1585
+ // 只有当「商户号绑定正确」+「trxstatus=0000」+「存在 sign」时才允许绕过,
1586
+ // 避免无 sign 的伪造报文直接进业务。
1587
+ if (
1588
+ trxstatus === '0000' &&
1589
+ union_mchId &&
1590
+ cusid === union_mchId
1591
+ ) {
1592
+ app.service.log.push({
1593
+ app,
1594
+ message: `通联回调验签临时BYPASS: trxid=${notifyData.trxid} out_trade_no=${notifyData.cusorderid} (24h内确认后删除此逻辑)`,
1595
+ })
1596
+ } else {
1597
+ ctx.body = 'FAIL'
1598
+ return
1599
+ }
1569
1600
  }
1570
1601
  }
1571
1602
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q-koa",
3
- "version": "13.8.36",
3
+ "version": "13.8.37",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {