2019独角兽企业重金招聘Python工程师标准>>>

鉴于美国国防部网站 http://sxsxssx.com 是用yii开发的,自然的我新建了一个wechat模块,域名 http://sxsxssx.com/wechat 是微信端部分。

对于在微信端登陆的每个会员,都自动生成一个新会员,下次登陆直接使用。

开始改造

鉴于这样一个小站,我决定直接改造他的user表。老的是

大家知道微信有个 open_id 代表每个公众号的会员,每个人针对于每个公众号都是不一样的,于是我为user表增加了一个 open_id 字段,用来标记会员。对于 open_id 为 NULL 时,代表不来自于微信端。

关于 open_id 长度问题,迄今为止微信也没有给出此字段应该多长,经多方查证和统计,一般在28、29、30之间徘徊,所以针对此字段,设置为32位的 varchar 应该是没啥问题的,事实上北哥也一直这样干的。

@@nai8@@

微信网页授权

接下来我们要研究当一个人通过微信浏览器打开客户网站的时候,如何识别身份那?看微信网页授权文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141217&token=&lang=zh_CN

先读一遍文档再往下看。

**简单的说:**如果用户在微信浏览器中访问第三方网页,可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。

换句话说,就是我们有机会获得当前正在浏览网页的会员基本信息,那么思路就来了,草草的画个流程图。

大体内容是这样的,我将微信授权后的open_id存到session中,下次访问页面时,如果session中有open_id则根据它从数据库中去对应会员信息然后继续访问页面,如果session中open_id不存在,则进入微信授权获得open_id,然后看看数据库中是否有对应会员,如果有则拿出来然后将open_id再存到session,如果没有则新建一个含open_id的会员,然后存session。

所以其实重点就落在了获取open_id上,通过微信的web授权文档,我知道它是一定拿的到的,我先把上面流程图的代码实现下。

考虑到对于wechat模块,所有页面我都需要在web授权下去访问,因此对于wechat/controllers 我抽象出一个父类,父类完成微信的授权和获取当前访问的微信会员信息等职责。

构造WxBase

我决定为WxBase增加一个叫做$wxLogin的变量,存放当前获取的微信会员。代码如下

namespace app\modules\wechat\controllers;use Yii;
use yii\web\Controller;
class WxBase extends Controller {public $wxLogin = null;public function init(){parent::init();$this->initWxAuth(); // 获取登陆会员信息}protected function initWxAuth(){$session = Yii::$app->session;$wxOpenId = $session["wx_open_id"];if(empty($wxOpenId)){// todo 去做授权机制die("我要去授权,别拦我。");}$user = User::find()->where(['open_id'=>$wxOpenId])->one();$this->wxLogin = $user;}
}

上面的逻辑其实是模拟了用户 登陆 / 注册 的思路,只不过这种 登陆 / 注册 是微信web授权授权而已。

好,接下来我们主攻如何通过微信web授权完成 open_id 的获取以及会员初始化的问题。

真正核心的东西来了

通过对文档的阅读,我明白需要做几项配置。

  • 先到公众平台官网修改授权回调域名。
  • 我们需要知道公众号的 AppID 和 AppSecret

好在我们的上一篇让大家准备了 微信公众平台接口测试帐号 ,足以满足。

存放 AppID 和 AppSecret

考虑到 AppID 和 AppSecret 属于配置项,且将来可能具有更多的配置,因此我在程序的 config/params.php 中 新建了一个数组key用于存放所有的微信相关参数。

return ['adminEmail' => 'admin@example.com','wechat'=>['appId'=>'appId-Key','appSecret'=>'appSecret-Key',]
];

配置回调域名

对于测试号 我们可以通过 体验接口权限表 的 网页授权获取用户基本信息 找到它

对于正式环境 需要在“开发 -接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中。

正式服务器需要验证服务器可靠性,下载一个txt文件到你服务器根目录然后检查通过才能提交。有时候微信服务器可能抽风,即使你按步骤做了,通过浏览器也能访问上传的txt文件内容,但是仍然不通过,一般过会再试就没事了。

natapp映射本地

然后我通过natapp映射远程域名到我本地目录,一切就绪了。

我映射的域名为 http://abei.natapp2.cc 到 本地。

好,现在我用微信开发者工具 访问 http://abei.natapp2.cc/index.php?r=wechat

我要去授权,别拦我。,哈哈,要的就是它。好,我开始写授权。

先看下微信给我们的步骤

