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

微信網頁授權 OAuth2.0 PHP 完整實現:從獲取 Code 到拉取用戶信息

     編輯:PHP 綜合知識

業務流程圖解

用戶訪問頁面
    ↓
引導至微信授權頁(scope=snsapi_userinfo)
    ↓
用戶點擊授權
    ↓
微信回調 redirect_uri?code=CODE&state=STATE
    ↓
後端用 code 換取 access_token + openid
    ↓
用 access_token + openid 拉取用戶詳情
    ↓
業務邏輯處理(綁定、登錄、註冊)

核心參數說明

參數來源說明
appid公眾平台公眾號唯一標識
secret公眾平台開發者密鑰,極度機密
redirect_uri業務配置授權後回調地址,需 URL 編碼
scope固定值snsapi_base靜默獲取openid / snsapi_userinfo獲取用戶信息
state自定義防 CSRF、攜帶業務參數,原樣回傳

完整單文件實現

 $user['openid'],
        'nickname' => $user['nickname'],
        'headimgurl' => $user['headimgurl'],
        'sex' => $user['sex'],      // 1男 2女 0未知
        'city' => $user['city'],
        'province' => $user['province'],
        'country' => $user['country'],
        'unionid' => $user['unionid'] ?? null,  // 僅在綁定開放平台時返回
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

// ========== 工具函數 ==========
function httpRequest(string $url, array $postData = []): string {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,  // 生產環境建議開啟並配置 CA 憑證
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
    ]);
    if ($postData) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
    }
    $response = curl_exec($ch);
    if ($response === false) {
        throw new RuntimeException('cURL 錯誤: ' . curl_error($ch));
    }
    curl_close($ch);
    return $response;
}

關鍵細節與避坑指南

1. 域名配置陷阱

  • 公眾平台「開發配置」→「網頁授權域名」需填寫不帶協議和路徑的域名(如 domain.com)
  • 回調頁域名必須與授權域名一致,支持子目錄
  • 本地開發可用內網穿透(ngrok/frp)映射到公網域名

2. Scope 選擇策略

3. Access Token 刷新機制

// access_token 有效期 2 小時,過期需用 refresh_token 刷新
function refreshAccessToken(string $appid, string $refreshToken): array {
    $url = "https://api.weixin.qq.com/sns/oauth2/refresh_token"
        . "?appid={$appid}"
        . "&grant_type=refresh_token"
        . "&refresh_token={$refreshToken}";
    return json_decode(httpRequest($url), true);
}

// 業務中建議:存儲 refresh_token 到數據庫,定時任務刷新

4. 狀態保持與 State 參數

// 生成授權 URL 時攜帶 state
$state = base64_encode(json_encode([
    'from' => $_GET['from'] ?? 'index',
    'csrf' => bin2hex(random_bytes(8)),
]));
$authUrl = "...&state={$state}#wechat_redirect";

// 回調驗證
$stateData = json_decode(base64_decode($_GET['state']), true);
if (!hash_equals($_SESSION['csrf_token'], $stateData['csrf'])) {
    die('CSRF 攻擊檢測');
}
// 跳轉回原業務頁
header("Location: /{$stateData['from']}");

5. 多公眾號/開放平台 UnionID 打通

  • 同一開放平台下的公眾號、小程序、APP 共享 UnionID
  • 需在開放平台綁定公眾號,且用戶授權過該公眾號
  • UnionID 是跨應用識別同一用戶的唯一鍵

生產環境架構建議

  1. 分層封裝:將 OAuth 邏輯封裝為 Service 類,Controller 僅調用
  2. 緩存 Token:access_token 存 Redis,key 為 wx:token:{appid},TTL 7000 秒
  3. 用戶表設計:存儲 openid、unionid、session_key、最新用戶信息、最後登錄時間
  4. 靜默授權降級:首次訪問嘗試 snsapi_base 獲取 openid,需詳細信息時再引導 snsapi_userinfo
  5. 錯誤碼處理:40029(code無效)、40163(code已被使用)、40003(openid不匹配) 等分類處理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
Scope用戶感知獲取信息適用場景
snsapi_base無感(靜默)僅 openid判斷關注、簡單標識用戶
snsapi_userinfo彈窗授權完整用戶信息需頭像、暱稱、地區等業務