基于thinkCMF5的微信网页授权源码 <https://github.com/top-songshijie/WechatAuthorization>

主要是在项目中遇到网页授权登录这个需求,就对此做些总结记录。

OAuth2.0授权

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的个人信息,而无需将用户名和密码提供给第三方应用。常见微信、QQ登录,省去管理账户的麻烦,也不会造成用户的流失。

打开微信的官方文档,会看到网页授权一些说明。(有点摸不着头脑,主要是当时没能关联起来,微信文档每次看都那么郁闷!!!)

来了解下授权的模式,官方说的详细(这得仔细阅读下):
关于网页授权的两种scope的区别说明

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

<> <> <> <>

实现思路

 



 

101637543016285

 

* 在微信公众号中设定网页授权域名;
* 用户打开登录页,进入网页授权页面url;
* 微信询问用户是否同意授权给微信公众号;(snsapi_base 静默授权无此步骤,并且此模式snsapi_userinfo需关注微信公众号)
* 用户同意授权(snsapi_base静默授权直接默认同意)
* 回调code,带code参数请求微信,换取网页授权access_token(此步获取openid,微信用户的唯一标识)
*
通过【获取用户基本信息】接口,参数access_token(和上面的不同,普通的access_token)和openid,判断是否绑定微信公众号,未绑定,跳转绑定页。(此步骤snsapi_base无需,当然这个步骤可以去掉,视情况而定,像我项目就有这要求,唉)
* 将openid带入登录页,商户服务器检测当前openid是否存在数据库用户记录中
* 不存在openid记录,登录用户,商户服务器将openid存入用户表中;(存在openid记录跳过此步骤)
* openid记录存在,则拉取用户信息,存入会话,完成登录;
以上是本人实际项目中的做法,除此之外我们的接口做了签名验证,有一定安全性。仅供参考,总觉得有更好的思路,希望大家指出。

话不多说,贴出实现逻辑代码:
商户端登录
public function actionLogin() { session_start(); $_SESSION['openid'] = empty(
$_SESSION['openid'] ) ? $_GET['openid'] : $_SESSION['openid'];
if(!$_GET['openid']){
$this->apiget('WeixinServer/ScopeRedirectUriAppid',array('sign'=>$this->sign,'sourcetype'=>7,'data'
=> ''));
header("Location:".Yii::app()->params['apipath'].'/WeixinServer/ScopeRedirectUriAppid?sign='.$this->sign.'&sourcetype=7'
); exit; } if($_SESSION['openid']){ //判断绑定公众号 $jssdk = new JSSDK();
$access_token = $jssdk->getAccessToken(); $url =
"https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$_SESSION['openid']}&lang=zh_CN";
$UserInfo = json_decode($this->dogetCurl($url),1); if(
empty($UserInfo['subscribe']) ){ //跳转关注页
header("Location:https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzA3Mzg2MjMyNw==&scene=124#wechat_redirect"
); die; } //微信登录 $WeixinLogin = $this->apiget('WeixinServer/WeixinLogin',
array('sign'=>$this->sign,'sourcetype'=>7,'openid'=>$_SESSION['openid'])); if(
$WeixinLogin['error']==1){ return $this->render($this->act); }
$this->WeinxinLogin($WeixinLogin); die; } $this->render($this->act); } ##微信授权成功
写入session,跳转首页 public function WeinxinLogin( $data=array() ){ $_SESSION['user']
= $data['data']; $this->redirect('/index/index'); } ##curl请求 public function
apiget($path, $param=array()){ $url = Yii::app()->params['apipath'].$path;
$curl = curl_init(); curl_setopt($curl, CURLOPT_USERAGENT, '3'); //User-Agent
curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $param); curl_setopt($curl,
CURLOPT_RETURNTRANSFER, 1); $return = curl_exec($curl); curl_close($curl); $j =
json_decode($return, 1); return $return; }
WeixinServer 处理微信授权
<?php class WeixinServerController extends Controller { public function
__construct() { //todo 验证签名 } public function error($msg){
header("Content-type: application/json"); $o['time'] = "".time(); $o['error'] =
'1'; $o['errorMsg'] = $msg; echo json_encode($o);die; } public function
Login($user=array()){ //todo 获取用户信息 }
##=====================================微信授权========================================##
##微信授权登录 public function actionWeixinLogin(){ if( empty($_POST['openid']) )
$this->error('openid为空'); //todo 通过openid查询用户 $user = DB::get_one("SELECT *
FROM {{user}} WHERE openid='{$_POST['openid']}' "); if( !$user
)$this->error('openid不存在'); $userinfo = $this->Login($user['uid']);
$this->out($userinfo); } ##微信授权 获取code public function
actionScopeRedirectUriAppid( ){ $APPID = "XXXXXXXXXXXX"; $REDIRECT_URI=
'http://'.$_SERVER['HTTP_HOST'].'/WeixinServer/WeixinOpenidCallback';
$scope='snsapi_base'; //手动授权snsapi_userinfo 静默授权snsapi_base
$url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$APPID.'&redirect_uri='.urlencode($REDIRECT_URI).'&response_type=code&scope='.$scope.'&state=scene#wechat_redirect';
header("Location:{$url}" ); } ##微信回调,获取openid public function
actionWeixinOpenidCallback(){ if( $code= Yii::app()->request->getParam('code')
){ $APPID = "XXXXXXXXXXXX"; $SECRET = "XXXXXXXXXXXX"; $url =
"https://api.weixin.qq.com/sns/oauth2/access_token?appid={$APPID}&secret={$SECRET}&code={$code}&grant_type=authorization_code";
$UserOpenidArr = json_decode($this->dogetCurl($url),1); if(
empty($UserOpenidArr ['openid']) ) { print_r( $UserOpenidArr ); die(); }
header("Location:http://XXXXXXXX/index/login?openid={$UserOpenidArr
['openid']}" ); }else{ die("微信授权失败"); } } public function dogetCurl( $url ='' )
{ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch,
CURLOPT_HEADER, 0); curl_setopt ( $ch, CURLOPT_HTTPHEADER, array( 'Connection:
Keep-Alive', 'Keep-Alive: 300' )); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch); curl_close ( $ch ); return $data; } }
代码结合实现思路,大致思想清楚就好实现了,希望对大家有帮助(代码写的烂,将就看吧)。

<> <> <> <>

—— 路漫漫其修远兮 吾将上下而求索

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信