C#发送短信最可靠方式是复用HttpClient调用第三方REST API,需校验参数、异步重试降级、记录日志并追踪回执。

直接调用第三方短信平台 API 是 C# 发送短信最可靠的方式,自己搭 SMPP 网关或调用本地串口设备在现代生产环境基本不可行,也不推荐。
用 HttpClient 调用 REST API 最稳妥
绝大多数短信服务商(如阿里云、腾讯云、容联云、亿美软通)只提供 HTTP 接口,HttpClient 是唯一合理选择。别用 WebClient(已过时)或 HttpWebRequest(冗余复杂)。
- 复用单例
HttpClient实例,避免 socket 耗尽 —— 不要在每次发短信都 new 一个 - 设置合理的
Timeout(通常 10–15 秒),超时后应记录日志并返回明确错误码,不能静默失败 - 请求头必须带
Content-Type: application/json(JSON 接口)或application/x-www-form-urlencoded(表单接口),否则服务商直接拒收 - 敏感参数如
AppKey、Secret、TemplateId必须从配置中心或IConfiguration读取,禁止硬编码
签名、模板、手机号格式必须严格校验
90% 的“发送失败”不是代码问题,而是参数不合规。服务商会在网关层拦截,连日志都不留。
- 手机号必须是纯数字,国内号码去“+86”、空格、横杠,且长度为 11 位 —— 建议用正则
^1[3-9]\d{9}$预检 - 短信签名(如“【某某科技】”)必须提前在平台审核通过,代码里传的值要和后台完全一致(含中括号、全角字符)
- 模板 ID 和模板内容变量必须匹配:若模板是“验证码是
{code}”,则提交的 JSON 中必须有"code": "123456"字段,字段名大小写敏感 - 部分平台要求签名 + 模板组合也需备案,单独通过不等于能一起用
异步发送 + 重试 + 降级是生产必备
短信属于弱一致性通知,不能阻塞主业务流程,也不能因单次失败就丢弃消息。
- 对外暴露的方法必须是
Task,内部用SendSmsAsync(...) await client.PostAsync(...) - 网络超时或 HTTP 5xx 错误可重试 1 次(间隔 1–2 秒),但 4xx 错误(如签名不合法、余额不足)绝不重试
- 若短信服务不可用,应降级为写入本地队列(如
ConcurrentQueue)或持久化到数据库,由后台任务补偿发送 - 务必记录完整上下文:手机号、模板 ID、请求参数、响应状态码、响应体(脱敏后),否则出问题根本无法排查
最容易被忽略的是回调验证和送达率追踪 —— 单纯收到 “success: true” 不代表用户收到了短信,真正关键的是服务商推送的回执(report)或上行短信(reply)。这部分需要单独监听 webhook 或轮询拉取,和发送逻辑解耦。










