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

PHP 實現微信掃碼登錄/註冊全流程:從二維碼生成到 UnionID 綁定

     編輯:PHP 綜合知識

微信掃碼登錄已成標配功能。本文完整梳理 PC 端「掃碼→授權→回調→綁定/註冊」全鏈路,涵蓋二維碼帶參生成、雙授權模式區分、access_token 換取、用戶信息獲取、UnionID 去重綁定等核心環節,附生產級代碼片段。

核心流程圖解

  1. PC 端生成帶 state 參數的授權二維碼
  2. 用戶掃碼授權(網頁授權/UnionID 兩種模式)
  3. 微信回調 redirect_uri 攜帶 code + state
  4. 後端用 code 換取 access_token → refresh_token → 用戶信息
  5. 拿到 unionid(或 openid)查庫判斷:老用戶登錄 / 新用戶註冊綁定
  6. PC 端輪詢或長連接感知狀態變化 → 自動登入 / 跳轉

關鍵技術點深度解析

1. 二維碼生成:state 參數傳遞業務標識

// 使用 phpqrcode 庫生成二維碼圖片流直接輸出
$state = generateUniqueState(); // 自定義業務標識,回調時原樣返回
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?" . http_build_query([
    'appid'         => $appid,
    'redirect_uri'  => 'https://your.com/wcallback',
    'response_type' => 'code',
    'scope'         => 'snsapi_userinfo', // 必須用 userinfo 才能拿 unionid
    'state'         => $state,
]);
QRcode::png($url, false, 'L', 5); // 直接輸出 PNG 圖片流

2. 兩種授權模式區別(必看)

模式scope用戶感知可獲取信息適用場景
靜默授權 snsapi_base 無彈窗,直接跳轉 僅 openid 已關注公眾號、僅需標識用戶
用戶信息授權 snsapi_userinfo 彈窗確認授權 openid + unionid + 昵稱/頭像/性別/地區 開放平台綁定、需展示用戶資料

本文採用 snsapi_userinfo,確保能獲取 unionid 實現跨應用用戶唯一標識。

3. 回調處理:code 換取用戶信息完整鏈路

public function wcallbackAction() {
    $code  = $_GET['code'];
    $state = $_GET['state']; // 驗證 state 防 CSRF
    if (!$code) exit('授權失敗');

    // 1. code 換 access_token
    $tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" . http_build_query([
        'appid'      => $appid,
        'secret'     => $appsecret,
        'code'       => $code,
        'grant_type' => 'authorization_code',
    ]);
    $token = json_decode(httpGet($tokenUrl));
    if (isset($token->errcode)) exit('Token錯誤:' . $token->errmsg);

    // 2. 刷新 access_token(可選,延長有效期)
    $refreshUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?" . http_build_query([
        'appid'         => $appid,
        'grant_type'    => 'refresh_token',
        'refresh_token' => $token->refresh_token,
    ]);
    $access = json_decode(httpGet($refreshUrl));

    // 3. 拉取用戶信息(含 unionid)
    $infoUrl = "https://api.weixin.qq.com/sns/userinfo?" . http_build_query([
        'access_token' => $access->access_token,
        'openid'       => $access->openid,
        'lang'         => 'zh_CN',
    ]);
    $user = json_decode(httpGet($infoUrl));
    if (isset($user->errcode)) exit('用戶信息錯誤:' . $user->errmsg);

    // 4. 核心:unionid 去重綁定邏輯
    $unionid = $user->unionid;
    $existing = DB::getOne("SELECT user_id FROM user_bind WHERE type='weixin' AND unionid=?", [$unionid]);
    
    if ($existing) {
        // 老用戶:直接登錄,寫 session
        loginByUserId($existing);
    } else {
        // 新用戶:註冊 + 綁定
        $uid = registerUser(['nickname'=>$user->nickname, 'avatar'=>$user->headimgurl]);
        bindWeixin($uid, $unionid, $access->openid);
        loginByUserId($uid);
    }

    // 5. 通知 PC 端:WebSocket / 長輪詢 / 寫快取狀態
    setLoginState($state, $uid); // PC 端輪詢該 state 即可感知
}

4. PC 端狀態感知三種方案對比

方案實現複雜度實時性資源消耗推薦指數
AJAX 短輪詢低秒級中⭐⭐⭐ 簡單項目首選
WebSocket 長連接中毫秒級低⭐⭐⭐⭐⭐ 高併發首選
Server-Sent Events (SSE)低毫秒級低⭐⭐⭐⭐ 輕量級最佳

5. 微信瀏覽器關閉/跳轉技巧

// 授權成功後在微信內置瀏覽器關閉當前頁
WeixinJSBridge.call('closeWindow');

// 或跳轉到公眾號關注頁
location.href = 'weixin://profile/gh_xxxxxxxx';

安全與避坑清單

  • ✅ state 必須驗證:防 CSRF 攻擊,生成時存 Redis,回調時比對並刪除
  • ✅ access_token 必須緩存:7200 秒有效期,避免高頻請求觸發頻控
  • ✅ unionid 為唯一綁定鍵:openid 隨應用不同,unionid 跨應用唯一(需綁定開放平台)
  • ✅ 錯誤碼完整處理:40029(code無效)、40163(code已用)、48001(未授權) 等
  • ✅ HTTPS 強制:redirect_uri 必須 HTTPS,否則微信攔截

掌握這套流程,即可實現從「掃碼」到「登錄」的閉環。建議將微信授權封裝為獨立 Service 類,配合事件驅動架構,支援多端(PC/H5/小程序)複用。

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