fix: reconcile shared-channel receipts and protocol logs

This commit is contained in:
hectorzhao
2026-07-24 12:52:06 +08:00
parent 3997349c21
commit ca12f14b00
14 changed files with 1110 additions and 43 deletions
@@ -1,4 +1,4 @@
import { Body, Controller, Post } from '@nestjs/common';
import { BadRequestException, Body, Controller, Post } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import {
GatewayInboundAuthDto,
@@ -28,7 +28,7 @@ export class GatewayEventsController {
@Post('submit-result')
submitResult(@Body() body: GatewaySubmitResultDto) {
return this.trackGatewayEvent('submit_resp', body, () => this.sendChain.handleSubmitResult(body));
return this.sendChain.handleSubmitResult(body);
}
@Post('receipt')
@@ -41,6 +41,25 @@ export class GatewayEventsController {
return this.trackGatewayEvent('deliver_uplink', body, () => this.sendChain.handleUplink(body));
}
@Post('protocol-log')
protocolLog(@Body() body: ProtocolLogInput) {
const allowedPacket = (
body.direction === 'platform_to_channel'
&& ['submit', 'deliver_resp'].includes(body.eventType)
) || (
body.direction === 'channel_to_platform'
&& body.eventType === 'submit_resp'
) || (
body.direction === 'platform_to_client'
&& body.eventType === 'submit_resp'
);
if (body.protocol !== 'cmpp' || !allowedPacket || !['success', 'failed'].includes(body.status)) {
throw new BadRequestException('Unsupported Gateway protocol log event');
}
this.protocolLogs.record(body);
return { accepted: true };
}
@Post('dead-letter')
deadLetter(@Body() body: GatewaySubmitDeadLetterDto) {
return this.sendChain.recordGatewaySubmitDeadLetter(body);
@@ -110,14 +129,25 @@ export class GatewayEventsController {
messageId: (value.messageId ?? value.platformMessageId) as string,
gatewayMessageId: (value.gatewayMessageId ?? value.msgId ?? value.upstreamMessageId) as string,
phone: (value.phoneNumber ?? value.srcTerminalId ?? value.destinationId) as string,
resultCode: (value.result ?? value.status ?? value.stat) as string,
resultCode: (value.result ?? value.submitStatus ?? value.rawStatus ?? value.status ?? value.stat) as string,
detail: { sequenceId: value.sequenceId, connectionId: value.connectionId },
};
this.protocolLogs.record({ ...common, status: 'received', durationMs: 0 });
try {
const result = await action();
const resultValue = result && typeof result === 'object'
? result as Record<string, unknown>
: {};
this.protocolLogs.record({
...common,
tenantId: (resultValue.tenantId ?? common.tenantId) as string,
applicationId: (resultValue.applicationId ?? common.applicationId) as string,
channelId: common.channelId ?? resultValue.channelId as string,
account: common.account ?? resultValue.account as string,
messageId: (resultValue.messageId ?? common.messageId) as string,
gatewayMessageId: common.gatewayMessageId
?? (resultValue.gatewayMessageId ?? resultValue.msgId) as string,
resultCode: common.resultCode
?? (resultValue.result ?? resultValue.status) as string,
status: 'success',
durationMs: Date.now() - startedAt,
});