这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
本篇文章主要介绍了谈谈第三方 App 接入微信登录 解读 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧。
接入微信登录:
1、准备工作
1. 在微信开放平台 https://open.weixin.qq.com / 注册成为开发者。
2. 在 "管理中心" 中创建一个移动应用,需 "应用名称、简介、及 28*28 和 108*108 的 PNG 图片各一张,且大小不超过 300k", 点击下一步,需 "应用官网地址,应用签名及包名" 等信息,然后即可提交审核。
说明:
应用签名:可在微信开发平台的资源中心》》资源下载》》中下载 "签名生成工具",用户获取已经安装到手机的第三方应用的签名。输入应用包名,即可获得该应用的签名值。
3. 提交审核后,在 7 个工作日内腾讯将给出审核结果。(通常较快,几个小时就可反馈结果)
2、微信登录接入
微信登录遵循协议 Aouth2.0 中的授权码模式,先介绍一下 Aouth2.0 的流程:
3、微信登录的官方文档将微信登录分为 3 个步骤:
第一步. 请求 code:
- {
- // send oauth request
- Final SendAuth.Req req = new SendAuth.Req();
- req.scope = "snsapi_userinfo";
- req.state = "wechat_sdk_demo_test";
- api.sendReq(req);
- }
用这段代码向微信开放平台请求授权码 code, 可拉起微信并打开授权登录页(前提是你安装了微信应用并已登录,未登录的会引导你先登录)下图:
需要注意的情况:
1. 如果微信授权页不显示,请检查你的 APP 签名是否和你在腾讯开放平台的 APP 签名一致,不一致可修改腾讯开放平台中的 APP 签名,修改后重装微信或清除微信数据后重试。
2. 在你的包名相应目录下新建一个 wxapi 目录,并在该 wxapi 目录下新增一个 WXEntryActivity 类,该类继承自 Activity(例如应用程序的包名为 net.sourceforge,则新的包名为:net.sourceforge.wxapi), 此处应注意包名不要弄错,新增类的名字必须为 WXEntryActivity。
返回说明
用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK 通过 SendAuth 的 Resp 返回数据给调用方。回调 WXEntryActivity 中的 onResp(BaseResp resp) 方法,如下:
- @Override public void onResp(BaseResp resp) {
- int errorCode = resp.errCode;
- switch (errorCode) {
- case BaseResp.ErrCode.ERR_OK:
- //用户同意
- String code = ((SendAuth.Resp) resp).code;
- break;
- case BaseResp.ErrCode.ERR_AUTH_DENIED:
- //用户拒绝
- break;
- case BaseResp.ErrCode.ERR_USER_CANCEL:
- //用户取消
- break;
- default:
- break;
- }
- ToastUtil.showMessageLong(this, resp.errStr);
- }
客户端收到授权码后,向自己的服务器发起登录请求,并附带收到的授权码。
服务端收到登录请求,向微信开放平台请求获取 access_token,微信开放平台返回 Json 字符串:
第二步:通过 code 获取 access_token:
获取第一步的 code 后,请求以下链接获取 access_token:
- private String getAccessToken(String code) {
- String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
- URI uri = URI.create(url);
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(uri);
- HttpResponse response;
- try {
- response = client.execute(get);
- if (response.getStatusLine().getStatusCode() == 200) {
- HttpEntity entity = response.getEntity();
- BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
- StringBuilder sb = new StringBuilder();
- for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
- sb.append(temp);
- }
- JSONObject object = new JSONObject(sb.toString().trim());
- accessToken = object.getString("access_token");
- openID = object.getString("openid");
- refreshToken = object.getString("refresh_token");
- expires_in = object.getLong("expires_in");
- return accessToken;
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return null;
- }
参数说明
参数 是否必须 说明
appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
secret 是 应用密钥 AppSecret,在微信开放平台提交应用审核通过后获得
code 是 填写第一步获取的 code 参数
grant_type 是 填 authorization_code 回说明 **
正确的返回:
- {
- "access_token": "ACCESS_TOKEN",
- "expires_in": 7200,
- "refresh_token": "REFRESH_TOKEN",
- "openid": "OPENID",
- "scope": "SCOPE",
- "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
- }
参数 说明
access_token 接口调用凭证
expires_in access_token 接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新 access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
错误返回样例:
- {
- "errcode": 40029,
- "errmsg": "invalid code"
- }
第三步:通过 access_token 调用接口
获取 access_token 后,进行接口调用,有以下前提:
对于接口作用域(scope),能调用的接口有以下:
授权作用域(scope) 接口 接口说明
snsapi_base /sns/oauth2/access_token 通过 code 换取 access_token、refresh_token 和已授权 scope
/sns/oauth2/refresh_token 刷新或续期 access_token 使用
/sns/auth 检查 access_token 有效性
snsapi_userinfo /sns/userinfo 获取用户个人信息
其中 snsapi_base 属于基础接口,若应用已拥有其它 scope 权限,则默认拥有 snsapi_base 的权限。使用 snsapi_base 可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为 snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。
以获取用户信息为例:
- private void getUserInfo() {
- if (isAccessTokenIsInvalid() && System.currentTimeMillis() < expires_in) {
- String uri = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openID;
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(URI.create(uri));
- try {
- HttpResponse response = client.execute(get);
- if (response.getStatusLine().getStatusCode() == 200) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
- StringBuilder builder = new StringBuilder();
- for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
- builder.append(temp);
- }
- JSONObject object = new JSONObject(builder.toString().trim());
- String nikeName = object.getString("nickname");
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
微信重复登录
假设用户已经获得授权,则下次登录时只需要验证 access_token 是否有效,无效则重新获取授权,有效则无需重新获得授权。
1. 用户向自己的服务器请求登录,登录方式为微信登录,附带上次登录返回的的 access_token
2. 服务器收到用户的登录请求,向微信开放平台发送 access_token 是否有效的验证请求如下:
- private boolean isAccessTokenIsInvalid() {
- String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openID;
- URI uri = URI.create(url);
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(uri);
- HttpResponse response;
- try {
- response = client.execute(get);
- if (response.getStatusLine().getStatusCode() == 200) {
- HttpEntity entity = response.getEntity();
- BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
- StringBuilder sb = new StringBuilder();
- for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
- sb.append(temp);
- }
- JSONObject object = new JSONObject(sb.toString().trim());
- int errorCode = object.getInt("errcode");
- if (errorCode == 0) {
- return true;
- }
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return false;
- }
返回说明
正确的 Json 返回结果:
- {
- "errcode": 0,
- "errmsg": "ok"
- }
错误的 Json 返回示例:
- {
- "errcode": 40003,
- "errmsg": "invalid openid"
- }
如果 access_token 有效,服务端将信息返回给客户端,客户端成功登录。
如果 access_token 无效,服务端向微信开放平台发送刷新 access_token 的请求如下:
access_token 是调用授权关系接口的调用凭证,由于 access_token 有效期(目前为 2 个小时)较短,当 access_token 超时后,可以使用 refresh_token 进行刷新,access_token 刷新结果有两种:
1. 若 access_token 已超时,那么进行 refresh_token 会获取一个新的 access_token,新的超时时间;
2. 若 access_token 未超时,那么进行 refresh_token 不会改变 access_token,但超时时间会刷新,相当于续期 access_token。
刷新 token
- private void refreshAccessToken() {
- String uri = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + ShareUtil.APP_ID + "&grant_type=refresh_token&refresh_token=" + refreshToken;
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(URI.create(uri));
- try {
- HttpResponse response = client.execute(get);
- if (response.getStatusLine().getStatusCode() == 200) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
- StringBuilder builder = new StringBuilder();
- for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
- builder.append(temp);
- }
- JSONObject object = new JSONObject(builder.toString().trim());
- accessToken = object.getString("access_token");
- refreshToken = object.getString("refresh_token");
- openID = object.getString("openid");
- expires_in = object.getLong("expires_in");
- }
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
正确的返回:
- {
- "access_token": "ACCESS_TOKEN",
- "expires_in": 7200,
- "refresh_token": "REFRESH_TOKEN",
- "openid": "OPENID",
- "scope": "SCOPE"
- }
参数 说明
access_token 接口调用凭证
expires_in access_token 接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新 access_token
openid 授权用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
错误返回样例:
- {
- "errcode": 40030,
- "errmsg": "invalid refresh_token"
- }
来源: http://www.phperz.com/article/17/0724/329113.html