InstantMessaging 域统一了企业即时通讯平台的消息发送与频道管理能力。Slack 和 WhatsApp 两家供应商共享同一个 IInstantMessagingService 接口,两者都使用 Bearer Token 鉴权,但 API 体系与成功判断方式各有差异。
域结构
Bitzsoft.Integrations.InstantMessaging ← 抽象层├── Bitzsoft.Integrations.InstantMessaging.Slack ← Slack(Bearer Bot Token)├── Bitzsoft.Integrations.InstantMessaging.WhatsApp ← WhatsApp(Bearer Token,Cloud API)└── Bitzsoft.Integrations.InstantMessaging.All ← 聚合包标准三层包模式。
统一接口(8 方法)
IInstantMessagingService 围绕”消息(Message)“和”频道(Channel)“两个核心概念组织,共 8 个成员:
public interface IInstantMessagingService{ string ProviderName { get; }
// 消息(4) Task<MessageInfo> SendTextAsync(SendTextRequest request, CancellationToken cancellationToken = default); Task<MessageInfo> SendCardAsync(SendCardRequest request, CancellationToken cancellationToken = default); Task DeleteMessageAsync(string messageId, CancellationToken cancellationToken = default); Task<MessageInfo> UpdateMessageAsync(string messageId, UpdateMessageRequest request, CancellationToken cancellationToken = default);
// 频道(4) Task<List<ChannelInfo>> ListChannelsAsync(CancellationToken cancellationToken = default); Task<ChannelInfo> CreateChannelAsync(CreateChannelRequest request, CancellationToken cancellationToken = default); Task InviteMemberAsync(string channelId, string memberId, CancellationToken cancellationToken = default); Task<InviteResult> InviteMembersAsync(string channelId, IReadOnlyList<string> memberIds, CancellationToken cancellationToken = default);}消息发送/更新返回 MessageInfo(含 MessageId / ChannelId / Timestamp),操作类方法(Delete / Invite)为无返回 Task 或返回结果对象,失败抛 InstantMessagingException。
鉴权模型
两家供应商都用 Bearer Token,但来源与 API 体系不同:
| 供应商 | 鉴权机制 | Token 注入 | 成功判断 | API 体系 |
|---|---|---|---|---|
| Slack | Bot User OAuth Token(xoxb-) | Authorization: Bearer {botToken} 头 | response.ok == true | Web API(chat.postMessage / conversations.*) |
| Permanent Access Token | Authorization: Bearer {token} 头 | HTTP 2xx + 业务码 | WhatsApp Business Cloud API(Graph) |
Slack 的消息与频道 API
Slack 发文本走 chat.postMessage、改消息走 chat.update、删消息走 chat.delete;频道相关走 conversations.list / conversations.create / conversations.invite。Bot Token 需具备对应 OAuth scope(如 chat:write、channels:manage)。
供应商清单
| 供应商 | Provider ID | API 基地址 | Stability | DI 方法 |
|---|---|---|---|---|
| Slack | slack | slack.com/api | Preview | AddSlackInstantMessaging() |
whatsapp | graph.facebook.com/v{version}/{phone-number-id}/messages | Preview | AddWhatsAppInstantMessaging() |
Slack 面向企业团队协作,WhatsApp 面向客户触达与营销消息。
注册
单厂商
// ① Slack(Bearer Bot Token)builder.Services.AddSlackInstantMessaging(builder.Configuration.GetSection("InstantMessaging:Slack"));
// ② WhatsApp(Bearer Token,Business Cloud API)builder.Services.AddWhatsAppInstantMessaging(builder.Configuration.GetSection("InstantMessaging:WhatsApp"));全量聚合
builder.Services.AddBitzsoftInstantMessagingAll(builder.Configuration, "InstantMessaging");按配置节存在性自动注册,appsettings.json 只需写出启用的供应商:
{ "InstantMessaging": { "Slack": { "BotToken": "xoxb-...", "DefaultChannel": "#general" }, "WhatsApp": { "AccessToken": "EAAG...", "PhoneNumberId": "123456789", "ApiVersion": "v18.0" } }}消费
发送文本与卡片消息
public class NotifyService(IIntegrationProviderResolver<IInstantMessagingService> providers){ public async Task<MessageInfo> NotifyAsync(string vendor, string channel, string text) { var im = providers.GetRequired(vendor); // "slack" / "whatsapp" return await im.SendTextAsync(new SendTextRequest { ChannelId = channel, Text = text, }); }}卡片消息(Slack 的 Block Kit、WhatsApp 的 template/button 消息)通过 SendCardAsync 传入结构化卡片定义,由各厂商实现翻译为各自的卡片格式。
消息增删改
// 更新已发送消息await im.UpdateMessageAsync(messageId, new UpdateMessageRequest{ ChannelId = channel, Text = "(已修订)" + newText,});
// 撤回消息await im.DeleteMessageAsync(messageId);频道与成员管理
// 创建新频道var channel = await im.CreateChannelAsync(new CreateChannelRequest{ Name = "project-phoenix", IsPrivate = false,});
// 批量邀请成员var inviteResult = await im.InviteMembersAsync(channel.Id, ["U001", "U002", "U003"]);// inviteResult.InvitedCount / inviteResult.FailedMemberIds多厂商路由
public class ImRouter(IIntegrationProviderResolver<IInstantMessagingService> providers){ public async Task<List<ChannelInfo>> ListChannelsAsync(string platform) { var im = providers.GetRequired(platform); // "slack" / "whatsapp" return await im.ListChannelsAsync(); }}