之前我没有做过微信开发之类,今天接触到了,来记录一下自己所理解的一些逻辑,首先,我画了一个草图,模拟逻辑.(示例代码在末尾)
官方文档https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
配合着开发文档看,开发文档写的非常详细的了。我这边记录学习,我我也把我看文档的一些逻辑分享出来:
一、关于网页授权回调域名的说明(节选了主要的部分,详细部分请查看官方文档)。
1. 在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;
2.授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面,例:http://www.qq.com/music.html、http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。
二、关于网页授权的两种scope的区别说明
1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。
三、关于网页授权access_token和普通access_token的区别
1、微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
2、其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。
四、关于UnionID机制
1、请注意,网页授权获取用户基本信息也遵循UnionID机制。即如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。
2、UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。
五、关于特殊场景下的静默授权
1、上面已经提到,对于以snsapi_base为scope的网页授权,就静默授权的,用户无感知;
2、对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。
具体而言,网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code
2、通过code换取网页授权access_token(与基础支持中的access_token不同)
3、如果需要,开发者可以刷新网页授权access_token,避免过期
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
接下来,我们来看具体的步骤:
就像我第一幅图中说的,weixin()方法中判断session中是否存在openid,如果没有存在,就去访问授权页面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
尤其注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问
尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。
参数说明:
参数 |
是否必须 |
说明 |
appid |
是 |
公众号的唯一标识 |
redirect_uri |
是 |
授权后重定向的回调链接地 址, 请使用 urlEncode 对链接进 行处理 |
response_type |
是 |
返回类型,请填写code |
scope |
是 |
应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 ) |
state |
否 |
重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect |
是 |
无论直接打开还是做页面302重定向时候,必须带此参数 |
如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE
这里的redirect_url 为你在访问授权页面链接中的redirect_url参数。后面带着code,你可以使用get方法得到。
code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
错误返回码说明如下:
返回码 |
说明 |
10003 |
redirect_uri域名与后台配置不一致 |
10004 |
此公众号被封禁 |
10005 |
此公众号并没有这些scope的权限 |
10006 |
必须关注此测试号 |
10009 |
操作太频繁了,请稍后重试 |
10010 |
scope不能为空 |
10011 |
redirect_uri不能为空 |
10012 |
appid不能为空 |
10013 |
state不能为空 |
10015 |
公众号未授权第三方平台,请检查授权状态 |
10016 |
不支持微信开放平台的Appid,请使用公众号Appid |
网页授权之后,回调到你的回调地址并带参数code,在我第一幅图中,即为callback()方法,接下来的步骤就在这个方法中实现就可以了,那我们直接先获取参数code,然后再请求获取access_token
首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
请求方法
获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 |
是否必须 |
说明 |
appid |
是 |
公众号的唯一标识 |
secret |
是 |
公众号的appsecret |
code |
是 |
填写第一步获取的code参数 |
grant_type |
是 |
填写为authorization_code |
返回说明
正确时返回的JSON数据包如下:
{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }
参数 |
描述 |
access_token |
网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 |
expires_in |
access_token接口调用凭证超时时间,单位(秒) |
refresh_token |
用户刷新access_token |
openid |
用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID |
scope |
用户授权的作用域,使用逗号(,)分隔 |
错误时微信会返回JSON数据包如下(示例为Code无效错误):
{"errcode":40029,"errmsg":"invalid code"}
注:官方文档第三步为刷新access_token,因为他会过期,但是我们现在学习就不必用了,你可以先在官方文档上了解一下,写的也比较详细的了,今后有需要可以用上。
现在我们获取到了access_token,如何来获取用户的信息呢,当然还是请求地址啦!
请求方法
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明
参数 |
描述 |
access_token |
网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 |
openid |
用户的唯一标识 |
lang |
返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 |
返回说明
正确时返回的JSON数据包如下:
{ "openid":" OPENID",
" nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
参数 |
描述 |
openid |
用户的唯一标识 |
nickname |
用户昵称 |
sex |
用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 |
province |
用户个人资料填写的省份 |
city |
普通用户个人资料填写的城市 |
country |
国家,如中国为CN |
headimgurl |
用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 |
privilege |
用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) |
unionid |
只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 |
错误时微信会返回JSON数据包如下(示例为openid无效):
{"errcode":40003,"errmsg":" invalid openid "}
好了,获取到用户信息后,我们就把自己需要的信息存入到session中,这样,weixin()方法中判断的时候就会有信息啦,存入session后跳转到weixin()方法。现在session中有了openid,就不会在请求授权页面啦,直接获取session中的nickname然后输出到页面就可以啦!微信授权就到此就结束了。
还有需要注意的是,微信授权都是发请求,获取参数,但是,我们不能保证每次请求都能成功的。微信返回的数据不论成功还是失败,都是json数据的,所以,这个必须要注意的呀,实际开发中必须要记住的。
下面附上我的代码,一共两个页面,一个是视图页面(views)一个是控制器(controllers)控制器中有两个方法,也就是我文章头上所展示的图片,
我这边自己的appid与secret 隐藏掉了,这属于个人信息,每个公众号都是有的。
代码:
weixin.blade.php:
昵称:{{ $nickname }}
TestWeixinController.php:
session()->get('openid')){
return redirect('https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=http://api.xiaoxxx.com/test/callback&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect');
}
//取出session中的nickname,返回到页面输出。
$nickname = $request->session()->get('nickname');
return view('weixin',[
'nickname' => $nickname,
]);
}
public function callback(Request $request)
{
//回掉后获取微信授权生成的code
$code = $request->get('code');
//公众号的appid、secret
$appId = "appid";
$secret = "secret";
//获取access_token的请求地址
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appId&secret=$secret&code=$code&grant_type=authorization_code";
//请求地址获取返回数据
$weixin = file_get_contents($url);
//因为返回的数据为json格式,需要json_decode
$jsonDecode = json_decode($weixin);
//json_decode后的参数为对象。获取需要的access_token、openid。
$accessToken = $jsonDecode->access_token;
$openId = $jsonDecode->openid;
//根据access_token、openid去生成获取用户信息的地址
$userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=$accessToken&openid=$openId&lang=zh_CN";
//请求地址,并获取相关参数
$userInfoJson = file_get_contents($userInfoUrl);
//因为返回的数据为json格式,需要json_decode
$userInfoJsonDecode = json_decode($userInfoJson);
//json_decode后的参数为对象。获取需要的openid、nickname。
$openIdNew = $userInfoJsonDecode->openid;
$nickName = $userInfoJsonDecode->nickname;
//把openid、nickname存入session,方便weixin()方法能够调用
$request->session()->put('openid', $openIdNew);
$request->session()->put('nickname', $nickName);
//返回weixin()方法
return redirect('/test/weixin');
}
}