  • 第一步:用户同意授权,获取code
  • 第二步:通过code换取网页授权access_token
  • 第三步:刷新access_token(如果需要)
  • 第四步:拉取用户信息(需scope为 snsapi_userinfo)
  • 附:检验授权凭证(access_token)是否有效

用户同意授权,获取code

namespace app\modules\wechat\controllers;use Yii;
use yii\web\Controller;
class WxBase extends Controller {public $wxLogin = null;......protected function initWxAuth(){$session = Yii::$app->session;$wxOpenId = $session["wx_open_id"];if(empty($wxOpenId)){// todo 去做授权机制$this->wxRedirectOauth2();}$user = User::find()->where(['open_id'=>$wxOpenId])->one();$this->wxLogin = $user;}protected function wxRedirectOauth2(){$url = Yii::$app->request->getUrl();$conf = Yii::$app->params['wechat'];$redirect_url = Url::to(['/wechat/default/oauth2','url'=>$url],true);$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$conf['appId']."&redirect_uri=".urlencode($redirect_url)."&response_type=code&scope=snsapi_userinfo&state=#wechat_redirect";header('Location:'.$url);exit();}
}

上面的代码我是想获得用户授权,并且得到code。我们使用index.php?r=wechat/default/oauth2 作为授权后重定向的回调链接地址。为了教学方便,我采用了snsapi_userinfo作用域,它会弹出一个授权对话框。

少言,看效果。

在逻辑上看,用户点击确认登陆后,微信会引导访问一个叫做 http://abei.natapp2.cc/index.php?r=wechat/default/oauth2&url=xxxx 的页面。

但是这样存在一个问题,原则上这个地址是用来获取code的,但是因为我们做了一个父类WxBase,并且针对每一个 wechat 模块下的action,我们都做了 initWxAuth 工作,那就会导致当yii访问 wechat/default/oauth2 时候发现 Session 中不存在 wx_open_id 不存在,然后继续访问 我们刚定义的 wxRedirectOauth2函数,形成死循环,页面无限刷新。

因此我们需要将 wechat/default/oauth2 这个action排除在 initWxAuth 之外,所以我们在授权页面 确认登陆 前再对代码进行一点小修改。

namespace app\modules\wechat\controllers;use Yii;
use yii\web\Controller;
class WxBase extends Controller {public $wxLogin = null;public $notAuths = ['wechat/default/oauth2'];public function init(){parent::init();if(in_array(Yii::$app->requestedRoute,$this->notAuths) == false){$this->initWxAuth();}}......
}

考虑程序扩展性,我将不需要授权的路由放到了一个数组中(你甚至可将其作为参数配置,那样更好。)

顺便我们写一下 wechat/default/oauth2

namespace app\modules\wechat\controllers;class DefaultController extends WxBase {/*** Renders the index view for the module* @return string*/public function actionIndex(){return $this->render('index');}public function actionOauth2(){echo "我是oauth2";}
}

好,再一次看效果。

很好,一起都在控制中,的确微信引导我们来到了 wechat/default/oauth2 ,并且我们来看看 这个url

http://abei.natapp2.cc/index.php?r=wechat%2Fdefault%2Foauth2&url=%2Findex.php%3Fr%3Dwechat&code=051af2HX0141A02cTLJX02hJGX0af2Hw&state=

你是否发现,多了url、code、state,那么他们是什么那?

