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>
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
import { Controller, Headers, Inject, Post, Req, Res } from '@nestjs/common';
|
|
import type { Request, Response } from 'express';
|
|
import { TradeService } from '../modules/trade/trade.service';
|
|
import { WECHAT_PROVIDER } from '../integrations/integrations.constants';
|
|
import type { IWechatProvider } from '../integrations/wechat/wechat.interface';
|
|
import { PayRedeemAnomalyService } from '../common/alert/pay-redeem-anomaly.service';
|
|
import { AlertService } from '../common/alert/alert.service';
|
|
|
|
type RawBodyRequest = Request & { body: Buffer };
|
|
|
|
@Controller('callbacks/wechat')
|
|
export class WechatPayCallbackController {
|
|
constructor(
|
|
private readonly tradeService: TradeService,
|
|
@Inject(WECHAT_PROVIDER) private readonly wechat: IWechatProvider,
|
|
private readonly payRedeemAnomaly: PayRedeemAnomalyService,
|
|
private readonly alert: AlertService,
|
|
) {}
|
|
|
|
@Post('pay')
|
|
async payNotify(
|
|
@Req() req: RawBodyRequest,
|
|
@Headers() headers: Record<string, string | string[] | undefined>,
|
|
@Res() res: Response,
|
|
) {
|
|
let orderNo: string | undefined;
|
|
try {
|
|
const rawBody =
|
|
(req as Request & { rawBody?: Buffer }).rawBody?.toString('utf8') ??
|
|
(typeof req.body === 'string' ? req.body : JSON.stringify(req.body ?? {}));
|
|
const notify = await this.wechat.parsePayNotification(headers, rawBody);
|
|
orderNo = notify.outTradeNo;
|
|
await this.tradeService.handlePaySuccess({
|
|
orderNo: notify.outTradeNo,
|
|
transactionId: notify.transactionId,
|
|
amountFen: notify.amountFen,
|
|
});
|
|
return res.status(200).json({ code: 'SUCCESS', message: '成功' });
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : '处理失败';
|
|
this.payRedeemAnomaly.onPayFail(message, { orderNo });
|
|
this.alert.notify({
|
|
level: 'P0',
|
|
category: 'pay',
|
|
title: '支付回调处理失败',
|
|
detail: `${orderNo ? `订单 ${orderNo}\n` : ''}${message}`,
|
|
dedupeKey: `pay_callback_fail|${orderNo ?? message.slice(0, 40)}`,
|
|
dedupeTtlSec: 120,
|
|
});
|
|
return res.status(500).json({ code: 'FAIL', message });
|
|
}
|
|
}
|
|
}
|