首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii 框架整合 smsto 短信接口實戰:發送函數封裝、編碼處理與錯誤重試最佳實踐

     編輯:PHP 相關知識

Yii 框架整合 smsto 短信接口實戰:發送函數封裝、編碼處理與錯誤重試最佳實踐

短信驗證碼、通知類消息是 Web 應用標配。本文展示在 Yii 1.x 中封裝 smsto (假設為某短信服務商) 接口的完整流程,含參數構建、GB2312 編碼轉換、URL 編碼、HTTP 請求發送與響應處理。

控制器/組件中封裝發送方法

<?php
class SmsComponent extends CApplicationComponent {
    // 接口配置 (建議放入 params.php)
    private $uid     = 'zyd';
    private $password = '123456';
    private $gateway  = 'https://sms.zyd.com/msgsend.ashx';

    /**
     * 發送短信
     * @param string $mobile 手機號
     * @param string $message 短信內容
     * @return string|false 接口原始響應 / 失敗 false
     */
    public function send($mobile, $message) {
        // 1. 參數校驗
        if (!preg_match('/^1\d{10}$/', $mobile)) {
            Yii::log("無效手機號: $mobile", CLogger::LEVEL_WARNING);
            return false;
        }
        if (empty($message)) return false;

        // 2. 編碼轉換:內部 UTF-8 → 接口要求 GB2312 → URL 編碼
        $encodedMessage = urlencode(mb_convert_encoding($message, 'GB2312', 'UTF-8'));

        // 3. 構建請求 URL (GET 方式)
        $params = [
            'USERNAME' => $this->uid,
            'PASSWORD' => $this->password,
            'MOBILE'   => $mobile,
            'CONTENT'  => $encodedMessage,
            'SEQ'      => 1000, // 流水號,可用於狀態報告匹配
        ];
        $url = $this->gateway . '?' . http_build_query($params);

        // 4. 發送請求 (設置超時防止阻塞)
        $ctx = stream_context_create([
            'http' => [
                'timeout' => 10, // 10 秒超時
                'ignore_errors' => true, // 獲取非 2xx 響應體
            ]
        ]);
        $response = @file_get_contents($url, false, $ctx);

        // 5. 響應處理
        if ($response === false) {
            Yii::log("短信發送失敗 (網絡/超時): $mobile", CLogger::LEVEL_ERROR);
            return false;
        }

        // 6. 記錄日誌供審計
        Yii::log("短信發送: mobile=$mobile, response=$response", CLogger::LEVEL_INFO);
        return $response;
    }
}

配置文件注入 (main.php)

return array(
    'components' => array(
        'sms' => array(
            'class' => 'application.components.SmsComponent',
            // 可在這裡覆蓋 uid/password/gateway
        ),
    ),
);

業務代碼中調用

// 控制器中
public function actionSendVerifyCode() {
    $mobile = $_POST['mobile'];
    $code   = sprintf('%06d', mt_rand(0, 999999));
    $msg    = "您的驗證碼是 $code,10 分鐘內有效,請勿泄露。";

    if (Yii::app()->sms->send($mobile, $msg)) {
        // 存入緩存/Session,設置 10 分鐘過期
        Yii::app()->cache->set("sms_code_$mobile", $code, 600);
        echo CJSON::encode(['success' => true]);
    } else {
        echo CJSON::encode(['success' => false, 'error' => '發送失敗,請稍後重試']);
    }
}

關鍵技術細節深度解析

1. 編碼轉換鏈路:UTF-8 → GB2312 → URL Encode

$message = "中文內容";
// 步驟 1: 內部 UTF-8 → 接口要求 GB2312
$gb2312 = mb_convert_encoding($message, 'GB2312', 'UTF-8');
// 步驟 2: URL 編碼 (空格→+ 或 %20,中文→%XX%XX)
$final  = urlencode($gb2312);
// 發送後接口端:urldecode → GB2312 解碼 → 入庫/下發

注意:若接口文檔要求 UTF-8,則跳過 mb_convert_encoding 直接 urlencode。

2. 超時控制與非阻塞

  • stream_context_create(['http'=>['timeout'=>10]]) 防止接口掛起導致 PHP-FPM 進程佔用。
  • 高并發場景建議:寫入消息隊列 (Redis/RabbitMQ),Worker 進程異步消費發送。

3. 幂等性與防刷

// 同一手機號 60 秒內只允許發送一次
$key = "sms_limit_$mobile";
if (Yii::app()->cache->get($key)) {
    throw new CHttpException(429, '請求過於頻繁');
}
Yii::app()->cache->set($key, 1, 60);

4. 狀態報告回調處理

預留路由 /sms/callback 接收服務商 POST 狀態報告:

public function actionCallback() {
    $seq   = $_POST['SEQ'];
    $status = $_POST['STATUS']; // 0 成功, 非 0 失敗
    $mobile = $_POST['MOBILE'];
    // 更新發送記錄表、觸發業務邏輯
    Yii::log("短信狀態報告: seq=$seq, mobile=$mobile, status=$status");
    echo 'OK'; // 告知服務商已接收
}

擴展:支持多通道輪詢/備用

class MultiChannelSms extends CApplicationComponent {
    private $channels = [
        ['class' => 'SmsComponent', 'weight' => 70], // 主通道 70%
        ['class' => 'BackupSmsComponent', 'weight' => 30], // 備用 30%
    ];

    public function send($mobile, $message) {
        // 加權隨機選擇通道
        $channel = $this->selectChannel();
        return $channel->send($mobile, $message);
    }
}

總結

Yii 整合短信接口核心在於:組件化封裝、編碼鏈路正確、超時保護、日誌審計、防刷限流、狀態報告回調。將發送邏輯下沉至 Component,業務層僅需一行 Yii::app()->sms->send() 即可調用,實現高內聚、低耦合、易測試、易擴展。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved