fix: route through reported signature channels

This commit is contained in:
hectorzhao
2026-07-13 10:02:48 +08:00
parent 7703873346
commit ade06058f5
5 changed files with 70 additions and 19 deletions
+20 -14
View File
@@ -1626,8 +1626,6 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
await reject('TEMPLATE', '短信模板尚未审核通过');
} else if (!template.signature || template.signature.auditStatus !== 'approved') {
await reject('SIGNATURE', '短信签名尚未审核通过');
} else if (template.signature.reportStatus !== 'approved') {
await reject('REPORT', '短信签名尚未报备通过');
} else {
const risk = await this.riskReview.evaluateTask({
tenantId: application.tenantId,
@@ -1861,7 +1859,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
}
private async selectChannelForMessage(
message: { id: string; tenantId: string; applicationId?: string | null; phoneNumber: string },
message: { id: string; tenantId: string; applicationId?: string | null; templateId?: string | null; phoneNumber: string; template?: { signature?: { id?: string | null } | null } | null; signature?: { id?: string | null } | null },
options: { forceNational?: boolean; excludeChannelIds?: string[] } = {},
): Promise<RoutedChannel> {
if (!message.applicationId) {
@@ -1875,8 +1873,16 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
});
const route = await this.findApplicationRoute(message.tenantId, message.applicationId, carrier);
const excluded = new Set(options.excludeChannelIds ?? []);
const signatureId = await this.resolveMessageSignatureId(message);
if (!signatureId) throw new BadRequestException('短信签名未配置,无法选择已报备通道');
const approvedTasks = await this.prisma.channelSignatureReportTask.findMany({
where: { signatureId, status: 'approved', channelId: { in: route.group.items.map((item) => item.channelId) } },
select: { channelId: true },
});
const approvedChannelIds = new Set(approvedTasks.map((task) => task.channelId));
const items = route.group.items.filter((item) =>
!excluded.has(item.channelId)
&& approvedChannelIds.has(item.channelId)
&& normalizeCarrier(item.carrier) === carrier
&& isCarrierCompatible(item.channel.carrier, carrier),
);
@@ -1884,7 +1890,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
const nationalCandidates = items.filter((item) => isNationalChannel(item));
const selected = [...provinceCandidates, ...nationalCandidates].find((item) => this.isChannelSendAvailable(item.channel));
if (!selected) {
throw new NotFoundException('无可用在线通道');
throw new NotFoundException('无已报备通过且在线的可用通道');
}
return {
channel: selected.channel,
@@ -2111,8 +2117,8 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
if (!template || template.tenantId !== tenantId || template.applicationId !== applicationId || template.auditStatus !== 'approved') {
throw new BadRequestException('短信模板不存在、未通过审核或不属于当前应用');
}
if (!template.signature || template.signature.auditStatus !== 'approved' || template.signature.reportStatus !== 'approved') {
throw new BadRequestException('短信签名未审核通过或通道报备未通过');
if (!template.signature || template.signature.auditStatus !== 'approved') {
throw new BadRequestException('短信签名未审核通过');
}
}
@@ -2236,14 +2242,7 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
},
channelId: string,
) {
let signatureId = message.template?.signature?.id ?? message.signature?.id ?? null;
if (!signatureId && message.templateId) {
const template = await this.prisma.smsTemplate.findUnique({
where: { id: message.templateId },
include: { signature: true },
});
signatureId = template?.signature?.id ?? null;
}
const signatureId = await this.resolveMessageSignatureId(message);
if (!signatureId) {
throw new BadRequestException('短信签名未配置,不能提交到通道');
}
@@ -2256,6 +2255,13 @@ export class SendChainService implements OnModuleInit, OnModuleDestroy {
}
}
private async resolveMessageSignatureId(message: { templateId?: string | null; template?: { signature?: { id?: string | null } | null } | null; signature?: { id?: string | null } | null }) {
const direct = message.template?.signature?.id ?? message.signature?.id ?? null;
if (direct || !message.templateId) return direct;
const template = await this.prisma.smsTemplate.findUnique({ where: { id: message.templateId }, include: { signature: true } });
return template?.signature?.id ?? null;
}
private async waitForChannelRateLimit(channelId: string, tps: number) {
const redis = this.getRedis();
for (;;) {