vue微信网页授权最终解决方案

vue微信网页授权,基于vue-cli3.0+webpack 4+vant ui + sass+ rem适配方案+axios,开发的微信授权方案。项目地址:vue-wechat-auth 又又又一次来写微信网页授权,一年前写过的 [vue 微信授权解决方案]。 参考了[vue-wechat-login],思路有些不同,本文基于进入所有页面都必须先授权的操作。 与之前写的授权不同之处这次的逻辑全部在router的beforeEach进行,相较更加简洁明。之前是在一个中间页author.vue中,加上微信授权要跳转很多次 在这里你能找到微信网页授权前端解决方案,官方文档如何使用Natapp(ngrok)进行微信本地开发调试,官方文档如何配置微信开发测试账号关于测试账号和本地开发设置由于文章过长这里[微信测试账号和本地开发调试]记得回来哦~ 微信网页授权都设置好了那就开始微信网页开发第一步也是最重要的一步,微信网页授权 关于授权你首先要清楚的是,服务端要用到的是微信openid还是微信unionid,这两者的区别是,如果你要的是unionid,那么你需要在[微信开放平台]去绑定测试账号。测试号的appId和appsecret在微信公众平台的测试号里找。微信公众号后台->开发者工具->公众平台测试帐号->进入 如果你不需要unionid,那这个你就可以省略, 如果服务端是需要unionid的那不绑定的话授权会把报错的。记得问一下服务端开发人员哦。 开发首先我们看下微信授权的流程图,关于微信网页授权 前端需要做的是 第一步:用户同意授权,获取code,拼接微信授权地址,redirect_uri就是你的当前地址,关于appid有些人是通过接口获取的,我这里就直接写在项目全局变量里了VUE_APP_WECHAT_APPID,用户授权成功后微信会携带code和status跳回来 https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appid}&redirect_uri=${this.redirect_uri}&response_type=code&scope=${this.scope}&state=${this.state}#wechat_redirect第二步,访问登录接口,将code传给服务端,小哥哥进行一系列的操作,通过code换取网页授权access_token,拉取用户信息(需scope为 snsapi_userinfo),返回是否登录成功,成功后返回用户信息和登录令牌 token 在permission.js中路由拦截进行这一系列操作,代码注释很详细了 permission.js import router from './router'import store from './store'import getPageTitle from '@/utils/get-page-title'import wechatAuth from './plugins/wechatAuth' // 微信登录插件const qs = require('qs')router.beforeEach((to, from, next) => { const loginStatus = Number(store.getters.loginStatus) console.log('loginStatus=' + loginStatus) console.log('token=' + store.getters.token) // 页面标题 document.title = getPageTitle(to.meta.title) if (loginStatus === 0) { // 微信未授权登录跳转到授权登录页面 const url = window.location.href // 解决重复登录url添加重复的code与state问题 const parseUrl = qs.parse(url.split('?')[1]) let loginUrl if (parseUrl.code && parseUrl.state) { delete parseUrl.code delete parseUrl.state loginUrl = `${url.split('?')[0]}?${qs.stringify(parseUrl)}` } else { loginUrl = url } // 设置微信授权回调地址 wechatAuth.redirect_uri = loginUrl // 无论拒绝还是授权都设置成1 store.dispatch('user/setLoginStatus', 1) // 跳转到微信授权页面 window.location.href = wechatAuth.authUrl } else if (loginStatus === 1) { // 用户已授权,获取code try { // 通过回调链接设置code status wechatAuth.returnFromWechat(to.fullPath) } catch (err) { // 失败,设置状态未登录,刷新页面 store.dispatch('user/setLoginStatus', 0) location.reload() } // 同意授权 to.fullPath 携带code参数,拒绝授权没有code参数 const code = wechatAuth.code if (code) { // 拿到code 访问服务端的登录接口 store .dispatch('user/loginWechatAuth', code) .then(res => { // 成功设置已登录状态 store.dispatch('user/setLoginStatus', 2) next() }) .catch(() => { // 失败,设置状态未登录,刷新页面 store.dispatch('user/setLoginStatus', 0) location.reload() }) } else { store.dispatch('user/setLoginStatus', 0) location.reload() } } else { // 已登录直接进入 next() }})登录成功后存用户信息,token。访问所有的接口的时候都会在header携带token,如果token失效了,服务端会返回401,做退出操作,删除登录状态,用户信息,token,刷新页面重新进入。 ...

June 15, 2019 · 2 min · jiezi

laravel前后端分离获取微信授权结合laravelwechat

