短信域是单体包结构——6 家短信供应商(阿里云、腾讯云、华为云、Twilio、Vonage、云片)全部在 Bitzsoft.Integrations.Sms 一个 NuGet 包内,而非每家供应商一个包。这是因为短信接口极简(一个 SendAsync 方法),拆分收益不大。
ISMS 接口
public interface ISMS{ string ProviderName { get; }
Task<SMSResult> SendAsync(SmsMessage message, CancellationToken cancellationToken = default);}SmsMessage
| 字段 | 说明 |
|---|---|
PhoneNumbers | 手机号列表 |
SignName | 短信签名 |
TemplateCode | 模板编号 |
TemplateParams | 模板参数(键值对) |
SMSResult
| 字段 | 说明 |
|---|---|
Success | 是否成功 |
RequestId | 请求 ID(追踪用) |
BizId | 短信发送流水号 |
ErrorCode | 错误码 |
ErrorMessage | 错误消息 |
6 家供应商配置一览
| 供应商 | DI 注册方法 | 配置类 | 鉴权字段 |
|---|---|---|---|
| 阿里云 | AddAliyunSms | AliyunSmsOptions | AccessKeyId + AccessKeySecret + RegionId |
| 腾讯云 | AddTencentSms | TencentSmsOptions | SecretId + SecretKey + AppId + Region |
| 华为云 | AddHuaweiSms | HuaweiSmsOptions | AppKey + AppSecret + Endpoint + Sender |
| Twilio | AddTwilioSms | TwilioSmsOptions | AccountSid + AuthToken + From |
| Vonage | AddVonageSms | VonageSmsOptions | ApiKey + ApiSecret + From |
| 云片 | AddYunpianSms | YunpianSmsOptions | ApiKey + Domain |
配置与注册示例(阿里云)
{ "Sms": { "Aliyun": { "AccessKeyId": "LTAIxxxxxxxx", "AccessKeySecret": "your-secret-key", "RegionId": "cn-hangzhou" } }}builder.Services.AddAliyunSms(options =>{ options.AccessKeyId = "LTAIxxxxxxxx"; options.AccessKeySecret = "your-secret-key"; options.RegionId = "cn-hangzhou";});使用示例
public class SmsService(ISMS sms){ public async Task<SMSResult> SendVerificationCodeAsync(string phone, string code) { return await sms.SendAsync(new SmsMessage { PhoneNumbers = new() { phone }, SignName = "Bitzsoft", TemplateCode = "SMS_123456789", TemplateParams = new() { ["code"] = code }, }); }}为什么是单体包
短信接口只有一个 SendAsync,各家供应商实现差异仅在签名方式和 API 端点。拆成 6 个包的收益不足以覆盖包管理成本。与 TeamWork(15 个能力接口、能力差异巨大)的多包结构形成对比。
已知限制
- 国内供应商(阿里云/腾讯云/华为云/云片)需要预先审批签名和模板。
- 国际供应商(Twilio/Vonage)支持任意文本内容,但需购买号码。
- 华为云的
Endpoint含端口(如smsapi.cn-north-4.myhuaweicloud.com:443)。