Laravel中使用Twilio发送OTP时如何设置消息未送达异常处理
完善Laravel + Twilio OTP发送的异常处理
看起来你已经搞定了基础的OTP发送功能,接下来咱们把异常处理这块补全,覆盖从Twilio API错误到系统通用异常的各种场景,让你的代码更健壮:
1. 先引入必要的异常类
Twilio的PHP SDK自带专属异常,先把它引入进来,方便针对性捕获:
use Twilio\Exceptions\TwilioException; use Twilio\Rest\Client; use Illuminate\Support\Facades\Log;
2. 扩展try-catch逻辑,覆盖所有失败场景
我给你完善了send_otp方法的异常处理,包含日志记录、用户友好提示、不同错误场景的区分:
public function send_otp() { // 先校验用户是否登录,避免空指针 abort_unless(Auth::check(), 401, 'Please login first'); try { $account_sid = env('TWILIO_ACCOUNT_SID'); $auth_token = env('TWILIO_AUTH_TOKEN'); $user = Auth::user(); $number = $user->user_phone; // 简单校验手机号格式,提前拦截无效号码 if (!preg_match('/^\+?[1-9]\d{1,14}$/', $number)) { return response()->json(['status' => 'error', 'message' => 'Invalid phone number format'], 400); } $client = new Client($account_sid, $auth_token); $message = $client->messages->create( $number, [ 'From' => '+12533368077', 'Body' => "Your verification code is: {$user->user_otp}", // 给OTP加个友好前缀 ] ); // 发送成功后记录日志,方便后续排查 Log::info("OTP sent successfully to {$number}", [ 'user_id' => $user->id, 'twilio_message_sid' => $message->sid ]); return response()->json(['status' => 'success', 'message' => 'OTP sent to your phone']); } catch (TwilioException $e) { // 处理Twilio专属异常:无效号码、余额不足、认证失败等 Log::error("Twilio API error when sending OTP", [ 'user_id' => $user->id ?? 'unknown', 'phone_number' => $number, 'error_code' => $e->getCode(), 'error_message' => $e->getMessage() ]); // 根据Twilio官方错误码返回更精准的提示 $userMessage = match ($e->getCode()) { 21604 => 'The phone number you provided is invalid or cannot receive SMS.', 21211 => 'The sender phone number is not a valid Twilio number.', 21407 => 'Twilio account has insufficient balance to send messages.', default => 'Failed to send OTP. Please try again in a few minutes.' }; return response()->json(['status' => 'error', 'message' => $userMessage], 500); } catch (\Exception $e) { // 处理系统通用异常:比如环境变量未配置、数据库错误等 Log::error("Unexpected error when sending OTP", [ 'error_message' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return response()->json(['status' => 'error', 'message' => 'An unexpected error occurred.'], 500); } }
3. 几个关键优化点
- 提前校验:先检查用户登录状态和手机号格式,减少不必要的API调用
- 日志分级:用
info记录成功事件,error记录错误,方便后期排查问题 - 用户友好:根据Twilio错误码返回不同提示,避免给用户展示技术术语
- 响应规范:统一返回JSON格式,前端可以直接解析处理
4. 额外进阶建议
如果想更精准处理消息未送达的情况,可以在Twilio控制台设置状态回调Webhook,当消息状态变为failed或undelivered时,Twilio会主动通知你的后端,你可以做重试逻辑或者给用户发推送提醒。
内容的提问来源于stack exchange,提问作者Pranav Mandlik
相关产品推荐
相关产品推荐