1、开始之前,请一定仔细阅读微信开发者文档文档中,总共写了几个步骤: 1、通过appId和需要跳转的路由去请求授权2、授权之后跳转路由中返回的code 注:前端只需要知道这两个步骤3、根据code获取access_token4、根据access_token获取用户信息(snsapi_userinfo授权)2、前端发起授权请求。这一步需要前端拼凑路由,并且将页面跳转到拼凑路由,路由规则如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公众appId号&redirect_uri=你的回调路由&response_type=code&scope=你选择的方式&state=STATE#wechat_redirect注 授权方式可选择为snsapi_userinfo或者snsapi_base,差别请看文档跳转之后授权页面如下(开发者工具效果) 3、点击同意之后,会根据你之前拼凑的回调路由返回code,如下:http://test.***.com/index?code=021Azdiu12zdXd05kkju1ZYkiu1AzdiR&state=1 4、将路由中的code直接传递给后端,让后端做获取用户信息的系列的逻辑处理。注:如下是laravel中间件中处理方式,session只用于这次请求,也可以将用户的微信信息放在request中到controller进行逻辑处理,看个人喜好 public function handle($request, Closure $next, $scopes = null) { $wechatCacheKey = 'wechat.oauth_user.default'; if (config("qa.mock_user") == 1){ $user = new SocialiteUser(config('wechat.mock_user')); } else { $code = $request->get("code", ""); if ($code === ""){ $appId = $this->config["app_id"]; return Response::toJson(["aid" => $appId], "请重新获取授权CODE!",10006); } // 开始拉取用户信息 $app = Factory::officialAccount($this->config); $user = $app->oauth->user(); } session([$wechatCacheKey => $user]); } return $next($request); }注:这个例子只是写了授权的逻辑,token相关验证我已经做了剔除 坑点:1、vue的路由会将code拼接在url和#之间,如www.****.com/?code=XXXXX/#/index,这个code需要单独处理

June 14, 2019 · 1 min · jiezi

微信授权流程探索

微信授权流程前言最近项目接触到微信h5页面开发,对于一个对微信只接触过小程序的小白来说,整个流程都是懵懵逼逼的。对微信授权流程之前只是有个大致的了解,自己并不是很清楚其中的通信,刚好有机会跟小组长一起去探讨这个问题,梳理了一下基于我们项目的微信授权逻辑。由上顺序图可以看到用户进入微信h5页面,调用微信授权接口,返回用户授权界面,微信授权接口如下:https://open.weixin.qq.com/co…这里有两个参数比较注意的是:redirect_uri和state,redirect_uri主要是存放后台的接口访问地址,state主要存放微信授权成功后需要跳转的页面地址。与整个微信授权流程紧密相关,请先记住了!!记不住记得回来回忆一下若提示该链接无法访问,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。微信返回参数错误的原因一般有两种:一是在微信公众平台没有配置相应的参数;二是前端配置的接口参数与公众平台不一致。具体参数说明参数是否必须说明appid是公众号的唯一标识redirect_uri是授权后重定向的回调链接地址, 需要使用 urlEncode 对链接进行处理response_type是返回类型,填写codescope是应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )state否重定向后会带上state参数,传递什么返回什么wechat_redirect是无论直接打开还是做页面302重定向时候,必须带此参数用户同意授权之后,即向微信发送同意授权请求,微信返回一个302的重定向数据包(redirect_uri+code+state),客户端浏览器重定向redirect_uri+code。此处相当于向后台请求了一次接口,后台存取相关请求信息并通过获取的code换取网页授权access_token(后端)由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。后台用access_token换取用户信息之后,向客户端返回一个重定向数据包(state+token),客户端浏览器根据state进行重定向并在该页面存取相关token信息https://api.weixin.qq.com/sns…此时客户端已经获取token信息,根据token信息可以向后台请求接口获取相关信息。注意调取微信授权接口时根据scope的不同有两种授权方式:snsapi_base是用来获取用户的openid,不需要用户手动授权。而snsapi_userinfo是用来获取用户基本信息,需要用户手动授权。检验授权凭证(access_token)是否有效请求方法:http:GET(请使用https协议) https://api.weixin.qq.com/sns…参数说明access_token网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同openid用户的唯一标识

February 18, 2019 · 1 min · jiezi

PHP实现微信获取用户基本信息(openid、头像、昵称)

