微信第三方应用授权登录页面(第三方微信接入登录流程整理)

准备工作1.在微信开放平台https://open.weixin.qq.com/注册成为开发者,下面我们就来聊聊关于微信第三方应用授权登录页面?接下来我们就一起去了解一下吧!

微信第三方应用授权登录页面(第三方微信接入登录流程整理)

微信第三方应用授权登录页面

准备工作

1.在微信开放平台https://open.weixin.qq.com/注册成为开发者。

2.在“管理中心”中创建一个移动应用,需“应用名称、简介、及28*28和108*108的PNG图片各一张,且大小不超过300k”,点击下一步,需“应用官网地址,应用签名及包名”等信息,然后即可提交审核。

说明:

应用签名:可在微信开发平台的资源中心》》资源下载》》中下载“签名生成工具”,用户获取已经安装到手机的第三方应用的签名。输入应用包名,即可获得该应用的签名值。

3.提交审核后,在7个工作日内腾讯将给出审核结果。(通常较快,几个小时就可反馈结果)

微信登录接入

微信登录遵循协议Aouth2.0中的授权码模式

我们来看一下Aouth2.0中的授权码模式是怎么定义的:

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。

它的步骤如下:

(A)用户访问客户端,后者将前者导向认证服务器。

1.如果微信授权页不显示,请检查你的APP签名是否和你在腾讯开放平台的APP签名一致,不一致可修改腾讯开放平台中的APP签名,修改后重装微信或清除微信数据后重试。

2.在你的包名相应目录下新建一个wxapi目录,并在该wxapi目录下新增一个WXEntryActivity类,该类继承自Activity(例如应用程序的包名为net.sourceforge,则新的包名为:net.sourceforge.wxapi),此处应注意包名不要弄错,新增类的名字必须为WXEntryActivity。

返回说明

用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK通过SendAuth的Resp返回数据给调用方。回调WXEntryActivity中的onResp(BaseResp resp)方法,如下:

  1. @Override
  2. public void onResp(BaseResp resp) {
  3. int errorCode = resp.errCode;
  4. switch (errorCode) {
  5. case BaseResp.ErrCode.ERR_OK:
  6. //用户同意
  7. String code = ((SendAuth.Resp) resp).code;
  8. break;
  9. case BaseResp.ErrCode.ERR_AUTH_DENIED:
  10. //用户拒绝
  11. break;
  12. case BaseResp.ErrCode.ERR_USER_CANCEL:
  13. //用户取消
  14. break;
  15. default:
  16. break;
  17. }
  18. ToastUtil.showMessageLong(this, resp.errStr);
  19. }

客户端收到授权码后,向自己的服务器发起登录请求,并附带收到的授权码。

服务端收到登录请求,向微信开放平台请求获取access_token,微信开放平台返回Json字符串:

第二步:通过code获取access_token(在自己服务器端做)

获取第一步的code后,请求以下链接获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

  1. private String getAccessToken(String code) {
  2. String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
  3. URI uri = URI.create(url);
  4. HttpClient client = new DefaultHttpClient();
  5. HttpGet get = new HttpGet(uri);
  6. HttpResponse response;
  7. try {
  8. response = client.execute(get);
  9. if (response.getStatusLine().getStatusCode() == 200) {
  10. HttpEntity entity = response.getEntity();
  11. BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
  12. StringBuilder sb = new StringBuilder();
  13. for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
  14. sb.append(temp);
  15. }
  16. JSONObject object = new JSONObject(sb.toString().trim());
  17. accessToken = object.getString("access_token");
  18. openid = object.getString("openid");
  19. refreshToken = object.getString("refresh_token");
  20. expires_in = object.getLong("expires_in");
  21. return accessToken;
  22. }
  23. } catch (ClientProtocolException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. } catch (IOException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. } catch (IllegalStateException e) {
  30. // TODO Auto-generated catch block
  31. e.printStackTrace();
  32. } catch (JSONException e) {
  33. // TODO Auto-generated catch block
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }

参数说明

  1. 参数 是否必须 说明
  2. appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得
  3. secret 是 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
  4. code 是 填写第一步获取的code参数
  5. grant_type 是 填authorization_code回说明**

正确的返回:

  1. {
  2. "access_token":"ACCESS_TOKEN",
  3. "expires_in":7200,
  4. "refresh_token":"REFRESH_TOKEN",
  5. "openid":"OPENID",
  6. "scope":"SCOPE",
  7. "unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
  8. }
  1. 参数 说明
  2. access_token 接口调用凭证
  3. expires_in access_token 接口调用凭证超时时间,单位(秒)
  4. refresh_token 用户刷新access_token
  5. openid 授权用户唯一标识
  6. scope 用户授权的作用域,使用逗号(,)分隔
  7. unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
  8. 错误返回样例:
  9. {"errcode":40029,"errmsg":"invalid code"}

服务端收到返回的access_token,将access_token,expires_in,access_token是否有效 等数据返回给客户端,客户端成功登录

客户端可利用已有的access_token获取微信用户信息

第三步:通过access_token调用接口

获取access_token后,进行接口调用,有以下前提:

  1. access_token有效且未超时;
  2. 微信用户已授权给第三方应用帐号相应接口作用域(scope)。

