PHP開發網站之微信登錄、綁定



PHP開發網站引入第三方登錄之微信登錄綁定
案例www.spaceyun.com

寫在前面的話
如果在做此項功能之前有去了解OAuth2.0協議那么接下來一切都很容易理解如果沒有了解OAuth2.0協議
也不影響完成此項功能不過應該是很難領會其原理

准備工作
微信登錄時在微信開放平台open.weixin.qq.com上面
注冊登錄之后*認證開發者資質*不認證是無法開放網頁登錄授權的),在管理中心添加網站應用相關信息准備齊全
通過*審核*之后可以獲取到APPID和APPSECERT然后在應用詳情里面查看微信登錄接口狀態如果為已獲得表示可以正常開發了
需要注意的是網站授權回調域和官網地址是沒有http或者https例如我的網站授權回調域是www.spaceyun.com
我的官網地址也是www.spaceyun.com),
數據表用戶表里面有openid字段新建一個微信表用來存儲微信的openidnickname,headimgurlsex,city,province,country等信息

流程
1用戶同意授權獲取code
2通過code獲取網頁授權access_token
3)刷新access_token(如果需要)
4拉去用戶信息需要scope為snsapi_userinfo

正式開發
我的開發是在laravel5.2框架里面的所以代碼會按照框架的模式不過並沒有使用laravel的擴展包純手工代碼
應該有參考價值
登錄和綁定其實是一套流程就算綁定也是操作的snsapi_login的scope接口就是說登錄是點擊掃碼獲取openid登錄
綁定也是點擊掃碼獲取openid綁定
先以微信登錄為例
路由
Route::get('wxLogin', 'WeixinController@wxLogin');//點擊微信登錄跳轉到的url路由
Route::get('wxGetCode', 'WeixinController@wxGetCode');//用戶掃碼之后跳轉到的url路由
控制器
先單個方法分析后面補上完整代碼
1.
//login
public function wxLogin(){
$appid = $this->appid;
$redirect_uri = urlencode($this->redirect_uri);
$scope = "snsapi_login";
$state = "wxLogin";
$url = "https://open.weixin.qq.com/connect/qrconnect?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
return redirect($url);
}
這個方法用來做微信登錄請求觸發就是用戶點擊微信登錄提示的鏈接是跳轉到上面的$url,
其中的appid是在開放平台創建應用后獲取的
redirect_uri是用戶掃碼之后的回調地址因為會拼接在下面的url里面需要用urlencode處理
scope這里必須是"snsapi_login"
state是會提供給回調地址的參數類似於一個場景值的設定可以任意設置用來區分從網站的不同位置發起的請求建議使用有意義的英文單詞
url是微信開放平台固定的里面的參數替換成我們上面的參數
最后做一個跳轉我使用的是框架自帶的方法可根據實際情況更改
這個操作會出現一個展示微信登錄二維碼的頁面這個頁面也是微信的頁面跟我們本地的服務器沒有任何關系
2.
//reback url-->wxGetCode
public function wxGetCode(){
$code = $_GET['code'];
$state = $_GET['state'];

if($state === 'wxLogin'){
$this->loginWeixin($code);
}elseif($state === 'wxBind'){
$this->bindWeixin($code);
}else{
return redirect("http://www.spaceyun.com");
}
}
這是用戶掃碼之后從微信的二維碼頁面會跳轉到我們服務器的處理頁面用戶掃碼登錄成功之后
會攜帶code和state參數提交到我們服務器的服務器的地址
我們接收code和state根據state場景值判斷做什么處理上面我們是wxLogin會到loginWeixin方法繼續處理code
3.
//loginWeixin
private function loginWeixin($code){
$appid = $this->appid;
$appsecert = $this->appsecert;
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecert."&code=".$code."&grant_type=authorization_code";

//curl模擬get請求,獲取結果
$res = $this->http_curl($url);
//轉化為數組
$return_data = json_decode($res,true);
$openid = $return_data['openid'];

//openid存在,直接登錄,openid不存在,先注冊再登錄
$result = User::where('wx_openid',$openid)->first();
if($result){
//login
Auth::loginUsingId($result->id,true);

$jump_url = 'http://www.spaceyun.com/accountSettings';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/accountSettings');
}else{
$access_token = $return_data['access_token'];
//獲取用戶基本信息
$getInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
$userInfo = $this->http_curl($getInfoUrl);
$weixins = json_decode($userInfo);

//判斷weixins表里面是否存在該條數據
$weixins_result = Weixin::where('openid',$openid)->first();
if(empty($weixins_result)){
//插入數據
Weixin::create([
'openid'=>$weixins->openid,
'nickname'=>$weixins->nickname,
'sex'=>$weixins->sex,
'city'=>$weixins->city,
'province'=>$weixins->province,
'country'=>$weixins->country,
'headimgurl'=>$weixins->headimgurl,
]);
}

//Register and login
$user = new User();
$arr['name'] = $weixins->nickname;
$arr['email'] = $openid."@fake.com";
$arr['password'] = "passwd";
$arr['phone'] = substr($openid,8);
$arr['wx_openid'] = $openid;
$insertId = $user->insertGetId($arr);
Auth::loginUsingId($insertId,true);
$jump_url = 'http://www.spaceyun.com/accountSettings';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/accountSettings');
}

}
在這個方法里面根據appidappsecert這兩個都是開放平台獲取的還有回調返回的code拼接成url
然后用curl模擬get請求抓取返回數據我將返回的數據res轉化成數組獲取到用戶的openid和access_token,
這時在我們的用戶表里面一定要有一個叫做微信的openid的字段我的字段名是wx_openid因為我還會有qq_openid和sina_openid,
我們去用戶表查詢我們獲取到的微信用戶openid在不在我們的用戶表里面
如果存在說明用戶是一個老用戶直接登錄我用的laravel的Auth::loginUsingId($result->id,true)方法完成登錄做跳轉
我跳轉到了賬號設置頁
如果不存在說明這是一個新用戶新用戶需要注冊到用戶表並且獲取相關信息新增到微信表
獲取用戶基本信息需要access_token和openid在上面已經獲取到獲取到信息判斷微信表里面是否存在此條數據
不存在就插入到微信表這些數據是微信開放給第三方應用的一些相關信息包括openidnickname,headimgurl
sex,city,province,country等信息
然后繼續在用戶表里面插入一條數據因為有一些非空字段我就自定義生成了一些數據
最后給這條最新添加的用戶做登錄登陸之后跳轉

