PHP开发网站之微信登录、绑定
PHP开发网站引入第三方登录之微信登录、绑定
案例(www.spaceyun.com) 写在前面的话:
如果在做此项功能之前有去了解OAuth2.0协议,那么接下来一切都很容易理解,如果没有了解OAuth2.0协议,
也不影响完成此项功能,不过应该是很难领会其原理。 准备工作:
微信登录时在微信开放平台(open.weixin.qq.com)上面,
注册登录之后,*认证开发者资质*(不认证是无法开放网页登录授权的),在管理中心添加网站应用,相关信息准备齐全,
通过*审核*之后,可以获取到APPID和APPSECERT,然后在应用详情里面查看微信登录接口状态,如果为已获得,表示可以正常开发了。
需要注意的是,网站授权回调域和官网地址是没有(http)或者(https)的,例如我的网站授权回调域是(www.spaceyun.com)
我的官网地址也是(www.spaceyun.com),
数据表:用户表里面有openid字段,新建一个微信表,用来存储微信的openid,nickname,headimgurl,sex,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');
} }
在这个方法里面,根据appid,appsecert(这两个都是开放平台获取的)还有回调返回的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在上面已经获取到,获取到信息判断微信表里面是否存在此条数据,
不存在就插入到微信表,这些数据是微信开放给第三方应用的一些相关信息,包括openid,nickname,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;
}
}
?>
PHP开发网站之微信登录、绑定的更多相关文章
- 网站实现微信登录之回调函数中登录逻辑的处理--基于yii2开发的描述
上一篇文章网站实现微信登录之嵌入二维码中描述了如何在自己的登录页面内嵌入登录二维码,今天的这篇文章主要是描述下在扫码成功之后微信重定向回网站后登录逻辑的处理,其实也就是验证身份信息,授权用户登录的逻辑 ...
- 利用WxJava实现网站集成微信登录功能,核心代码竟然不超过10行
最近网站PC端集成微信扫码登录,踩了不少坑,在此记录下实现过程和注意事项. 本文目录 一.微信开放平台操作步骤1.创建“网站应用”2.获取AppID和AppSecret二.开发指南三.开发实战1.po ...
- 利用WxJava实现PC网站集成微信登录功能
原文地址:https://mp.weixin.qq.com/s/rT0xL9uAdHdZck_F8nyncg 来源:微信公众号:java碎碎念 1. 微信开放平台操作步骤 微信开放平台地址:https ...
- 网站实现微信登录之嵌入二维码——基于yii2开发的描述
之前写了一篇yii2获取登录前的页面url地址的文章,然后发现自己对于网站实现微信扫码登录功能的实现不是很熟悉,所以,我会写2-3篇的文章来描述下一个站点如何实现微信扫码登录的功能,来复习下微信扫码登 ...
- 无需公众号PHP微信登录微信授权微信第三方登录微信开发php开发
无论是个人还是公司,无需申请公众号,无需申请微信开放平台,即可实现手机网站和PC网站的微 信登录!!! 正常的微信登录是这样的: 1.手机版网站做微信登录,需要申请一个认证公众号,认证不仅需要公司营 ...
- Asp.Net微信登录-电脑版扫描二维码登录
像京东,一号店等网站都实现了用微信来登录的功能,就是用手机上的微信扫一扫网站上的二维码,微信上确认后,即可自动用微信的帐号登录网站. 一.创建网站应用 在微信开放平台创建一个网站应用 https:// ...
- C#微信登录-电脑版扫描二维码登录
像京东,一号店等网站都实现了用微信来登录的功能,就是用手机上的微信扫一扫网站上的二维码,微信上确认后,即可自动用微信的帐号登录网站. 一.创建网站应用 在微信开放平台创建一个网站应用 https:// ...
- .net Core2.2 WebApi通过OAuth2.0实现微信登录
前言 微信相关配置请参考 微信公众平台 的这篇文章.注意授权回调域名一定要修改正确. 微信网页授权是通过OAuth2.0机制实现的,所以我们可以使用 https://github.com/china- ...
- springboot如何实现微信登录,前期准备
现在网站用微信登录真的是很多,那么具体是怎么实现的呢? 首先介绍的是微信开放平台,我们如果需要微信登录或者支付都需要在上面注册一个账号,用这个账号去为我们的网站申请的话,需要用到企业资料(家里有营业执 ...
随机推荐
- Python的第三天
一.字典 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下所示: ...
- C# 读取和配置IniFile
自定义IniFile操作类 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- c++中的引用与指针的区别
http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...
- Android zxing 解析二维码,生成二维码极简demo
zxing 官方的代码很多,看起来很费劲,此demo只抽取了有用的部分,实现了相机预览解码,解析本地二维码,生成二维码三个功能. 简化后的结构如下: 废话少说直接上代码: BaseDecodeHand ...
- 【转】bind - DNS 設定
http://www.l-penguin.idv.tw/article/dns.htm 參考資訊 DNS 是所有伺服之母,電腦連節時均以 IP 為主,比方說輸入 202.43.195.52 就會到台灣 ...
- vim入门过程
先下载了一本VIM的用户手册. 看到可以使用vimtutor(VIM的入门教程,很不错,由浅入深)作为入门. Unix系统中,请在命令行输入:vimtutor,进入教程. MS-Windows系统中, ...
- dsquery、netdom工具示例
C:\>netdom query fsmo架构主机 DC1.lypower.com.cn域命名主机 DC1.lypower.com.cnPDC ...
- 转载:最近有两款路由器D-link , Tenda分别被爆出固件中存在后门
最近有两款路由器分别被爆出固件中存在后门. D-link D-link是台湾公司,成立于1986年,『公司致力于高级网络.宽带.数字.语音和数据通信解决方案的设计.制造和营销,是业界的全球领导者』(官 ...
- 读取数据库的表并绑定到Listview
$aResultEventlog = _GetQueryTable($strSQL_Compare_FailRecordEventIDs, $iRowsEventlog, $iColsEventlog ...
- Spring知识汇总
Spring简介 Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版.Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通用步骤,留给开发者的仅 ...