fix(courier): log XFX track callback rawBody and Content-Type

Capture raw request for courier track callbacks regardless of Content-Type and persist contentType/rawBody/query into log_third_party for empty-body diagnosis.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-07 18:57:31 +08:00
parent b626db5d84
commit 155426b669
3 changed files with 163 additions and 11 deletions
@@ -1,7 +1,9 @@
import { Body, Controller, Param, Post, Res } from '@nestjs/common';
import type { Response } from 'express';
import { Body, Controller, Param, Post, Req, Res } from '@nestjs/common';
import type { Request, Response } from 'express';
import { DeliveryCallbackService } from './delivery-callback.service';
type CourierCallbackRequest = Request & { rawBody?: Buffer };
@Controller('callbacks')
export class DeliveryCallbackController {
constructor(private readonly deliveryCallbackService: DeliveryCallbackService) {}
@@ -11,12 +13,14 @@ export class DeliveryCallbackController {
async trackByProvider(
@Param('provider') provider: string,
@Body() body: unknown,
@Req() req: CourierCallbackRequest,
@Res() res: Response,
) {
const result = await this.deliveryCallbackService.handleTrackCallback(
provider,
body,
`/api/v1/callbacks/courier/${provider}/track`,
this.buildRequestMeta(req),
);
// 直出承运商约定结构,避免被全局 { code:0, data } 包装
return res.status(200).json(result);
@@ -24,12 +28,29 @@ export class DeliveryCallbackController {
/** 兼容旧路径,默认按小飞侠解析 */
@Post('delivery/track')
async trackLegacy(@Body() body: unknown, @Res() res: Response) {
async trackLegacy(
@Body() body: unknown,
@Req() req: CourierCallbackRequest,
@Res() res: Response,
) {
const result = await this.deliveryCallbackService.handleTrackCallback(
'xfx',
body,
'/api/v1/callbacks/delivery/track',
this.buildRequestMeta(req),
);
return res.status(200).json(result);
}
private buildRequestMeta(req: CourierCallbackRequest) {
const contentType = req.headers['content-type'];
return {
contentType: Array.isArray(contentType) ? contentType.join(', ') : contentType || null,
rawBody: req.rawBody?.toString('utf8') ?? null,
query:
req.query && typeof req.query === 'object'
? (req.query as Record<string, unknown>)
: undefined,
};
}
}