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

PHP 實作短信發送:XML 協議 + cURL 完整封裝類

     編輯:PHP 綜合知識

業務場景

對接第三方短信閘道(如卓望),協議為 HTTP POST + XML 報文,需簽名驗證。本類封裝 XML 組裝、簽名計算、cURL 發送、響應解析。

完整類別碼

class SmsSender {
    private $userId;
    private $password;      // 已為 MD5 小寫
    private $templateId;
    private $serverUri;
    private $port;

    public function __construct(array $config) {
        $this->userId     = $config['userId'];
        $this->password   = $config['password'];
        $this->templateId = $config['templateId'];
        $this->serverUri  = $config['serverUri'];
        $this->port       = $config['port'];
    }

    /**
     * 發送單條短信
     * @param string $message  內容(模板變數已替換)
     * @param string $mobile   手機號
     * @param string $signature 簽名
     * @return bool|string  true=成功, false=網路失敗, 其他=錯誤碼
     */
    public function sendOne(string $message, string $mobile, string $signature = 'demo') {
        $xml = $this->buildXml($message, $mobile, $signature);
        $resp = $this->postXml($xml);
        if ($resp === false) return false; // 網路錯誤

        $xmlObj = simplexml_load_string($resp);
        if (!$xmlObj) return 'PARSE_ERROR';
        return ($xmlObj->retCode == 1000) ? true : (string)$xmlObj->retCode;
    }

    /** 組裝 XML 報文 */
    private function buildXml(string $msg, string $mobile, string $sig): string {
        $data = [
            'userId'     => $this->userId,
            'password'   => $this->password,
            'templateId' => $this->templateId,
            'phone'      => $mobile,
            'port'       => $this->port,
            'data'       => $msg,
            'signature'  => $sig,
        ];
        $dom = new DOMDocument('1.0', 'UTF-8');
        $req = $dom->createElement('request');
        $dom->appendChild($req);
        foreach ($data as $k => $v) {
            $el = $dom->createElement($k);
            $req->appendChild($el);
            $el->appendChild($dom->createTextNode($v));
        }
        return $dom->saveXML();
    }

    /** 發送 HTTP POST XML */
    private function postXml(string $xml): ?string {
        $now = time();
        $headers = [
            'Content-Type: text/xml',
            'Content-Length: ' . strlen($xml),
            'Cmd: mt',
            'TS: ' . $now,
            'Authorization: ' . strtoupper(md5($xml . $now . $this->password)),
        ];
        $ch = curl_init($this->serverUri);
        curl_setopt_array($ch, [
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POST       => true,
            CURLOPT_POSTFIELDS => $xml,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER     => false,
            CURLOPT_TIMEOUT    => 10,
        ]);
        $resp = curl_exec($ch);
        $err  = curl_error($ch);
        curl_close($ch);
        if ($err) error_log("SMS cURL error: $err");
        return $resp ?: null;
    }
}

使用範例

$sender = new SmsSender([
    'userId'     => 'YOUR_UID',
    'password'   => 'MD5_PASSWORD_LOWERCASE',
    'templateId' => 'TPL_12345',
    'serverUri'  => 'https://sms.api.provider/gateway',
    'port'       => '8888',
]);

$result = $sender->sendOne('您的驗證碼是 123456', '13800138000', 'MyApp');
if ($result === true) {
    echo "發送成功";
} elseif ($result === false) {
    echo "網路異常,請重試";
} else {
    echo "閘道返回錯誤碼:$result";
}

關鍵安全細節

  1. 密碼存儲:配置檔存 MD5 小寫,勿存明文。
  2. 簽名算法:MD5(XML_BODY + TIMESTAMP + PASSWORD) 大寫,確保報文未被竄改。
  3. HTTPS:生產環境強制使用 HTTPS 端點,防止中間人竄改。
  4. 錯誤碼映射:建立對照表(如 1001=餘額不足、1002=模板不存在),轉為人類可讀訊息。
  5. 重試策略:網路失敗指數退避重試 3 次,記錄失敗隊列供人工補發。

結語

XML 協議雖顯老舊,但金融、電信領域仍廣泛使用。封裝可復用類別,統一異常處理與日誌,能大幅降低對接維護成本。

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