@@ -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('订单不存在');
|
||||
|
||||
Reference in New Issue
Block a user