3328c52cb4
Add outbound group-bot alerts, rate/amount rules, stuck-order cron, HQ test button, and health db/redis checks. Co-authored-by: Cursor <cursoragent@cursor.com>
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import { Controller, Headers, Post, Req, Res } from '@nestjs/common';
|
|
import type { Request, Response } from 'express';
|
|
import { PrismaService } from '../common/prisma/prisma.module';
|
|
import { AlertService } from '../common/alert/alert.service';
|
|
|
|
@Controller('callbacks/wechat')
|
|
export class WechatRefundCallbackController {
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
private readonly alert: AlertService,
|
|
) {}
|
|
|
|
@Post('refund')
|
|
async refundNotify(
|
|
@Req() req: Request,
|
|
@Headers() _headers: Record<string, string | string[] | undefined>,
|
|
@Res() res: Response,
|
|
) {
|
|
try {
|
|
const body = typeof req.body === 'object' ? req.body : {};
|
|
const outRefundNo = String((body as Record<string, unknown>).out_refund_no ?? '');
|
|
const refundId = String((body as Record<string, unknown>).refund_id ?? outRefundNo);
|
|
|
|
const existing = await this.prisma.logThirdParty.findFirst({
|
|
where: { provider: 'WECHAT_REFUND', externalNo: refundId, status: 'SUCCESS' },
|
|
});
|
|
if (existing) {
|
|
return res.status(200).json({ code: 'SUCCESS', message: '成功' });
|
|
}
|
|
|
|
await this.prisma.logThirdParty.create({
|
|
data: {
|
|
provider: 'WECHAT_REFUND',
|
|
scene: 'ORDER_REFUND_CALLBACK',
|
|
refType: 'TICKET',
|
|
refId: BigInt(0),
|
|
externalNo: refundId,
|
|
status: 'SUCCESS',
|
|
},
|
|
});
|
|
|
|
return res.status(200).json({ code: 'SUCCESS', message: '成功' });
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : '处理失败';
|
|
this.alert.notify({
|
|
level: 'P0',
|
|
category: 'pay',
|
|
title: '退款回调处理失败',
|
|
detail: message,
|
|
dedupeKey: `refund_callback_fail|${message.slice(0, 40)}`,
|
|
dedupeTtlSec: 120,
|
|
});
|
|
return res.status(500).json({ code: 'FAIL', message });
|
|
}
|
|
}
|
|
}
|