文件
shanghaipeiwan/server/tests/wechat-refund.spec.ts
xcbyy 8edffbefa2 feat(pay): 接入微信支付V3原路退款(按支付渠道分流 + 幂等 + 退款回调)
- 新增微信退款客户端 createRefund/queryRefundByOutRefundNo(/v3/refund/domestic/refunds)

- 新增退款桥接模块与 payment_refunds 幂等退款记录表

- 订单退款按渠道分流:微信支付原路退回微信;余额支付退回钱包余额;微信退款失败(502)不回退余额,防重复退款

- 覆盖拒单/买家取消/仲裁全额与部分/超时自动退款;新增 /api/pay/wechat/refund-notify 回调

- 后台新增退款回调地址配置;文档补充退款验收说明

- 新增回归护栏 wechat-refund.spec.ts(77 套件/605 用例全绿)
2026-10-19 08:47:08 +08:00

43 行
2.0 KiB
TypeScript

// 已读取AGENTS.md
import * as fs from 'fs';
import * as path from 'path';
/**
* 第六十一批回归闸门:微信原路退款接入(按支付渠道分流 + 幂等)
*/
describe('第六十一批微信原路退款闸门', () => {
const rootDir = path.resolve(__dirname, '../../');
const payV3 = fs.readFileSync(path.join(rootDir, 'server/src/core/pay/wechat-pay-v3.ts'), 'utf-8');
const bridge = fs.readFileSync(path.join(rootDir, 'server/src/core/pay/refund-bridge.ts'), 'utf-8');
const repoCode = fs.readFileSync(path.join(rootDir, 'server/src/db/repository.ts'), 'utf-8');
const indexCode = fs.readFileSync(path.join(rootDir, 'server/src/index.ts'), 'utf-8');
const mysqlCode = fs.readFileSync(path.join(rootDir, 'server/src/db/mysql.ts'), 'utf-8');
it('支付客户端具备退款与退款查单能力', () => {
expect(payV3).toContain('export async function createRefund(');
expect(payV3).toContain("'/v3/refund/domestic/refunds'");
expect(payV3).toContain('export async function queryRefundByOutRefundNo(');
});
it('退款桥接模块可注入执行器', () => {
expect(bridge).toContain('export function setWeChatRefundFn(');
expect(bridge).toContain('export async function tryRefundToWeChat(');
});
it('仓储层按支付渠道分流退款并支持幂等记录', () => {
expect(repoCode).toContain('private async refundOrderPayment(');
expect(repoCode).toContain('private async orderPaidViaWechat(');
expect(repoCode).toContain('async getRefundByOutRefundNo(');
expect(repoCode).toContain('async upsertRefundRecord(');
// 四个退款入口均使用统一分流
const count = (repoCode.match(/this\.refundOrderPayment\(/g) || []).length;
expect(count).toBeGreaterThanOrEqual(5);
expect(mysqlCode).toContain('CREATE TABLE IF NOT EXISTS payment_refunds');
});
it('后端注册退款执行器并提供退款回调', () => {
expect(indexCode).toContain('setWeChatRefundFn(async');
expect(indexCode).toContain("app.post('/api/pay/wechat/refund-notify'");
});
});