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

PHP 發送微信模板訊息完整實作(基於 ThinkPHP)

     編輯:PHP 綜合知識

前言

微信模板訊息是服務號觸達用戶的重要管道(如訂單通知、付款成功、發貨提醒)。本文提供基於 ThinkPHP 框架的完整封裝類別,涵蓋 Access Token 管理、模板發送、錯誤處理。

核心類別:Org\Weixin\OrderPush

<?php
namespace Org\Weixin;

/**
 * 微信模板訊息發送類
 * 依賴:ThinkPHP S() 快取、cURL 擴充
 */
class OrderPush {
    protected $appid;
    protected $secret;
    protected $accessToken;

    public function __construct($appid, $secret) {
        $this->appid = $appid;
        $this->secret = $secret;
        $this->accessToken = $this->getToken($appid, $secret);
    }

    // ========== HTTP 請求封裝 ==========
    protected function requestPost($url, $data) {
        if (empty($url) || empty($data)) return false;
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => false,
            CURLOPT_SSL_VERIFYPEER => false, // 生產環境建議驗證憑證
            CURLOPT_TIMEOUT => 10,
        ]);
        
        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        
        if ($error) {
            // 記錄日誌:$error
            return false;
        }
        return $response;
    }

    protected function requestGet($url) {
        if (empty($url)) return false;
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_TIMEOUT => 10,
        ]);
        
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }

    // ========== Access Token 管理(含快取) ==========
    protected function getToken($appid, $secret) {
        // 1. 嘗試從快取讀取
        $cacheKey = "wx_access_token_{$appid}";
        if (S($cacheKey)) {
            return S($cacheKey);
        }

        // 2. 向微信請求新 Token
        $url = "https://api.weixin.qq.com/cgi-bin/token" . http_build_query([
            'grant_type' => 'client_credential',
            'appid' => $appid,
            'secret' => $secret,
        ]);

        $response = $this->requestGet($url);
        if (!$response) return false;

        $result = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE || !isset($result['access_token'])) {
            // 記錄錯誤:$result['errcode'], $result['errmsg']
            return false;
        }

        $token = $result['access_token'];
        // 3. 快取 7200 秒(微信 Token 有效期 2 小時,提前刷新)
        S($cacheKey, $token, 7200);
        return $token;
    }

    // ========== 發送模板訊息 ==========
    /**
     * 發送模板訊息
     * 
     * @param string $touser 接收者 OpenID
     * @param string $template_id 模板 ID(在公眾平台配置)
     * @param string $url 點擊訊息跳轉連結
     * @param array $data 模板資料(需符合模板定義的鍵名)
     * @param string $topcolor 頂部顏色(預設 #7B68EE)
     * @return bool 發送是否成功
     */
    public function doSend($touser, $template_id, $url, $data, $topcolor = '#7B68EE') {
        if (!$this->accessToken) {
            // 記錄:Token 獲取失敗
            return false;
        }

        // 1. 組裝訊息結構
        $template = [
            'touser' => $touser,
            'template_id' => $template_id,
            'url' => $url,
            'topcolor' => $topcolor,
            'data' => $data,
        ];

        // 2. JSON 編碼(注意:微信要求 UTF-8,不轉義 Unicode)
        $json = json_encode($template, JSON_UNESCAPED_UNICODE);

        // 3. 發送請求
        $apiUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$this->accessToken}";
        $response = $this->requestPost($apiUrl, $json);

        if (!$response) return false;

        $result = json_decode($response, true);
        
        // 4. 判斷結果(errcode 0 為成功)
        if (isset($result['errcode']) && $result['errcode'] == 0) {
            return true;
        } else {
            // 記錄失敗:$result['errcode'], $result['errmsg']
            // 常見錯誤:40037 模板ID錯誤、43004 需要用戶關注、45009 發送頻率超限
            return false;
        }
    }
}
?>

模板資料結構範例

<?php
// 假設模板內容為:
// {{first.DATA}}
// 商品:{{name.DATA}}
// 金額:{{amount.DATA}}
// 時間:{{time.DATA}}
// {{remark.DATA}}

$data = [
    'first' => [
        'value' => "您好,您的訂單已付款成功!",
        'color' => "#173177"
    ],
    'name' => [
        'value' => "iPhone 15 Pro Max 256GB 深空灰",
        'color' => "#173177"
    ],
    'amount' => [
        'value' => "¥ 9,999.00",
        'color' => "#E74C3C"  // 金額用紅色突出
    ],
    'time' => [
        'value' => date('Y-m-d H:i:s'),
        'color' => "#173177"
    ],
    'remark' => [
        'value' => "預計 1-3 個工作日發貨,請留意查收。",
        'color' => "#173177"
    ],
];
?>

控制器調用範例

<?php
namespace Home\Controller;
use Think\Controller;
use Org\Weixin\OrderPush;

class OrderController extends Controller {
    public function notifyUser() {
        $appid = C('WEIXIN_APPID');
        $secret = C('WEIXIN_SECRET');
        
        $pusher = new OrderPush($appid, $secret);
        
        $openid = 'oUpF8uMuAJ...'; // 用戶 OpenID
        $templateId = 'TM_00123...'; // 模板 ID
        $detailUrl = 'https://shop.example.com/order/12345';
        
        $data = [ /* 如上方模板資料結構 */ ];
        
        $success = $pusher->doSend($openid, $templateId, $detailUrl, $data);
        
        if ($success) {
            $this->ajaxReturn(['status' => 1, 'msg' => '模板訊息發送成功']);
        } else {
            $this->ajaxReturn(['status' => 0, 'msg' => '發送失敗,請檢查日誌']);
        }
    }
}
?>

關鍵注意事項與最佳實踐

項目說明
Access Token 快取全域唯一、2小時有效、每日調用上限 2000 次,必須快取,避免重複請求導致封禁
Token 刷新策略建議提前 5-10 分鐘刷新(快取設定 7100-7150 秒),避免邊界失效
模板審核模板需在微信公眾平台「模板庫」選用並提交審核,通過後獲得 template_id
用戶授權僅能發送給已關注公眾號的用戶(OpenID 來源:網頁授權、掃碼關注、客服訊息)
發送頻率同一用戶同一模板 1 分鐘 1 次、1 小時 5 次、1 天 20 次(視帳號等級調整)
資料編碼使用 JSON_UNESCAPED_UNICODE 避免中文被轉義為 \uXXXX,減少封包大小
錯誤碼處理建立錯誤碼對照表,針對 43004(未關注)、45009(頻率限制) 等做重試或降級

生產環境增強建議

  1. 非同步發送: 將發送任務寫入 Redis/RabbitMQ 佇列,Worker 後台處理,Web 請求秒級回應
  2. 發送記錄持久化: 記錄 OpenID、模板ID、參數、結果、錯誤碼、時間,便於追蹤與重發
  3. 多帳號支援: 服務號、訂閱號、小程序、企業微信不同憑證,工廠模式管理多實例
  4. 熔斷機制: 連續失敗超過閾值暫停發送,避免無效請求消耗配額
  5. 監控告警: 成功率、延遲、配額使用率儀表板,異常即時通知

微信模板訊息雖 API 簡單,但生產環境涉及 Token 管理、頻率控制、錯誤重試、記錄追蹤等工程化課題,建議封裝為獨立服務模組統一管理。

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