对于接口作用域(scope),能调用的接口有以下:

  1. 授权作用域(scope) 接口 接口说明
  2. snsapi_base /sns/oauth2/access_token 通过code换取 access_token、refresh_token和已授权scope
  3. /sns/oauth2/refresh_token 刷新或续期access_token使用
  4. /sns/auth 检查access_token有效性
  5. snsapi_userinfo /sns/userinfo 获取用户个人信息

其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。

以获取用户信息为例:

  1. private void getUserInfo() {
  2. if (isAccessTokenIsInvalid() && System.currentTimeMillis() < expires_in) {
  3. String uri = "https://api.weixin.qq.com/sns/userinfo?access_token=" accessToken "&openid=" openID;
  4. HttpClient client = new DefaultHttpClient();
  5. HttpGet get = new HttpGet(URI.create(uri));
  6. try {
  7. HttpResponse response = client.execute(get);
  8. if (response.getStatusLine().getStatusCode() == 200) {
  9. BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
  10. StringBuilder builder = new StringBuilder();
  11. for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
  12. builder.append(temp);
  13. }
  14. JSONObject object = new JSONObject(builder.toString().trim());
  15. String nikeName = object.getString("nickname");
  16. }
  17. } catch (ClientProtocolException e) {
  18. // TODO Auto-generated catch block
  19. e.printStackTrace();
  20. } catch (IOException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. } catch (JSONException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. }
  27. }
  28. }

微信重复登录

假设用户已经获得授权,则下次登录时只需要验证access_token是否有效,无效则重新获取授权,有效则无需重新获得授权。

1.用户向自己的服务器请求登录,登录方式为微信登录,附带上次登录返回的的access_token

2.服务器收到用户的登录请求,向微信开放平台发送access_token是否有效的验证请求如下

  1. private boolean isAccessTokenIsInvalid() {
  2. String url = "https://api.weixin.qq.com/sns/auth?access_token=" accessToken "&openid=" openID;
  3. URI uri = URI.create(url);
  4. HttpClient client = new DefaultHttpClient();
  5. HttpGet get = new HttpGet(uri);
  6. HttpResponse response;
  7. try {
  8. response = client.execute(get);
  9. if (response.getStatusLine().getStatusCode() == 200) {
  10. HttpEntity entity = response.getEntity();
  11. BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
  12. StringBuilder sb = new StringBuilder();
  13. for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
  14. sb.append(temp);
  15. }
  16. JSONObject object = new JSONObject(sb.toString().trim());
  17. int errorCode = object.getInt("errcode");
  18. if (errorCode == 0) {
  19. return true;
  20. }
  21. }
  22. } catch (ClientProtocolException e) {
  23. // TODO Auto-generated catch block
  24. e.printStackTrace();
  25. } catch (IOException e) {
  26. // TODO Auto-generated catch block
  27. e.printStackTrace();
  28. } catch (JSONException e) {
  29. // TODO Auto-generated catch block
  30. e.printStackTrace();
  31. }
  32. return false;
  33. }

返回说明

  1. 正确的Json返回结果:
  2. {
  3. "errcode":0,"errmsg":"ok"
  4. }
  5. 错误的Json返回示例:
  6. {
  7. "errcode":40003,"errmsg":"invalid openid"
  8. }

如果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。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

  1. private void refreshAccessToken() {
  2. String uri = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" ShareUtil.APP_ID "&grant_type=refresh_token&refresh_token="
  3. refreshToken;
  4. HttpClient client = new DefaultHttpClient();
  5. HttpGet get = new HttpGet(URI.create(uri));
  6. try {
  7. HttpResponse response = client.execute(get);
  8. if (response.getStatusLine().getStatusCode() == 200) {
  9. BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
  10. StringBuilder builder = new StringBuilder();
  11. for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) {
  12. builder.append(temp);
  13. }
  14. JSONObject object = new JSONObject(builder.toString().trim());
  15. accessToken = object.getString("access_token");
  16. refreshToken = object.getString("refresh_token");
  17. openID = object.getString("openid");
  18. expires_in = object.getLong("expires_in");
  19. }
  20. } catch (ClientProtocolException e) {
  21. // TODO Auto-generated catch block
  22. e.printStackTrace();
  23. } catch (IOException e) {
  24. // TODO Auto-generated catch block
  25. e.printStackTrace();
  26. } catch (JSONException e) {
  27. // TODO Auto-generated catch block
  28. e.printStackTrace();
  29. }
  30. }

返回说明

  1. 正确的返回:
  2. {
  3. "access_token":"ACCESS_TOKEN",
  4. "expires_in":7200,
  5. "refresh_token":"REFRESH_TOKEN",
  6. "openid":"OPENID",
  7. "scope":"SCOPE"
  8. }
  9. 参数 说明
  10. access_token 接口调用凭证
  11. expires_in access_token接口调用凭证超时时间,单位(秒)
  12. refresh_token 用户刷新access_token
  13. openid 授权用户唯一标识
  14. scope 用户授权的作用域,使用逗号(,)分隔
  15. 错误返回样例:
  16. {
  17. "errcode":40030,"errmsg":"invalid refresh_token"
  18. }

3.服务端获取到新的access_token等信息,并返回给客户端,客户端成功登录或者重新获取授权。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页