微信網站應用一鍵登入--Thinkphp
實現步驟:
1.註冊微信開放平臺https://open.weixin.qq.com,一定要清楚微信開放平臺和微信公眾平臺是分別獨立的,不能共用。
2.登入進入——管理中心,網站應用,建立網站應用。填寫申請,企業還要蓋章,然後設定域名,最後交300元保護費。成功通過驗證。獲得appid和appSecret兩個引數。3.現在可以在web端裡寫登入控制器了。
4.微信網站登入的文件在https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=41ab5f757248bbbdcc2aad1a6d52b49fdc19579e&lang=zh_CN。
5.微信登入請求,其實你可以當成是個url跳轉。https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
引數 是否必須 說明
appid 是 應用唯一標識
redirect_uri 是 重定向地址,需要進行UrlEncode
response_type 是 填code
scope 是 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即可
state 否 用於保持請求和回撥的狀態,授權請求後原樣帶回給第三方。該引數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該引數,可設定為簡單的隨機數加session進行校驗
把appid引數傳給開放平臺。連結頁面會顯示一個二維碼。
6.使用者掃碼二維碼,掃碼成功後,會跳轉回你傳的域名地址。
同時域名後面會帶有code和state引數。這個code則是我們需要拿到的鑰匙
redirect_uri?code=CODE&state=STATE
7.在redirect_uri跳轉的頁面或者控制器中,接收code值
code每次會生成一個,用後即會銷燬,也就是你不能不停跳轉。
8.通過appid、appSecret還有code值,請求open的access_token介面,獲得access_token。
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
引數 說明
access_token 介面呼叫憑證
expires_in access_token介面呼叫憑證超時時間,單位(秒)
refresh_token 使用者重新整理access_token
openid 授權使用者唯一標識
scope 使用者授權的作用域,使用逗號(,)分隔
unionid 當且僅當該網站應用已獲得該使用者的userinfo授權時,才會出現該欄位。
這裡解釋一下,access_token是介面憑證,請求介面需要帶上,時間為2個小時。openid是獲取使用者資訊的引數,就如username。而unionid則是uid,使用者的唯一ID。
9.拿到token和openid後,可以通過UserInfo介面獲得使用者資料。https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
正確的Json返回結果:
{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
10.基本上流程就是這樣。
流程完了就描述下問題。
1.如果第一步跳轉到微信介面時,出現“scope引數錯誤”,說明appid錯誤或者你沒交保護費。用微信公眾號的appid沒用
2.請求token的時候,需要通過cURL來抓取,CURL抓取時普遍會出現抓取不到的問題,具體沒用深究,估計是https的抓取方式和http不一樣,寫了個httpGet方法實現了抓取,抓取後內容為json資料,需要decode一下轉化為陣列
3.為了實現與手機端使用者一致性,我們需要記錄openid以及unionid。公眾號與開放平臺的openid是不一樣的,唯一相同的unionid。但是這兩個openid都能獲取到使用者資訊。我建議除了使用者表以外,加一個第三方登入表,欄位為 id,uid,type,openid,unionid,refresh_token。type
1是微信端,2是PC端。unionid存在時,就不需要再建立一條使用者資訊。資訊獲取後建立session或者cookie
4.為防止csrf跨站請求,state我加入了一個隨機數,這個隨機數存到session中,當用戶掃碼確認後,返回時,如果不一致即會被認為跨站請求偽造攻擊
<?php
/**
* Created by PhpStorm.
* function: 處理第三方登入:微信登入
* User: yule
* Date: 2016/4/29 0029
* Time: 下午 6:48
*/
namespace Home\Controller;
use Think\Controller;
class LoginApiController extends Controller
{
private $_appId;
private $_appSecret;
private $_webRoot;
private $_openUrlQrc;
private $_openUrlToken;
private $_openUrlUserInfo;
public function __construct()
{
parent::__construct();
//修改成自己的
$this->_appId = 'wx836a5fd61d0a420f';//開放平臺網站應用
$this->_appSecret = '6293594d396c450b32eb71da5caa9197';
$this->_webRoot = 'http://www.volunteerinaustralia.com/index.php/Home/LoginApi/wxCheck';//返回的域名網址,必須跟網站應用的域名網址相同
$this->_openUrlQrc = 'https://open.weixin.qq.com/connect/qrconnect';//申請二維碼介面
$this->_openUrlToken = 'https://api.weixin.qq.com/sns/oauth2/access_token';//申請token介面
$this->_openUrlUserInfo = 'https://api.weixin.qq.com/sns/userinfo';//申請使用者資訊介面
}
public function index(){
}
/**
* 驗證微信掃碼後的使用者資料
*/
public function wxCheck(){
$code = I('code');//只能使用1次即銷燬
$state = I('state');
if($state != $_SESSION['wx_state']){
$this->error("請進入官網掃描二維碼",'/index.php/Home/Index/login');
exit();
}
session('wx_state',null);//清除這個session
//獲取access_token和openid資訊,還有使用者唯一標識unionid
$ken = $this->wxToken($code);//:access_token,expires_in,refresh_token,openid,scope,unionid
if($ken['errcode'] == 40029){
$this->error("code引數已經過期");
}
//判斷是否已存在
$map['openid'] = $ken['openid'];
$map['unionid'] = $ken['unionid'];
$Member = M('member');//這個自己寫一下查詢資料庫
$res = $Member->where($map)->select();//查詢openid是否存在,而PC和微信端 openid不一致,只有unionid才是唯一標識
if($res){
cookie('username',$res[0]['username']);
cookie('memberId',$res[0]['id']);
}
else{
$user = $this->wxUserInfo($ken['access_token'],$ken['openid']);//獲取使用者資訊
$data = array(
'openid' => $user['openid'],
'unionid' => $user['unionid'],
'username' => $user['nickname'],
'password' => '微信使用者'.$this->getRandChar(8),
//'updated' => time(),
'pubdate' => date("Y-m-d H:i:s"),
);
$memberId = $Member->add($data);//寫入到資料庫中,返回的是插入id
cookie('username',$user['nickname']);
cookie('memberId', $memberId);
}
//session('userInfo', $userinfo);//寫入session
redirect("http://www.volunteerinaustralia.com/index.php/Home/Index/member");
}
/**
* 提交微信登入請求
*/
public function wxLogin(){
$stats = $this->getRandChar(16);//該引數可用於防止csrf攻擊(跨站請求偽造攻擊)
session('wx_state',$stats);//把隨機字串寫入session,驗證時對比
$url = $this->_openUrlQrc.'?appid='.$this->_appId.'&redirect_uri='.urlencode($this->_webRoot).'&response_type=code&scope=snsapi_login&state='.$stats;
redirect($url);//跳轉到掃碼
}
//生成隨機數,length長度
function getRandChar($length){
$str = null;
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($strPol)-1;
for($i=0;$i<$length;$i++){
$str.=$strPol[rand(0,$max)];//rand($min,$max)生成介於min和max兩個數之間的一個隨機整數
}
return $str;
}
//CURL獲取url返回值
function httpGet($url){
$oCurl = curl_init();//例項化
if(stripos($url,"https://")!==FALSE){
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );//是否返回值,1時給字串,0輸出到螢幕
$sContent = curl_exec($oCurl);//獲得頁面資料
$aStatus = curl_getinfo($oCurl);//獲取CURL連線資料的資訊
curl_close($oCurl);//關閉資源
//獲取成功
$output_array = json_decode($sContent,true);//轉換json格式
if(intval($aStatus["http_code"])==200){
return $output_array;
}else{
return false;
}
}
//獲取token資訊
public function wxToken($code){
$url = $this->_openUrlToken.'?appid='.$this->_appId.'&secret='.$this->_appSecret.'&code='.$code.'&grant_type=authorization_code';
$sContent = $this->httpGet($url);//獲取token資料
return $sContent;
}
//延長token時間,預設token兩個小時
public function wxrefresh($refresh){
$url = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?appid='.$this->_appId.'&grant_type=refresh_token&refresh_token='.$refresh;
return $this->httpGet($url);
}
//檢驗token授權是否有效
public function wxchecktoken($token,$openid){
$url = 'https://api.weixin.qq.com/sns/auth?access_token='.$token.'&openid='.$openid;
return $this->httpGet($url);
}
//獲取微信使用者個人資訊,但公眾號和開放平臺opendid 會不一樣,unionid是使用者唯一標識
public function wxUserInfo($token,$openid){
$url = $this->_openUrlUserInfo.'?access_token='.$token.'&lang=zh-CN&openid='.$openid;
return $this->httpGet($url);
}
}
作品網址:http://www.volunteerinaustralia.com/