微信自定義菜單的 view 型按鈕雖能直接打開網頁,但不會攜帶用戶身份資訊。若需在網頁中識別用戶(如個人中心、授權登入、積分商城),必須使用網頁授權獲取用戶基本信息高級介面 (OAuth2.0 流程),透過 code 換取 access_token 與 openid。
getcodeurl.php)code 回調 callback.phpcallback.php 用 code 換取 access_token + openidaccess_token + openid 拉取用戶詳細資料 (snsapi_userinfo)<?php
session_start();
// 若已有用戶資訊直接使用
if (isset($_SESSION['user'])) {
// 這裡可直接進行業務邏輯,或重導向至實際業務頁
header('Location: /member.php');
exit;
}
$appId = '你的公眾號 AppID';
$redirect = 'https://你的域名/callback.php'; // 必須與公眾平台配置的「網頁授權回調域名」一致
$scope = 'snsapi_base'; // 靜默授權,僅獲取 openid;需用戶資料改為 'snsapi_userinfo'
$state = 'STATE_' . time(); // 防 CSRF,回調時原樣返回
$authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"
. "?appid={$appId}"
. "&redirect_uri=" . urlencode($redirect)
. "&response_type=code"
. "&scope={$scope}"
. "&state={$state}"
. "#wechat_redirect";
header("Location: {$authUrl}");
exit;
?>
<?php
session_start();
$appId = '你的公眾號 AppID';
$secret = '你的公眾號 AppSecret';
$code = $_GET['code'] ?? '';
$state = $_GET['state'] ?? '';
// 基礎驗證
if (empty($code)) {
exit('授權失敗:缺少 code 參數');
}
// 1. 用 code 換取 access_token 與 openid
$tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"
. "?appid={$appId}"
. "&secret={$secret}"
. "&code={$code}"
. "&grant_type=authorization_code";
$ch = curl_init($tokenUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => false, // 生產環境建議開啟並配置 CA 憑證
]);
$resp = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
if ($err) {
exit("請求微信介面失敗: {$err}");
}
$tokenData = json_decode($resp, true);
if (isset($tokenData['errcode'])) {
exit("微信返回錯誤: {$tokenData['errmsg']} (errcode: {$tokenData['errcode']})");
}
$accessToken = $tokenData['access_token'];
$openid = $tokenData['openid'];
// 2. (可選) 獲取用戶詳細資料 — 僅 scope=snsapi_userinfo 時有效
$userInfo = ['openid' => $openid]; // 基礎資訊
if ($scope === 'snsapi_userinfo') {
$userUrl = "https://api.weixin.qq.com/sns/userinfo"
. "?access_token={$accessToken}"
. "&openid={$openid}"
. "&lang=zh_CN";
$ch = curl_init($userUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 15,
]);
$userResp = curl_exec($ch);
curl_close($ch);
$userData = json_decode($userResp, true);
if (empty($userData['errcode'])) {
$userInfo = array_merge($userInfo, $userData); // 合併 nickname, headimgurl, sex, city...
}
}
// 3. 存入 Session,完成授權
$_SESSION['user'] = $userInfo;
// 4. 重導向至實際業務頁
header('Location: /member.php');
exit;
?>
| 項目 | 說明 |
|---|---|
| 網頁授權回調域名 | 公眾平台 → 開發 → 介面權限 → 網頁授權獲取用戶基本信息 → 修改。填寫域名 (不帶協議/路徑),如 example.com。需 ICP 備案。 |
| Scope 選擇 | snsapi_base:靜默授權,用戶無感知,僅獲 openid。snsapi_userinfo:彈出授權頁,可獲昵稱、頭像、性別、地區等。 |
| State 參數 | 防 CSRF 攻擊,建議生成隨機字串存 Session,回調時驗證一致性。 |
| Access Token 時效 | 網頁授權 access_token 有效期 2 小時,可用 refresh_token 刷新 (有效期 30 天)。長期業務建議存資料庫並定時刷新。 |
| HTTPS 強制 | 回調域名必須支援 HTTPS,微信伺服器拒絕 HTTP 回調。 |
| 測試賬號 | 未認證訂閱號可用「公眾平台測試賬號」體驗完整流程。 |
實際專案建議封裝 WechatOAuth 類,提供 getAuthorizeUrl()、handleCallback()、getUserInfo() 等方法,並整合 access_token 快取 (Redis/檔案) 避免重複請求微信介面。另需處理「用戶拒絕授權」回調 (?authdeny=1) 的友善提示頁面。
微信網頁授權雖流程稍繁瑣,但掌握「引導 → 授權 → 回調換 token → 存 Session」四步核心邏輯,配合正確的域名配置與 Scope 選擇,即可可靠獲取用戶 OpenID 乃至完整資料,為公眾號業務開發奠定身份識別基石。