直接用CodeIgniter-Twilio库最省事,但必须严格遵循CI3加载规则:类文件须置于application/libraries/Twilio.php,类名为Twilio(无命名空间、不继承CI_Library),构造函数中调用get_instance()获取CI实例,凭证从config/sms.php加载,号码须为E.164格式(如+8613812345678),接收回调需IP校验、验签及幂等去重。

直接用 CodeIgniter-Twilio 库是最省事的路径,但必须严格按 CI3 的加载规则来,否则 $this->load->library('twilio') 会报 Unable to load the requested class: twilio —— 这不是 Twilio 配置问题,而是 CI 自身类加载机制卡住了。
Twilio 类必须放在 application/libraries/Twilio.php 且类名首字母大写
CI3 不识别命名空间,也不走 Composer 自动加载。哪怕你用 composer require twilio/sdk 装了官方 SDK,$this->load->library('Twilio') 依然会失败,因为 CI 只认 application/libraries/ 下的裸类文件。
-
application/libraries/Twilio.php是唯一合法路径,文件名必须是Twilio.php(不是twilio.php或TwilioLibrary.php) - 类定义必须是
class Twilio,不能带namespace,也不能继承CI_Library - 内部要手动保存
$this->CI = &get_instance(),才能访问 config、log 等核心对象 - 如果沿用 Bened Edmunds 的
CodeIgniter-Twilio,注意它只适配 CI3,且依赖curl—— 确保 PHP 启用了curl扩展,否则message()会静默失败
Account SID 和 Auth Token 必须从 config/sms.php 加载,不能硬编码
凭证写死在类里等于把钥匙贴在门上。Twilio 控制台生成的 Account SID 和 Auth Token 必须抽离到配置文件,否则上线后密钥泄露风险极高。
- 新建
application/config/sms.php,内容为:$config['twilio_account_sid'] = 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';<br>$config['twilio_auth_token'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';<br>$config['twilio_from_number'] = '+1234567890';
- 在
Twilio.php的__construct()里调用$this->CI->config->load('sms'),再用$this->CI->config->item('twilio_account_sid')读取 - 别信“环境变量更安全”的说法 —— CI3 本身不支持
$_ENV自动注入,硬塞getenv()容易因 PHP-FPM 配置差异导致读不到
发送短信时 $number 必须带国际区号,+1 开头不能省略
Twilio 对号码格式极其敏感。$this->twilio->message('13812345678', 'hi') 看似合理,实则 100% 失败,错误不会抛出异常,而是返回空响应或 HTTP 400,日志里只显示 InvalidPhoneNumber。
- 所有号码必须用 E.164 格式:中国手机号是
+8613812345678,美国是+1234567890,+不可省略,中间不能有空格或横线 - 测试阶段务必用 Twilio 控制台里分配的
From号码(sandbox number),它只允许发给已验证的号码(verified numbers);正式号码需完成号码认证流程 - 调试时打开 Twilio 控制台的
Monitor → Logs,筛选 SMS,看实际请求中的To和From字段是否符合 E.164
接收短信回调必须单独控制器 + IP 白名单 + 幂等校验
Twilio 接收短信不是“监听端口”,而是靠你暴露一个公网可访问的 URL,Twilio 把 POST 请求推过来。这带来三个硬性约束:
- 必须用独立控制器(如
application/controllers/Sms_webhook.php),方法里第一行就做$this->input->is_post()和$this->input->ip_address()校验,只放行 Twilio 官方 IP 段(官方 IP 列表) - Twilio 请求带
X-Twilio-Signature头,必须用hash_hmac('sha256', $raw_input, $auth_token)验签,否则任何人都能伪造短信请求 - 同一个
MessageSid可能因网络重试被推送多次,得用 Redis 存twilio:seen:$message_sid做去重,TTL 设为 300 秒足够
最容易被忽略的是:Twilio 的 webhook 默认用 application/x-www-form-urlencoded 编码,不是 JSON —— 所以别用 $this->input->raw_input_stream 去解析,直接用 $this->input->post('From') 和 $this->input->post('Body') 就行。


















