fix(send): use stored WECOM_BOT webhook URL and preserve single-chat routing without scene

- Copy account.ext_info into extra.webhook_url for WECOM_BOT sends.
- Allow null conversation_scene for single chats; only enforce scene-based routing for group chats.
- Harden WeComBotSender custom URL handling when placeholder is missing.
This commit is contained in:
2026-07-14 18:45:48 +08:00
parent 11ee7384b3
commit c24891a82e
2 changed files with 23 additions and 4 deletions

View File

@@ -85,7 +85,11 @@ public class WeComBotSender {
private String resolveWebhookUrl(Map<String, Object> extra, String key) {
String customUrl = getString(extra, "webhook_url");
if (customUrl != null && !customUrl.isBlank()) {
return String.format(customUrl, key);
if (customUrl.contains("%s")) {
return customUrl.replace("%s", key);
}
log.warn("[WeComBot] custom webhook_url missing %s placeholder; appending key param");
return customUrl.contains("?") ? customUrl + "&key=" + key : customUrl + "?key=" + key;
}
return String.format(DEFAULT_WEBHOOK_URL, key);
}

View File

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sino.mci.channel.adapter.registry.ChannelAdapterRegistry;
import com.sino.mci.channel.common.dto.SendMessageRequest;
import com.sino.mci.channel.common.dto.SendMessageResult;
import com.sino.mci.channel.common.model.AccountType;
import com.sino.mci.channel.common.model.ChannelType;
import com.sino.mci.channel.common.spi.ChannelAdapter;
import com.sino.mci.channel.entity.ChannelAccount;
@@ -79,6 +80,8 @@ public class SendService {
private static final int SEND_STATUS_SUCCESS = 2;
private static final int SEND_STATUS_FAILED = 3;
private static final int CONVERSATION_TYPE_SINGLE = 1;
private static final int CONVERSATION_TYPE_GROUP = 2;
private static final int CONVERSATION_SCENE_INTERNAL = 1;
private static final int CONVERSATION_SCENE_EXTERNAL = 2;
private static final Set<Integer> ACCOUNT_TYPES_BOT = Set.of(6);
@@ -350,14 +353,22 @@ public class SendService {
throw new BusinessException("会话不存在: " + conversationId);
}
ChannelType channelType = resolveChannelTypeForScene(conversation.getConversationScene());
Set<Integer> accountTypes = resolveAccountTypesForScene(conversation.getConversationScene());
ChannelType channelType;
Set<Integer> accountTypes;
// 单聊未回填场景时保持旧行为,按 channelStrategy 默认 WECOM 路由;群聊必须按场景路由
if (conversation.getConversationType() != null && conversation.getConversationType() == CONVERSATION_TYPE_SINGLE) {
channelType = parseChannelType(extractChannelType(channelStrategy));
accountTypes = null;
} else {
channelType = resolveChannelTypeForScene(conversation.getConversationScene());
accountTypes = resolveAccountTypesForScene(conversation.getConversationScene());
}
Long accountId = selectSendAccount(tenantCode, conversationId, channelType, accountTypes, channelStrategy);
if (accountId == null) {
accountId = conversation.getOwnerAccountId();
ChannelAccount ownerAccount = accountMapper.selectById(accountId);
if (ownerAccount == null || !accountTypes.contains(ownerAccount.getAccountType())) {
if (ownerAccount == null || (accountTypes != null && !accountTypes.contains(ownerAccount.getAccountType()))) {
accountId = null;
}
}
@@ -970,6 +981,10 @@ public class SendService {
if (StringUtils.hasText(account.getAccountId())) {
extra.put("account_id", account.getAccountId());
}
if (account.getAccountType() != null && account.getAccountType() == AccountType.WECOM_BOT.getCode()
&& StringUtils.hasText(account.getExtInfo())) {
extra.put("webhook_url", account.getExtInfo());
}
}
extra.put("record_id", record.getId());
extra.put("tenant_code", record.getTenantCode());