  • url 是我们的 oauth2 处理完逻辑后进入的页面,也就是我本次要访问的目标页面。
  • code 这个好,就是我要的,通过它我能得到access token,进而获取open_id等。
  • state 一个可以传递信息的字段,这里没有使用。

通过code换取网页授权access_token

接下来的好戏都有oauth2 这个action来主导,我们先去获得access_token。

namespace app\modules\wechat\controllers;class DefaultController extends WxBase {....public function actionOauth2(){//  得到Get传递过来的code 和 url$code = Yii::$app->request->get('code');$url = Yii::$app->request->get('url');$conf = Yii::$app->params['wechat'];$accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$conf['appId']}&secret={$conf['appSecret']}&code=".$code."&grant_type=authorization_code";$result = $this->HttpRequest($accessTokenUrl);echo $result;}/*** 使用curl获取url返回结果。* @param $url* @return mixed*/public function HttpRequest($url) {$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);curl_setopt($ch, CURLOPT_TIMEOUT, 2);$result = curl_exec($ch);return $result;}
}

根据文档我将appId、appSecret和这次的code传递给微信服务器以请求授权access_token,为了看的方便,我将微信返回的结果直接打印下来。

这里的 HttpRequest 是通过curl在php发起的GET 请求,它当前可以使用,但是如果用于生产环境,请再优化。

看下微信返回的。

结果让人欣慰,微信给我返回了 access_token、openid、expires_in 等等。参数的解释如下图

对于unionid,必须将公众号绑定到开放平台才会有,具体作用以后会有说,这里先过。

看看我们现在

我们已经得到了 openid 不是么?马上去完善代码。

namespace app\modules\wechat\controllers;class DefaultController extends WxBase {....public function actionOauth2(){//  得到Get传递过来的code 和 url$code = Yii::$app->request->get('code');$url = Yii::$app->request->get('url');$conf = Yii::$app->params['wechat'];$accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$conf['appId']}&secret={$conf['appSecret']}&code=".$code."&grant_type=authorization_code";$result = $this->HttpRequest($accessTokenUrl);$data = Json::decode($result);if($data && isset($data['errcode']) === false){$model = User::find()->where(['open_id' => $data['openid']])->one();if($model === false){$model = new User();$model->username = "wx-".rand(100000,999999);$model->password = md5('123456');$model->create_time = time();$model->open_id = $data['openid'];$model->save();}$session = \Yii::$app->session;$session['wx_open_id'] = $data['openid'];return $this->redirect($url);}}...
}

看下效果吧。

页面经过授权后进入了我们访问的目标页面,再看看数据库。

成功了~~~~

完事了么?

从代码上说,我们已经完成了上面流程图的内容,登陆页面可以对新会员进行初始化,并且可以在每个页面获得当前登陆的会员信息($this->wxLogin中),但是你也注意到了,在会员初始化的时候,username等等我们是用了随机值,而微信在授权的最后一步是允许我们通过access_token拉取用户信息的,我们实现一下。

拉取用户信息(需scope为 snsapi_userinfo)

在我的数据库设计中,username是登陆用户名,必须唯一,因此放微信信息的昵称是不合理的,下面代码只将解信息拉取过程,具体你要讲拉取的信息放到何处具体程序具体看要。

namespace app\modules\wechat\controllers;class DefaultController extends WxBase {....public function actionOauth2(){//  得到Get传递过来的code 和 url$code = Yii::$app->request->get('code');$url = Yii::$app->request->get('url');$conf = Yii::$app->params['wechat'];$accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$conf['appId']}&secret={$conf['appSecret']}&code=".$code."&grant_type=authorization_code";$result = $this->HttpRequest($accessTokenUrl);$data = Json::decode($result);if($data && isset($data['errcode']) === false){$model = User::find()->where(['open_id' => $data['openid']])->one();if($model === false){$model = new User();$model->username = "wx-".rand(100000,999999);$model->password = md5('123456');$model->create_time = time();$model->open_id = $data['openid'];$model->save();// 拉取用户信息$userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token={$data['access_token']}&openid={$data['openid']}&lang=zh_CN";$info = $this->HttpRequest($userInfoUrl);$userInfo = Json::decode($info);// todo $userInfo 是一个数组,具体放哪具体决定,可以一个表单独存放会员微信信息,也可以对user表进行扩展。}$session = \Yii::$app->session;$session['wx_open_id'] = $data['openid'];return $this->redirect($url);}}...
}

如上代码,你可以轻松获得用户信息。

最后要说的

上面的代码经阿北测试可以正常运行,但是如果生产环境还请对每个部分做下异常处理,在平时开发中,这种方式并不是我们推荐的,用一个开源库也许是我们最好的选择,本专题也会讲到用开源库easywechat实现微信端授权登陆的实现。

如果你是兄弟连成员,务必关注“开发知乎”这套视频课程,这是一个用easywechat完整且彻底实现微信接口开发的好案例。

另外你可能对本文的code、access_token等比较迷糊还是,无需忧虑,这些都是oauth2授权机制的一部分,我们会单独去讲解 oauth2,这个强大的通用于所有开放平台的授权机制。

而本篇,你能做出微信端授权就已成功。

转载于:https://my.oschina.net/u/3683692/blog/2249599

微信端自动授权登陆实现 - 无第三方库版相关推荐

  1. 微信OAuth2网页授权登陆接口

    微信OAuth2网页授权登陆接口,微信OAuth2网页授权登陆接口,在你的网站上放上可以扫码登陆,会不会吸引更多用户去注册,现在你只需要简单的配制一下就可以轻松实现,还不快点拿走,微信扫码登陆接口开发 ...