<?phperror_reporting(1);header(‘Content-type:text/html; Charset=utf-8’);/* 配置开始 /$appid = ‘’; //微信公众平台->开发->基本配置->AppID$appKey = ‘’; //微信公众平台->开发->基本配置->AppSecret/ 配置结束 ///①、获取用户openid$wxPay = new WxService($appid,$appKey);$data = $wxPay->GetOpenid(); //获取openidif(!$data[‘openid’]) exit(‘获取openid失败’);//②、获取用户信息$user = $wxPay->getUserInfo($data[‘openid’],$data[‘access_token’]);?><!DOCTYPE html><html lang=“en”><head> <meta charset=“UTF-8”> <meta name=“renderer” content=“webkit” /> <meta http-equiv=“X-UA-Compatible” content=“IE=edge,Chrome=1” /> <meta name=“viewport” content=“width=device-width, initial-scale=1.0, maximum-scale=1.0” /> <title>微信获取用户信息demo</title> <link href=“https://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel=“stylesheet”> <script src=“https://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script></head><body><div class=“container”> <div class=“row”> <h1>你的基本信息如下:</h1> <table class=“table table-bordered”> <tr> <td>openid</td> <td><?=$user[‘openid’]?></td> </tr> <tr> <td>unionid</td> <td><?=$user[‘unionid’]?></td> </tr> <tr> <td>昵称</td> <td><?=$user[’nickname’]?></td> </tr> <tr> <td>头像</td> <td><img src="<?=$user[‘headimgurl’]?>” style=“width: 100px;” alt=”"></td> </tr> <tr> <td>性别</td> <td><?php switch (strtoupper($user[‘sex’])){ case 1: echo ‘男性’; break; case 2: echo ‘女性’; break; default: echo ‘未知’; break; } ?></td> </tr> <tr> <td>省份 / 城市</td> <td><?=$user[‘province’].’ / ‘.$user[‘city’]?></td> </tr> <tr> <td>language</td> <td><?=$user[’language’]?></td> </tr> </table> </div></div></body></html><?phpclass WxService{ protected $appid; protected $appKey; public $data = null; public function __construct($appid, $appKey) { $this->appid = $appid; //微信支付申请对应的公众号的APPID $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key } /* * 通过跳转获取用户的openid,跳转流程如下: * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code * * @return 用户的openid / public function GetOpenid() { //通过code获得openid if (!isset($_GET[‘code’])){ //触发微信返回code码 $baseUrl = $this->getCurrentUrl(); $url = $this->__CreateOauthUrlForCode($baseUrl); Header(“Location: $url”); exit(); } else { //获取code码,以获取openid $code = $_GET[‘code’]; $openid = $this->getOpenidFromMp($code); return $openid; } } public function getCurrentUrl() { $scheme = $_SERVER[‘HTTPS’]==‘on’ ? ‘https://’ : ‘http://’; $uri = $_SERVER[‘PHP_SELF’].$_SERVER[‘QUERY_STRING’]; if($_SERVER[‘REQUEST_URI’]) $uri = $_SERVER[‘REQUEST_URI’]; $baseUrl = urlencode($scheme.$_SERVER[‘HTTP_HOST’].$uri); return $baseUrl; } /* * 通过code从工作平台获取openid机器access_token * @param string $code 微信跳转回来带上的code * @return openid / public function GetOpenidFromMp($code) { $url = $this->__CreateOauthUrlForOpenid($code); $res = self::curlGet($url); $data = json_decode($res,true); $this->data = $data; return $data; } /* * 构造获取open和access_toke的url地址 * @param string $code,微信跳转带回的code * @return 请求的url / private function __CreateOauthUrlForOpenid($code) { $urlObj[“appid”] = $this->appid; $urlObj[“secret”] = $this->appKey; $urlObj[“code”] = $code; $urlObj[“grant_type”] = “authorization_code”; $bizString = $this->ToUrlParams($urlObj); return “https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } /* * 构造获取code的url连接 * @param string $redirectUrl 微信服务器回跳的url,需要url编码 * @return 返回构造好的url / private function __CreateOauthUrlForCode($redirectUrl) { $urlObj[“appid”] = $this->appid; $urlObj[“redirect_uri”] = “$redirectUrl”; $urlObj[“response_type”] = “code”; $urlObj[“scope”] = “snsapi_userinfo”; $urlObj[“state”] = “STATE”; $bizString = $this->ToUrlParams($urlObj); return “https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; } /* * 拼接签名字符串 * @param array $urlObj * @return 返回已经拼接好的字符串 / private function ToUrlParams($urlObj) { $buff = “”; foreach ($urlObj as $k => $v) { if($k != “sign”) $buff .= $k . “=” . $v . “&”; } $buff = trim($buff, “&”); return $buff; } /* * 获取用户信息 * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid * @return string */ public function getUserInfo($openid,$access_token) { $response = self::curlGet(‘https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid='.$openid.'&lang=zh_CN'); return json_decode($response,true); } public static function curlGet($url = ‘’, $options = array()) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function curlPost($url = ‘’, $postData = ‘’, $options = array()) { if (is_array($postData)) { $postData = http_build_query($postData); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; }}DEMO:http://likeyunba.comTANKING2019-1-21 ...

January 21, 2019 · 3 min · jiezi