Twilio语音和短信是两个独立API,语音调用需用/Calls.json端点、CreateCall方法、Twiml参数及主账户凭证,且须验证号码、URL编码Twiml、限制QPS为1并区分错误类型重试。

Twilio语音和短信是两个独立API,别混用SendSMS发语音
Twilio没有“语音短信”这种混合接口——语音(MakeCall)和短信(SendSMS)走完全不同的REST端点、鉴权逻辑和响应结构。直接拿发短信的代码去“发语音”,会收到404 Not Found或400 Invalid Resource,因为路径根本不对。
- 短信用:
POST /2010-04-01/Accounts/{Sid}/Messages.json - 语音用:
POST /2010-04-01/Accounts/{Sid}/Calls.json - SDK里对应方法也不同:
twilio.CreateMessagevstwilio.CreateCall - 语音必须提供
Twiml(XML格式的指令),比如<Say>您的验证码是1234</Say>,不能只传纯文本
用gotwilio发语音前,先确认你装的是v3+版本
老版本github.com/sfreiberg/gotwilio(v2.x)根本不支持CreateCall,调用会panic或静默失败。v3.0起才补全语音能力,但没文档强调这点,很多人卡在undefined: twilio.CreateCall。
- 检查go.mod:
github.com/sfreiberg/gotwilio v3.0.0+incompatible(注意末尾+incompatible是正常的) - 初始化客户端时,Account SID和Auth Token必须来自主账户(不是子账户),否则
CreateCall返回20001 Authentication Failed - 语音号码必须已验证(Sandbox环境仅支持已验证号码;生产环境需完成
Verified Caller ID流程)
CreateCall必填参数比短信多,漏掉Twiml或From直接报错
短信只需From、To、Body三个字段;语音至少要四个:除了From、To,还必须显式传Twiml(XML字符串),且From必须是Twilio分配的号码或已验证号码——用个人手机号当From会触发21212 Invalid 'From' number。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
Twiml内容需URL编码,例如%3CSay%3Ehello%3C%2FSay%3E,不能直接传原始XML - 别把
Twiml写成JSON字段,Twilio后端只认twiml这个key(小写) - 如果想播录音,用
<Play>https://example.com/msg.mp3</Play>,但URL必须HTTPS且可公开访问
并发打语音电话必须加限流,Twilio默认QPS=1
Twilio对/Calls接口的默认速率限制极严:每秒最多1次请求(非每秒1通电话)。不加控制地起100个goroutine调CreateCall,99%会返回20005 Request was throttled,且后续请求可能被临时封禁。
立即学习“go语言免费学习笔记(深入)”;
- 用
semaphore包或带缓冲channel控并发,例如make(chan struct{}, 1)(严格1 QPS) - 别依赖
time.Sleep做节流——网络延迟会导致实际QPS超标 - 生产环境建议升配到
High Volume Calling套餐,并在控制台开启Concurrent Calls配额
Twilio语音的真正难点不在调通,而在错误分类和重试策略:网络超时可以重试,但32203 Invalid To number这类业务错误重试毫无意义。得把net.Error、HTTP状态码、Twilio错误码三层分开处理,不然日志里全是无效重试。

