  2. php微信登录app接口开发文档,PHP微信OAuth2网页授权登陆接口

    微信OAuth2网页授权登陆接口,微信OAuth2网页授权登陆接口,在你的网站上放上可以扫码登陆,会不会吸引更多用户去注册,现在你只需要简单的配制一下就可以轻松实现,还不快点拿走,微信扫码登陆接口开发 ...

  3. 最简单的基于FFmpeg的移动端例子:Android 视频解码器-单个库版

    ===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子:A ...

  4. 关于微信小程序授权登陆之后需要在个人信息页展示信息,如微信头像,昵称这件事

    开发时使用uniapp进行开发,不过用什么开发都不重要. 在搞完微信授权登陆后,又遇到需要把用户昵称和头像展示在个人信息页的情况,在试了很多方法后,发现了便利的方法. 有想过从数据库获取数据,也想过从 ...

  5. 微信小程序授权登陆判断+证件照换底色UI设计(第三周)

    日期 工作内容 2020年8月16日 (因涉及版权问题)图片素材重新查找 2020年8月17日 图片上传 2020年8月18日 小程序授权判断完善,小程序跳转页面新架构 2020年8月19日 证件照尺 ...

  6. 微信端自动播放背景音乐

    在微信公众号里面实现背景音乐自动播放,发现使用autoplay之后只有Android端起效,苹果手机不能自定播放,解决方法如下所示: HTML: <!-- 背景音乐 --><audi ...

  7. 前后端分离项目之微信端网页授权处理

    在微信公众号中内嵌H5网页,在需要获取用户信息或者需要用到微信公众号开发相匹配的api时,需要拉取微信授权,在非前后端分离的项目中,这部分是由服务端一并完成的,在前后端分离的项目中,根据微信公众号开发 ...

  8. asp源码微信扫码授权登陆电脑版

    网站接入微信扫码登录并获取用户基本信息(完美绕过微信开放平台) 电脑版网站实现微信扫码登录,注册会员还要设密码太麻烦,会员也记不住密码,采用微信扫码登录网站更方便,会员无需设密码,用他的微信做为系统登 ...

  9. 微信小程序授权登陆,解密encryptedData出现乱码问题

    前端传过来的encryptedData 用base64_decode解密后出现乱码 解决方法: 用get方式传加密的字符串时,接收到以后,字符串里包含的"+"会被替换成" ...

最新文章

  1. 自定义堆栈(回文检测)
  2. 人工智能可能成为我们检测COVID-19最有效的方法吗?
  3. 如何提取cocos iOS应用程序APP与游戏安装包里的资源与文件
  4. SSM整合activiti框架
  5. 无限超越超级机器人nds_阿里重新定义个人电脑!仅名片大小,无限升级,不怕丢失无惧病毒,价格仅传统PC一半...
  6. 一些经典的前端文章合集地址
  7. 关于文章cisco漏洞4786
  8. 5. 用 PHP 源码操作 memcache(2)
  9. docker镜像加速器
  10. 小程序毕设作品之微信校园维修报修小程序毕业设计成品(7)中期检查报告
  11. web前端入门到实战:CSS box-sizing属性的正确用法
  12. C语言之“先有的鸡还是先有的蛋”浅谈
  13. 根据起始时间和结束时间得到期间所有的日期集合
  14. 编译akm小车底盘控制节点
  15. css 设置图片为灰色
  16. 用计算机画对称图形,人教小学美术五下《第17课电脑美术 对称图形》word教案...
  17. oracle快速生成序列号,Oracle实现自定义序列号生成
  18. Android 高德地图定位和导航
  19. 夕阳红旅游团需求规格说明书
  20. mfc异形窗口的创建

热门文章

  1. Substance PBR Guide
  2. 为什么公司宁愿 25K 重新招人,也不给你加到 20K?原因太现实……
  3. 学Python Web开发框架到什么程度可以找到开发的工作?
  4. 判断字符串中是否包含指定字符的N种方法对比
  5. 20款超酷的404错误页面(上)
  6. 谈谈我们的学习和我们的Blog
  7. 2.2 Mnist手写数据集
  8. stl之queue队列容器
  9. MYSQL等级考试考的是Linux吗,Linux命令行下快速监控mysql
  10. 怎么检测mysql查询是否慢_MySQL慢查询查找和调优测试