补齐微信虚拟支付查单与补偿

接入微信官方虚拟支付查单并缓存稳定接口令牌
让用户确认与订单过期补偿统一核对支付类型、状态、金额和单号
增加单笔历史订单的 dry-run 与确认指纹补单工具
隔离运行时身份与敏感 openid 文件并补充配置契约和回归测试
This commit is contained in:
2026-07-13 13:12:44 +08:00
parent 06aa99e3eb
commit 2f69f2fda2
16 changed files with 1343 additions and 33 deletions
@@ -0,0 +1,107 @@
#!/usr/bin/env node
import assert from 'node:assert/strict';
import {
buildReconcileFingerprint,
calcPaySig,
normalizeLocalOrderSnapshot,
paidAtMicrosFromWechatOrder,
parseEnvText,
validateQueryResult,
} from './reconcile-wechat-virtual-payment-order.mjs';
assert.equal(
calcPaySig(
'12345',
'/xpay/query_user_balance',
'{"openid": "xxx", "user_ip": "127.0.0.1", "env": 0}',
),
'c37809f27c6d7fd1837ad2500a04512b66b34fd793a39a385fade56dca89a4b5',
);
assert.deepEqual(
parseEnvText(
'WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_ENV=0 # 现网\nWECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_APP_KEY="app-key"\n',
),
{
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_APP_KEY: 'app-key',
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_ENV: '0',
},
);
const localOrder = { amountCents: 600, orderId: 'order-001' };
const paidOrder = {
order_fee: 600,
order_id: 'order-001',
order_type: 0,
status: 2,
};
assert.deepEqual(validateQueryResult(localOrder, paidOrder), {
eligibleForCredit: true,
status: 2,
});
assert.deepEqual(validateQueryResult(localOrder, { ...paidOrder, status: 1 }), {
eligibleForCredit: false,
status: 1,
});
assert.deepEqual(
validateQueryResult(localOrder, { ...paidOrder, order_type: 7 }),
{ eligibleForCredit: true, status: 2 },
);
assert.equal(
paidAtMicrosFromWechatOrder({ paid_time: 1_777_111_200 }),
1_777_111_200_000_000,
);
assert.throws(() => paidAtMicrosFromWechatOrder({}), /paid_time/u);
assert.throws(
() => validateQueryResult(localOrder, { ...paidOrder, order_fee: 601 }),
/金额/u,
);
assert.throws(
() => validateQueryResult(localOrder, { ...paidOrder, order_type: 1 }),
/可入账虚拟支付单/u,
);
assert.throws(
() => validateQueryResult(localOrder, { ...paidOrder, order_type: 8 }),
/可入账虚拟支付单/u,
);
assert.equal(
buildReconcileFingerprint({ orderId: 'order-001', status: 2 }),
buildReconcileFingerprint({ orderId: 'order-001', status: 2 }),
);
assert.notEqual(
buildReconcileFingerprint({ orderId: 'order-001', status: 2 }),
buildReconcileFingerprint({ orderId: 'order-001', status: 1 }),
);
assert.deepEqual(
normalizeLocalOrderSnapshot([
'order-001',
'user-001',
'points_60',
'60 泥点',
[0],
600,
[0],
'wechat_mp_virtual',
[1],
[1],
1_777_111_200_000_000,
0,
[1],
[1],
[1],
[1],
[1],
]),
{
amount_cents: 600,
kind: [0],
order_id: 'order-001',
payment_channel: 'wechat_mp_virtual',
status: [0],
user_id: 'user-001',
},
);
console.log('wechat virtual payment reconcile checks passed');
File diff suppressed because it is too large Load Diff