文件
shanghaipeiwan/server/tests/payment-amount-integrity.spec.ts
xcbyy 77aa4cb50b feat(order): 平台派单闭环(发需求单进入待接单池)
- 下单页新增「指定大神 / 平台派单」模式:平台派单填品类、预算、地点/选点,expertId=0

- 服务端:平台派单单据支付后进入待接单池(余额支付即时入池,微信支付确认后入池),预算由买家出价但受 1~2000 元/小时约束

- 抢单由认领大神写入 expert_id 并转履约中;30 分钟无人接单沿用自动全额退款

- 修复订单 INSERT 占位符少一个导致下单报 Column count doesn't match 的问题,并新增列数/占位符一致性护栏

- 111 套件/737 用例全绿;线上 1 元实测:下单→待接单→池内 640m,测试数据已回滚
2026-10-21 15:16:03 +08:00

36 行
1.5 KiB
TypeScript

// 已读取AGENTS.md
import * as fs from 'fs';
import * as path from 'path';
/**
* 第十九批回归闸门:预支付金额不可篡改(低价支付高价订单)
*/
describe('第十九批支付金额完整性闸门', () => {
const rootDir = path.resolve(__dirname, '../../');
const indexCode = fs.readFileSync(path.join(rootDir, 'server/src/index.ts'), 'utf-8');
const repoCode = fs.readFileSync(path.join(rootDir, 'server/src/db/repository.ts'), 'utf-8');
it('订单归属解析必须携带订单金额', () => {
const start = repoCode.indexOf('async getOrderOwnership(');
const block = repoCode.slice(start, start + 1000);
expect(block).toContain('o.amount');
expect(block).toContain('amount: Number(r.amount)');
});
it('入账必须校验实收金额与支付意图一致', () => {
const start = repoCode.indexOf('async applyPaymentSuccess(');
const block = repoCode.slice(start, start + 1800);
expect(block).toContain('amountMismatch');
expect(block).toContain("reason: 'amount_mismatch'");
});
it('预支付:仅买家可发起,且订单金额以服务端订单为准', () => {
const start = indexCode.indexOf("app.post('/api/pay/wechat/prepay'");
const block = indexCode.slice(start, start + 2200);
expect(block).toContain("'发起微信支付'");
expect(block).toContain('repo.getOrderOwnership(String(orderId))');
expect(block).toContain('payAmount = Number(own.amount) || 0');
expect(block).not.toContain('const uid = Number(userId) || 0;');
});
});