關於我的跳轉多說一句因為用這個框架十來天之前也只開發了一個郵箱相關的功能所以沒能明白redirect的原理
准備系統研究laravel時再考慮這個我要是只用window.location.href或者只用return redirect都無法實現跳轉
把兩個都寫在這個就可以應該是有問題的不過不是錯誤先這樣吧


這樣登錄功能就開發完了綁定功能是相同的流程只是綁定要在登錄狀態下操作也不用插入用戶表只需要改用戶表中wx_openid字段
需要注意的是一些邏輯上的問題比如說微信號已經綁定過一個賬號根據自己應用需求判斷允不允許綁定多個等等

<?php
namespace App\Http\Controllers;

use App\Weixin;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests;
use App\User;
use Cookie;

class WeixinController extends Controller{
//attribute------開放平台獲取
private $appid = "your APPID";
private $appsecert = "your APPSECERT";
//redirect_uri,需要是跳到具體的頁面處理,並且要在開放平台創建應用的授權回調域下面
private $redirect_uri = "http://www.spaceyun.com/wxGetCode";

//login
public function wxLogin(){
$appid = $this->appid;
$redirect_uri = urlencode($this->redirect_uri);
$scope = "snsapi_login";
$state = "wxLogin";
$url = "https://open.weixin.qq.com/connect/qrconnect?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
return redirect($url);
}

//bind
public function wxBind(){
$appid = $this->appid;
$redirect_uri = urlencode($this->redirect_uri);
$scope = "snsapi_login";
$state = "wxBind";
$url = "https://open.weixin.qq.com/connect/qrconnect?appid=".$appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=".$scope."&state=".$state."#wechat_redirect";
return redirect($url);
}

//reback url-->wxGetCode
public function wxGetCode(){
$code = $_GET['code'];
$state = $_GET['state'];

if($state === 'wxLogin'){
$this->loginWeixin($code);
}elseif($state === 'wxBind'){
$this->bindWeixin($code);
}else{
return redirect("http://www.spaceyun.com");
}
}

//loginWeixin
private function loginWeixin($code){
$appid = $this->appid;
$appsecert = $this->appsecert;
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecert."&code=".$code."&grant_type=authorization_code";

//curl模擬get請求,獲取結果
$res = $this->http_curl($url);

//轉化為數組
$return_data = json_decode($res,true);
$openid = $return_data['openid'];

//openid存在,直接登錄,openid不存在,先注冊再登錄
$result = User::where('wx_openid',$openid)->first();
if($result){
//login
Auth::loginUsingId($result->id,true);

$jump_url = 'http://www.spaceyun.com/accountSettings';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/accountSettings');
}else{
//轉化為數組
$access_token = $return_data['access_token'];

//獲取用戶基本信息
$getInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
$userInfo = $this->http_curl($getInfoUrl);
$weixins = json_decode($userInfo);

//判斷weixins表里面是否存在該條數據
$weixins_result = Weixin::where('openid',$openid)->first();
if(empty($weixins_result)){
//插入數據
Weixin::create([
'openid'=>$weixins->openid,
'nickname'=>$weixins->nickname,
'sex'=>$weixins->sex,
'city'=>$weixins->city,
'province'=>$weixins->province,
'country'=>$weixins->country,
'headimgurl'=>$weixins->headimgurl,
]);
}

//Register and login
$user = new User();
$arr['name'] = $weixins->nickname;
$arr['email'] = $openid."@fake.com";
$arr['password'] = "passwd";
$arr['phone'] = substr($openid,8);
$arr['wx_openid'] = $openid;
$insertId = $user->insertGetId($arr);
Auth::loginUsingId($insertId,true);
$jump_url = 'http://www.spaceyun.com/accountSettings';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/accountSettings');
}

}


//bindWeixin
private function bindWeixin($code){
$appid = $this->appid;
$appsecert = $this->appsecert;
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecert."&code=".$code."&grant_type=authorization_code";

//curl模擬get請求,獲取結果
$res = $this->http_curl($url);

//轉化為數組
$return_data = json_decode($res, true);
$access_token = $return_data['access_token'];
$openid = $return_data['openid'];

//openid存在,提示需要解綁其他賬號,openid不存在,先補充信息到weixins表再綁定
$result = User::where('wx_openid',$openid)->first();
if($result){
$jump_url = 'http://www.spaceyun.com/wxBindError';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/wxBindError');

}else{
$user_id = Auth::id();
$user = User::find($user_id);
$user->wx_openid = $openid;
$user->save();

//判斷weixins表里面是否存在該條數據
$weixins_result = Weixin::where('openid',$openid)->first();
if(empty($weixins_result)){
//獲取用戶基本信息
$getInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";

$userInfo = $this->http_curl($getInfoUrl);
$weixins = json_decode($userInfo);
Weixin::create([
'openid'=>$weixins->openid,
'nickname'=>$weixins->nickname,
'sex'=>$weixins->sex,
'city'=>$weixins->city,
'province'=>$weixins->province,
'country'=>$weixins->country,
'headimgurl'=>$weixins->headimgurl,
]);
}
}
$jump_url = 'http://www.spaceyun.com/accountSettings';
echo "<script>window.location.href='".$jump_url."'</script>";
return redirect('http://www.spaceyun.com/accountSettings');
}

//wxBindError
public function wxBindError(){
$wxBindError = '該微信號已被綁定雲享客賬號,如需更改請到之前賬號解除綁定';
return view("weixin.wxBindError",['information'=>$wxBindError]);
}

//解綁
public function wxUnbind(){
//users表里面wx_openid字段清空
$user_id = Auth::id();
$user = User::find($user_id);
if(!preg_match("/^1[34578]{1}\d{9}$/",$user->phone)){
$wxBindError = '請認證手機號之后再解除綁定微信';
return view("weixin.wxBindError",['information'=>$wxBindError]);
}else{
$user->wx_openid = '0';
$user->save();

return redirect('/accountSettings');
}

}

//curl模擬get請求
private function http_curl($url){
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_URL, $url);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curlobj, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curlobj, CURLOPT_SSL_VERIFYHOST, FALSE);

$output = curl_exec($curlobj);
curl_close($curlobj);

return $output;
}
}
?>




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM