35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
const xml = await this.payments.handleRefundNotify(rawBodyOf(req));
|
|
res.type('application/xml').send(xml);
|
|
}
|
|
}
|