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

PHP 實作微信公眾號無限群發:客服介面突破群發限制、OpenID 批次獲取與訊息推送完整流程

     編輯:PHP 綜合知識

前言

微信公眾號**群發介面**有嚴格限制:服務號月 4 次、認證訂閱號月 1 次、需審核。但**客服介面**允許 48 小時內無限制主動推送訊息給任意關注用戶。本文實作「無限群發」:批次獲取 OpenID → 逐個調用客服介面發送文本/圖文/圖片等訊息。

核心類別代碼

appId = $appId;
        $this->appSecret = $appSecret;
        $this->tokenCacheFile = $cacheDir . '/access_token.json';
        if (!is_dir($cacheDir)) mkdir($cacheDir, 0755, true);
        $this->accessToken = $this->getAccessToken();
    }
    
    // ===== HTTP 工具 =====
    public function getData(string $url): string {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Wechat Bot)',
            CURLOPT_ENCODING => 'gzip',
            CURLOPT_TIMEOUT => 15,
        ]);
        $data = curl_exec($ch);
        if (curl_errno($ch)) throw new RuntimeException("cURL GET error: " . curl_error($ch));
        curl_close($ch);
        return $data;
    }
    
    public function postData(string $url, string $data): string {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP Wechat Bot)',
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_AUTOREFERER => true,
            CURLOPT_TIMEOUT => 15,
        ]);
        $result = curl_exec($ch);
        if (curl_errno($ch)) throw new RuntimeException("cURL POST error: " . curl_error($ch));
        curl_close($ch);
        return $result;
    }
    
    // ===== Access Token(快取 7000 秒)=====
    public function getAccessToken(): string {
        if (is_file($this->tokenCacheFile)) {
            $cache = json_decode(file_get_contents($this->tokenCacheFile), true);
            if ($cache && time() < $cache['expire']) return $cache['access_token'];
        }
        
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
        $res = $this->getData($url);
        $data = json_decode($res, true);
        
        if (empty($data['access_token'])) {
            throw new RuntimeException("Get access_token failed: {$res}");
        }
        
        $data['expire'] = time() + 7000;
        file_put_contents($this->tokenCacheFile, json_encode($data));
        return $data['access_token'];
    }
    
    // ===== 獲取所有關注者 OpenID(支援分頁)=====
    private function getAllOpenIds(): array {
        $openids = [];
        $nextOpenid = '';
        
        do {
            $url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$this->accessToken}" .
                   ($nextOpenid ? "&next_openid={$nextOpenid}" : '');
            $res = $this->getData($url);
            $data = json_decode($res, true);
            
            if (isset($data['errcode'])) {
                throw new RuntimeException("Get user list failed: {$res}");
            }
            
            $openids = array_merge($openids, $data['data']['openid'] ?? []);
            $nextOpenid = $data['next_openid'] ?? '';
        } while ($nextOpenid);
        
        return $openids;
    }
    
    // ===== 發送客服訊息 =====
    private function sendCustomMessage(string $openid, array $msgData): bool {
        $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$this->accessToken}";
        $payload = array_merge(['touser' => $openid], $msgData);
        $json = json_encode($payload, JSON_UNESCAPED_UNICODE);
        $res = $this->postData($url, $json);
        $data = json_decode($res, true);
        return empty($data['errcode']);
    }
    
    // ===== 公開介面:無限群發 =====
    public function sendMsgToAll(): void {
        $openids = $this->getAllOpenIds();
        echo "總共 {$openids} 位關注用戶\n";
        
        $success = $failed = 0;
        foreach ($openids as $openid) {
            // 示範:發送文本訊息
            $msg = [
                'msgtype' => 'text',
                'text' => ['content' => '測試群發訊息,抱歉打擾']
            ];
            
            // 可擴展:圖文、圖片、語音、視頻、卡券等
            // $msg = ['msgtype' => 'news', 'news' => ['articles' => [...]]];
            
            if ($this->sendCustomMessage($openid, $msg)) {
                $success++;
            } else {
                $failed++;
            }
            
            // 避免頻率限制:每秒最多 ~100 次(官方未公開確切值,建議 usleep)
            usleep(20000); // 20ms = 50/sec
        }
        
        echo "完成:成功 {$success},失敗 {$failed}\n";
    }
}

// 使用範例
$sender = new SendAllMsg('YOUR_APPID', 'YOUR_APPSECRET');
$sender->sendMsgToAll();

訊息類型 payload 範例

類型msgtypepayload 結構
文本text['text' => ['content' => '內容']]
圖片image['image' => ['media_id' => 'MEDIA_ID']]
語音voice['voice' => ['media_id' => 'MEDIA_ID']]
視頻video['video' => ['media_id' => 'MEDIA_ID', 'title' => '', 'description' => '']]
圖文news['news' => ['articles' => [['title'=>'', 'description'=>'', 'url'=>'', 'picurl'=>''], ...]]]
卡券wxcard['wxcard' => ['card_id' => 'CARD_ID']]

關鍵限制與應對策略

限制官方規定應對策略
48 小時規則用戶 48 小時內有互動才能發送引導用戶點擊選單/回覆關鍵字/掃碼,重置 48 小時窗口
頻率限制未公開確切值,約 100-500 次/秒usleep(20000) 控制 50/sec,分批次執行
用戶量 > 1 萬user/get 需分頁已實作 next_openid 分頁迴圈
Access Token 過期2 小時(7200 秒)檔案快取 + 7000 秒提前刷新
僵尸粉/封號發送失敗 errcode 40003/43004記錄失敗 OpenID,定期清理、標記異常

生產環境架構建議

// 1. 任務佇列化(Redis + Worker)
// 生產者:API 接收群發請求 -> 推入 Redis List
// 消費者:多進程 Worker 消費 -> 呼叫 sendCustomMessage -> 記錄結果

// 2. 失敗重試機制
// 失敗 OpenID 寫入 retry queue,指數退避重試 3 次

// 3. 統計儀表板
// 記錄每次群發:總數、成功、失敗、耗時、失敗原因分布

// 4. 內容審核
// 敏感詞過濾、圖片安全檢測、合規性審核

總結

「無限群發」本質是**客服介面批次推送**,核心流程:

  1. 快取 Access Token(檔案/Redis)
  2. 分頁獲取所有 OpenID
  3. 逐個組裝 payload 調用 message/custom/send
  4. 頻率控制 + 失敗重試 + 結果統計

配合任務佇列、多進程 Worker、監控儀表板,即可構建企業級微信群發系統,突破官方群發介面的次數與審核限制。

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