mockpay功能调试
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-08-20 00:51:18 +08:00
parent 2f633b307c
commit 4db21cf1a1
11 changed files with 320 additions and 531 deletions
@@ -24,7 +24,7 @@ import { AuthService } from '../iam/auth.service';
import { PromoCodeService } from '../promo/promo-code.service';
import { TicketService } from '../common/ticket.service';
import { PAY_PROVIDER, DELIVERY_PROVIDER } from '../../integrations/integrations.constants';
import { IPayProvider } from '../../integrations/pay/pay.interface';
import { IPayProvider, type PayOrderResult } from '../../integrations/pay/pay.interface';
import { IDeliveryProvider } from '../../integrations/delivery/delivery.interface';
import { IpGeoService } from '../../common/geo/ip-geo.service';
import { buildOrderClientLocationSnapshot } from '../../common/geo/client-location.util';
@@ -2173,6 +2173,9 @@ export class TradeService {
throw new BadRequestException('订单已超时未支付');
}
const mockPaid = await this.tryMockPayProxyOrder(order, 'PARTNER_PROXY_MOCK_PAY');
if (mockPaid) return mockPaid;
const lockedMethod = this.parseProxyPayMethod(order.channelSource);
if (lockedMethod && lockedMethod !== payMethod) {
throw new BadRequestException(
@@ -2217,33 +2220,7 @@ export class TradeService {
throw e;
}
if (payResult.mode === 'native') {
return {
mode: 'native' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
codeUrl: payResult.codeUrl,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
if (payResult.mode === 'jsapi') {
return {
mode: 'jsapi' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
prepay: payResult.prepay,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
await this.markProxyOrderPaid(order.id, payResult.externalNo, 'PARTNER_PROXY_MOCK_PAY');
return {
mode: 'mock' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
return this.finishProxyPayResult(order, payResult, 'PARTNER_PROXY_MOCK_PAY');
}
/** 总部代下单支付:仅 Native 收款码 */
@@ -2262,6 +2239,9 @@ export class TradeService {
throw new BadRequestException('订单已超时未支付');
}
const mockPaid = await this.tryMockPayProxyOrder(order, 'HQ_PROXY_MOCK_PAY');
if (mockPaid) return mockPaid;
this.payRedeemAnomaly.onPayAttempt(Number(order.payAmount), {
orderNo: order.orderNo,
userId: order.userId,
@@ -2277,20 +2257,15 @@ export class TradeService {
});
throw e;
}
if (payResult.mode !== 'native') {
const result = await this.finishProxyPayResult(order, payResult, 'HQ_PROXY_MOCK_PAY');
if (result.mode !== 'native' && result.mode !== 'mock') {
this.payRedeemAnomaly.onPayFail('无法生成收款码', {
orderNo: order.orderNo,
userId: order.userId,
});
throw new BadRequestException('无法生成收款码');
}
return {
mode: 'native' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
codeUrl: payResult.codeUrl,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
return result;
}
/** Mock 环境确认代下单支付 */
@@ -2375,6 +2350,64 @@ export class TradeService {
return this.fulfillmentService.getOrderTrack(orderId);
}
private async tryMockPayProxyOrder(
order: { id: bigint; orderNo: string; payExpireAt: Date | null },
operator: string,
) {
if (!loadAppConfig().mockPay) return null;
await this.markProxyOrderPaid(order.id, `MOCK-${Date.now()}`, operator);
return {
mode: 'mock' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
/** 代下单支付结果:Mock 环境直接落单,真实环境返回收款码/JSAPI */
private async finishProxyPayResult(
order: { id: bigint; orderNo: string; payExpireAt: Date | null },
payResult: PayOrderResult,
operator: string,
) {
const mockPay = loadAppConfig().mockPay;
const isMockNative =
payResult.mode === 'native' &&
(mockPay || payResult.codeUrl.startsWith('mock://'));
if (payResult.mode === 'mock' || isMockNative) {
await this.markProxyOrderPaid(order.id, payResult.externalNo, operator);
return {
mode: 'mock' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
if (payResult.mode === 'native') {
return {
mode: 'native' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
codeUrl: payResult.codeUrl,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
if (payResult.mode === 'jsapi') {
return {
mode: 'jsapi' as const,
orderId: order.id.toString(),
orderNo: order.orderNo,
prepay: payResult.prepay,
payExpireAt: order.payExpireAt?.toISOString() ?? null,
};
}
throw new BadRequestException('支付发起失败');
}
private async markProxyOrderPaid(orderId: bigint, externalNo: string, operator: string) {
const order = await this.prisma.order.findUnique({ where: { id: orderId } });
if (!order) throw new NotFoundException('订单不存在');