成為微信公眾號開發者的第一步是通過接口驗證。本文提供完整的微信基礎類(Weixin)、接口處理腳本(weixin.php)、驗證測試腳本,涵蓋文字訊息、圖文訊息回覆,並說明驗證流程與部署要點。
<?php
class Weixin {
public $token = '';
public $debug = false;
public $setFlag = false;
public $msgtype = 'text';
public $msg = [];
public function __construct($token, $debug) {
$this->token = $token;
$this->debug = $debug;
}
// 取得使用者訊息
public function getMsg() {
$postStr = $GLOBALS['HTTP_RAW_POST_DATA'];
if ($this->debug) $this->write_log($postStr);
if (!empty($postStr)) {
$this->msg = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$this->msgtype = strtolower($this->msg['MsgType']);
}
}
// 回覆文字訊息
public function makeText($text = '') {
$tpl = "<xml>
<ToUserName><![CDATA[{$this->msg['FromUserName']}]]></ToUserName>
<FromUserName><![CDATA[{$this->msg['ToUserName']}]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>%s</FuncFlag>
</xml>";
return sprintf($tpl, time(), $text, $this->setFlag ? 1 : 0);
}
// 回覆圖文訊息
public function makeNews($newsData = []) {
$itemTpl = "<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>";
$items = '';
$count = min(count($newsData), 10); // 最多 10 條
for ($i = 0; $i < $count; $i++) {
$item = $newsData[$i];
$items .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
}
$tpl = "<xml>
<ToUserName><![CDATA[{$this->msg['FromUserName']}]]></ToUserName>
<FromUserName><![CDATA[{$this->msg['ToUserName']}]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>$count</ArticleCount>
<Articles>$items</Articles>
<FuncFlag>%s</FuncFlag>
</xml>";
return sprintf($tpl, time(), $this->setFlag ? 1 : 0);
}
public function reply($data) {
if ($this->debug) $this->write_log($data);
echo $data;
}
// 接口驗證
public function valid() {
if ($this->checkSignature()) {
echo $_GET['echostr'];
exit;
} else {
$this->write_log('驗證失敗');
exit;
}
}
private function checkSignature() {
$signature = $_GET['signature'];
$timestamp = $_GET['timestamp'];
$nonce = $_GET['nonce'];
$tmpArr = [$this->token, $timestamp, $nonce];
sort($tmpArr, SORT_STRING);
$tmpStr = sha1(implode($tmpArr));
return $tmpStr === $signature;
}
private function write_log($log) {
// 實作寫入日誌檔案或資料庫
error_log(date('Y-m-d H:i:s') . " $log\n", 3, __DIR__ . '/weixin.log');
}
}
?>
<?php
header('Content-Type: text/html; charset=utf-8');
require_once 'Weixin.class.php';
define('TOKEN', 'your_token_here');
define('DEBUG', false);
$weixin = new Weixin(TOKEN, DEBUG);
// $weixin->valid(); // 驗證通過後註解掉
$weixin->getMsg();
$type = $weixin->msgtype;
$from = $weixin->msg['FromUserName'];
if ($type === 'text') {
$content = $weixin->msg['Content'];
if ($content === '你好') {
$reply = $weixin->makeText('歡迎關注!');
} else {
// 示例:回覆圖文
$articles = [
['Title'=>'電腦學習網', 'Description'=>'十萬個為什麼', 'PicUrl'=>'https://example.com/img1.jpg', 'Url'=>'https://www.why100000.com/'],
['Title'=>'PHP學習網', 'Description'=>'大型PHP社區', 'PicUrl'=>'https://example.com/img2.jpg', 'Url'=>'https://www.veryphp.cn/'],
];
$reply = $weixin->makeNews($articles);
}
} elseif ($type === 'event' && $weixin->msg['Event'] === 'subscribe') {
$reply = $weixin->makeText('感謝關注,輸入「你好」體驗功能。');
} else {
$reply = $weixin->makeText('收到:' . $content);
}
$weixin->reply($reply);
?>
<?php
define('TOKEN', 'your_token_here');
$echostr = 'test_echostr';
$timestamp = (string)time();
$nonce = 'test_nonce';
$tmpArr = [TOKEN, $timestamp, $nonce];
sort($tmpArr, SORT_STRING);
$signature = sha1(implode($tmpArr));
$url = 'https://yourdomain.com/weixin.php';
$params = http_build_query([
'signature' => $signature,
'timestamp' => $timestamp,
'nonce' => $nonce,
'echostr' => $echostr
]);
$ch = curl_init("$url?$params");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
echo "驗證回傳: $result"; // 應輸出 test_echostr
?>
| 項目 | 說明 |
|---|---|
| Token 一致性 | 微信後台設定的 Token 與程式碼 define('TOKEN', ...) 必須完全一致 |
| 伺服器網址 | 需為 80/443 埠、可公開存取、支援 HTTP/HTTPS |
| 驗證流程 | 首次提交時啟用 $weixin->valid(),驗證通過後**必須註解掉**,否則無法處理訊息 |
| 回覆格式 | 嚴格遵循微信 XML 規範,CDATA 區塊不可省略 |
| 編碼 | 全程 UTF-8,資料庫連線、PHP 檔案、HTML meta 皆設為 UTF-8 |
| 日誌 | 上線後關閉 DEBUG,但保留 write_log 記錄關鍵錯誤 |
EasyWeChat 等成熟 SDK 替代手工類別