import { Controller, Post, Req, Res } from '@nestjs/common'; import type { Request, Response } from 'express'; import { Public } from '../../common/auth'; import { PaymentsService } from './payments.service'; /** 取原始请求体。虚拟支付回调是 XML,必须拿到未经解析的字节。 */ function rawBodyOf(req: Request): string { const withRaw = req as Request & { rawBody?: Buffer }; if (withRaw.rawBody) return withRaw.rawBody.toString('utf8'); return typeof req.body === 'string' ? req.body : String(req.body ?? ''); } /** * 虚拟支付回调。由微信服务器调用,不带小程序身份,靠签名与业务校验保证安全。 * 请求体是 XML,应答也必须是 XML。 */ @Controller('v1/payments') export class PaymentsController { constructor(private readonly payments: PaymentsService) {} @Public() @Post('notify') async notify(@Req() req: Request, @Res() res: Response): Promise { const xml = await this.payments.handleDeliverNotify(rawBodyOf(req)); res.type('application/xml').send(xml); } @Public() @Post('refund-notify') async refundNotify(@Req() req: Request, @Res() res: Response): Promise { const xml = await this.payments.handleRefundNotify(rawBodyOf(req)); res.type('application/xml').send(xml); } }