对接微信支付
This commit is contained in:
@@ -222,6 +222,87 @@ export class TradeService {
|
||||
return this.getOrder(userId, orderId);
|
||||
}
|
||||
|
||||
/** 微信支付回调:幂等更新订单为已支付并发券 */
|
||||
async handlePaySuccess(params: {
|
||||
orderNo: string;
|
||||
transactionId: string;
|
||||
amountFen: number;
|
||||
}) {
|
||||
const order = await this.prisma.order.findUnique({ where: { orderNo: params.orderNo } });
|
||||
if (!order) {
|
||||
throw new NotFoundException('订单不存在');
|
||||
}
|
||||
|
||||
if (order.payStatus === 'PAID') {
|
||||
return { orderId: order.id.toString(), alreadyPaid: true };
|
||||
}
|
||||
|
||||
const expectedFen = Math.round(Number(order.payAmount) * 100);
|
||||
if (params.amountFen > 0 && params.amountFen !== expectedFen) {
|
||||
throw new BadRequestException('支付金额与订单不符');
|
||||
}
|
||||
|
||||
const existingLog = await this.prisma.logThirdParty.findFirst({
|
||||
where: {
|
||||
provider: 'WECHAT_PAY',
|
||||
externalNo: params.transactionId,
|
||||
status: 'SUCCESS',
|
||||
},
|
||||
});
|
||||
if (existingLog) {
|
||||
return { orderId: order.id.toString(), alreadyPaid: true };
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
const current = await tx.order.findUnique({ where: { id: order.id } });
|
||||
if (!current || current.payStatus === 'PAID') return;
|
||||
|
||||
await tx.order.update({
|
||||
where: { id: order.id },
|
||||
data: {
|
||||
status: 'PENDING_SHIP',
|
||||
payStatus: 'PAID',
|
||||
paidAt: now,
|
||||
payExternalNo: params.transactionId,
|
||||
},
|
||||
});
|
||||
await tx.logThirdParty.create({
|
||||
data: {
|
||||
provider: 'WECHAT_PAY',
|
||||
scene: 'ORDER_PAY',
|
||||
refType: 'ORDER',
|
||||
refId: order.id,
|
||||
externalNo: params.transactionId,
|
||||
amount: order.payAmount,
|
||||
status: 'SUCCESS',
|
||||
},
|
||||
});
|
||||
await tx.commonEvent.create({
|
||||
data: buildOrderStatusEvent({
|
||||
orderId: order.id,
|
||||
fromStatus: 'PENDING_PAY',
|
||||
toStatus: 'PENDING_SHIP',
|
||||
operator: 'WECHAT_PAY',
|
||||
}),
|
||||
});
|
||||
const delivery = await tx.orderDelivery.findUnique({ where: { orderId: order.id } });
|
||||
if (!delivery) {
|
||||
await tx.orderDelivery.create({
|
||||
data: { orderId: order.id, provider: 'MANUAL' },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const refreshed = await this.prisma.order.findUnique({ where: { id: order.id } });
|
||||
if (refreshed?.payStatus === 'PAID') {
|
||||
await this.benefitService.grantOnOrderPaid(order.id);
|
||||
await this.deliveryProvider.scheduleAutoAdvance(order.id);
|
||||
}
|
||||
|
||||
return { orderId: order.id.toString(), alreadyPaid: false };
|
||||
}
|
||||
|
||||
async listOrders(userId: bigint, tab = 'all', page = 1, pageSize = 20) {
|
||||
const statuses = orderTabToStatuses(tab);
|
||||
const where = {
|
||||
|
||||
Reference in New Issue
Block a user