ThinkPHP|ThinkPHP 公众号授权微信登录

公众号微信用户登录,可以在微信上直接使用应用,无需再去下载app,减少用户的注册登录流程,优化用户体验,本文是讲解微信公众号授权登录。
ThinkPHP|ThinkPHP 公众号授权微信登录
文章图片
公众号授权流程图
这是一张在网上找到的授权登录流程图,不知道是多久之前的了,其实这张图只是大致授权流程,并不详细。
  • 授权登录流程:
  1. 后台携带参数grant_type为client_credential、appid、secret用get方法请求“https://api.weixin.qq.com/cgi-bin/token”,获取到access_token,返回内容如下:

    ThinkPHP|ThinkPHP 公众号授权微信登录
    文章图片
    access_token
    然后使用access_token、type为jsapi,用get方法请求“https://api.weixin.qq.com/cgi-bin/ticket/getticket”,获取到ticket,然后将其中的ticket,和随机生成一串字符串,时间戳,还有最后需要回调的url,对应的几个参数进行字母表顺序排序后,进行sha1加密,然后将对应的参数返回给前端。
  2. 【ThinkPHP|ThinkPHP 公众号授权微信登录】在微信公众号的网站应用前端,引入到对应的微信sdk,并且需要配置到以下的配置项,代码块:
wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名 jsApiList: ['openLocation'] // 必填,需要使用的JS接口列表 这里填写需要用到的微信api openlocation为使用微信内置地图查看位置接口 });

上面代码块的配置项,需要我们php后端来返回结果内容,所以需要编写接口来获取签名,随机字符串等内容,jsApiList是微信公众号所具有的权限(数组)。
  1. 公众号前端应用获取到code,用code、appid、secret、grant_type四个参数用get方法请求到“https://api.weixin.qq.com/sns/oauth2/access_token”,用来获取到access_token,其中grant_type参数为authorization_code,返回内容格式如下。

    ThinkPHP|ThinkPHP 公众号授权微信登录
    文章图片
    access_token返回结果
  2. 利用第一步获取到的access_token和openid,连同lang为zh-cn请求“https://api.weixin.qq.com/sns/userinfo”,可以获取到对应用户的信息,返回用户信息格式如下。

    ThinkPHP|ThinkPHP 公众号授权微信登录
    文章图片
    用户信息
ThinkPHP6代码块:
  • WeChat.php
namespace app\models\operation; use GuzzleHttp\Client; class WeChatTool{ protected $config; public function __construct() { $this->config = config('wechat'); } // 属于公众号调起登录方法/** * 获取access-token(基础类) * @return bool|string */ public function get_access_token(){ $result = $this->start_get_request($this->config['get_access_token_url'],[ 'grant_type'=>'client_credential', 'appid'=>$this->config['open_app_id'], 'secret'=>$this->config['open_app_secret'] ]); if(false == $result){ return false; } return $result; }/** * 获取到jsTicket * @param $access_token * @return bool|string */ public function get_js_ticket($access_token){ $result = $this->start_get_request($this->config['get_js_ticket_url'],[ 'access_token'=>$access_token, 'type'=>'jsapi' ]); if(false == $result){ return false; } return $result; }/** * 获取到access_token(公众号使用) * @return bool|string */ public function get_open_access_token($code){ $result = $this->start_get_request($this->config['get_token_url'],[ 'appid'=>$this->config['open_app_id'], 'secret'=>$this->config['open_app_secret'], 'code'=>$code, 'grant_type'=>'authorization_code' ]); if(false == $result){ return false; } return $result; }/** * 获取用户信息 * @param $access_token 上一步获取access_token * @param $openid openid * @param $lang 语言 * @return bool|string */ public function get_open_user_info($access_token,$openid){ $result = $this->start_get_request($this->config['get_user_info_url'],[ 'access_token'=>$access_token, 'openid'=>$openid, 'lang'=>'zh_CN' ]); if(false == $result){ return false; } return $result; }/** * 获取到签名配置 * @param $ticket * @return array */ public function get_sign($ticket,$url,$jsApilist){ $timeStamp = time(); $nonceStr = $this->createNonceStr(); $tempStr = "jsapi_ticket=".$ticket."&noncestr=".$nonceStr."×tamp=".$timeStamp."&url=".$url; $signature = sha1($tempStr); $signPackage = array ( "debug"=>false, "appId" => $this->config['open_app_id'], "nonceStr" => $nonceStr, "timestamp" => $timeStamp, "signature" => $signature, "jsApiList" => $jsApilist ); return $signPackage; }// 工具类方法 /** * 发起Get请求并且返回结果 * @param $uri 请求地址 * @param $query 请求参数 * @return string */ public function start_get_request($uri,$query){ $body = (new Client())->request('GET',$uri,[ 'query'=>$query, 'timeout'=>3.14 ]); if($body->getStatusCode()!=200){ return false; } return json_decode($body->getBody(),true,512,JSON_BIGINT_AS_STRING); }/** * 获取到随机字符串 * @param int $length * @return string */ public function createNonceStr($length = 16) { $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $str = ""; for($i = 0; $i < $length; $i ++) { $str .= substr ( $chars, mt_rand ( 0, strlen ( $chars ) - 1 ), 1 ); } return $str; } }

  • config/wechat.php
'wx8a0cd86933b7****', 'open_app_secret'=>'2abdb7158887aa4cedf2f61e34eb****', 'get_access_token_url'=>'https://api.weixin.qq.com/cgi-bin/token', // 获取accesstoken 'get_js_ticket_url'=>'https://api.weixin.qq.com/cgi-bin/ticket/getticket', // 获取到ticket 'get_code_url'=>'https://open.weixin.qq.com/connect/oauth2/authorize', // 获取code ];

  • WeChatController.php
param('code'))){ return app('json')->fail('请传入code'); } $weChat = new WeChatTool(); $access_token = $weChat->get_open_access_token($request->param('code')); if($access_token == false || isset($access_token['errcode'])){ return app('json')->fail('获取access_token失败,请重试'); } $wechat_user = $weChat->get_open_user_info($access_token['access_token'],$access_token['openid']); if($wechat_user == false || isset($wechat_user['errcode'])){ return app('json')->fail('获取用户信息失败'); } } /** * 微信获取到jssdk配置 * @return mixed */ public function sdk_config(Request $request){ $weChat = new WeChatTool(); $accesstoken = $weChat->get_access_token(); if($accesstoken!=false){ $ticket = $weChat->get_js_ticket($accesstoken['access_token']); if($ticket!=false){ $list = explode(',',$request->param('jsApiList')); $result = $weChat->get_sign($ticket['ticket'],$request->param('url'),$list); return $result!=false?app('json')->success('获取成功',$result):app('json')->fail('获取失败'); } return app('json')->fail('获取失败'); } return app('json')->fail('获取失败'); } }

    推荐阅读