微信开放平台开发系列文章:

微信开放平台开发第三方授权登陆(一):开发前期准备

微信开放平台开发第三方授权登陆(二):PC网页端

微信开放平台开发第三方授权登陆(三):Android客户端

微信开放平台开发第三方授权登陆(四):微信公众号

微信开放平台开发第三方授权登陆(五):微信小程序

目录​​​​​​​

一、需求

二、开发流程

三、开发使用的技术及工具

四、具体实现步骤

1.前端(Android)

1)Android微信授权登录开发环境配置

2)引导用户点击登录并授权

3)接收微信服务端返回的数据并向服务端发送请求

4)根据服务端返回数据进行解析并显示给前端Android页面

2.服务端(Java)

1).统一返回JSON

2).相关参数配置:

3).请求响应逻辑

4).根据Token获取用户信息:

五、注意事项:

六、应用关键参数位置


当微信开放平台开发第三方授权登陆(一):开发前期准备完成后,已经获取到应用的AppID和AppSecret、且已经成功申请到微信登陆功能。可以进行第三方登陆授权开发。

注意:

目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用

对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微信客户端时,请引导用户下载安装微信客户端

开放平台中创建移动应用时,需要添加包名(一定要和开发的包名完全一致,不能是填写的包名的子包,否则微信无法回调成功)

安装验签工具:Gen_Signature_Android2.apk。

填写包名,然后会生成应用签名,填写应用签名就可以了。

一、需求

拥有第三方微信登录功能,并获取到用户信息。

二、开发流程

Android移动应用:(App唤醒微信客户端授权登陆)

1. 应用发起微信授权登录请求,用户允许授权应用后,微信会拉起应用或重定向到第三方网站(服务端),并且带上授权临时票据code参数;

2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;

3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

获取用户基本信息的流程

三、开发使用的技术及工具

1、.后端采用IDEA2017 进行开发

2、使用Android Studio 3.1.3 进行开发

3、后端必须基于JDK7以上版本,采用JDK8开发,前端基于Android SDK4.4

4、使用fastJson对json数据进行处理

四、具体实现步骤

1.前端(Android)

目录结构如下:

1)Android微信授权登录开发环境配置

I.添加微信依赖

Android Studio环境

在build.gradle文件中,添加依赖

dependencies {

compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'

}

dependencies {

compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'

}

Eclipse环境下:

在工程中新建一个libs目录,将开发工具包中libs目录下的libammsdk.jar复制到该目录中(如下图所示,建立了一个名为SDK_Sample 的工程,并把jar包复制到libs目录下)。

右键单击工程,选择Build Path中的Configure Build Path...,选中Libraries这个tab,并通过Add Jars...导入工程libs目录下的libammsdk.jar文件。(如下图所示)。

在需要使用微信终端API的文件中导入相应的类。

import com.tencent.mm.opensdk.openapi.WXTextObject;

II. AndroidManifest.xml 设置

添加如下权限支持:

    <!--权限声明--><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

III.若要混淆代码,为保证sdk正常使用,需在配置proguard.cfg(proguard-rule.pro):

# wechat
-keep class com.tencent.mm.opensdk.** {*;}
-keep class com.tencent.wxop.** {*;}
-keep class com.tencent.mm.sdk.** {*;}

2)引导用户点击登录并授权

I.layout.xml

添加button:

        <Buttonandroid:id="@+id/wechat_login_btn"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="@string/wechat_login"/>

II.监听button点击事件,拉起微信授权页

       findViewById(R.id.wechat_login_btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (isWXAppInstalledAndSupported()) {  // 用户是否安装微信客户端// send oauth requestfinal SendAuth.Req req = new SendAuth.Req();req.scope = "snsapi_userinfo";req.state = "none";api.sendReq(req);finish();} else {// TODO: 这里需要引导用户去下载微信客户端Toast.makeText(WXEntryActivity.this, "用户没有安装微信", Toast.LENGTH_SHORT).show();}}});

III.用户手机是否安装微信客户端检查

  private boolean isWXAppInstalledAndSupported() {IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);msgApi.registerApp(Constants.APP_ID);boolean sIsWXAppInstalledAndSupported = msgApi.isWXAppInstalled()&& msgApi.isWXAppSupportAPI();return sIsWXAppInstalledAndSupported;}

3)接收微信服务端返回的数据并向服务端发送请求

用户统一授权后,微信会返回数据,需要在.wxapi.WXEntryActivity下对数据进行处理。

I.新建wxapi包(包名固定,且必须是在微信开放平台注册的包名下)

II.新建Activity类,命名为WXEntryActivity

WXEntryActivity,并继承Activity类,实现IWXAPIEventHandler接口的两个方法

public interface IWXAPIEventHandler {void onReq(BaseReq var1);void onResp(BaseResp var1);
}

WXEntryActivity实现

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

private IWXAPI api;  // 在onCreate中进行了初始化

onReq方法

    // 微信发送请求到第三方应用时,会回调到该方法@Overridepublic void onReq(BaseReq req) {Toast.makeText(this, "Test ", Toast.LENGTH_SHORT).show();switch (req.getType()) {case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:break;case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:break;default:break;}
}

onResp方法

在onResp中需要实现逻辑,微信返回的数据在这里会被接收。

微信返回的数据包含code。在onResp需要实现向服务端发送请求,带上code等参数,后端再通过相应的参数去请求微信服务端,最终将获取到的用户信息返回给前端Android。

// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法@Overridepublic void onResp(final BaseResp resp) {int result = 0;Toast.makeText(this, "baseresp.getType = " + resp.getType(), Toast.LENGTH_SHORT).show();//成功后发送请求switch (resp.errCode) {case BaseResp.ErrCode.ERR_OK:result = R.string.errcode_success;final String code = ((SendAuth.Resp) resp).code;//需要转换一下才可以new Thread(new Runnable() {@Overridepublic void run() {//向服务端发送请求,预计返回用户信息数据,返回给前端进行显示。String url = "http://p2a3b8.natappfree.cc" +"/wechat/open/callback/android" + "?" +"state=" + "android" +//这里的state需与后端进行探讨"&code=" + code;String str = ApacheHttpUtil.get(url);JSONObject jsonObject = (JSONObject) JSONObject.parse(str);weChatUserInfo = (WeChatUserInfo) JSON.parseObject(jsonObject.get("data").toString(), new TypeReference<WeChatUserInfo>() {});}}).start();while (true) {
// TODO: 这里处理方案不合理,死循环或将造成界面卡死(需要前端优化)if (weChatUserInfo != null) {Intent intent = new Intent(WXEntryActivity.this, WechatUserInfoViewItem.class);/* 通过Bundle对象存储需要传递的数据 */Bundle bundle = new Bundle();bundle.putString("wechatopenid", weChatUserInfo.getOpenid());bundle.putString("wechatnickname", weChatUserInfo.getNickname());bundle.putString("wechatsex", weChatUserInfo.getSex().toString());bundle.putString("wechatprovince", weChatUserInfo.getProvince());bundle.putString("wechatcity", weChatUserInfo.getCity());bundle.putString("wechatcountry", weChatUserInfo.getCountry());bundle.putString("wechatheadimgurl", weChatUserInfo.getHeadimgurl());bundle.putString("wechatprivilege", weChatUserInfo.getPrivilege());bundle.putString("wechatunionid", weChatUserInfo.getOpenid());/*把bundle对象assign给Intent*/intent.putExtras(bundle);startActivity(intent);break;}}break;case BaseResp.ErrCode.ERR_USER_CANCEL:result = R.string.errcode_cancel;   // 发送取消break;case BaseResp.ErrCode.ERR_AUTH_DENIED:result = R.string.errcode_deny;   // 发送被拒绝break;case BaseResp.ErrCode.ERR_UNSUPPORT:result = R.string.errcode_unsupported;  // 不支持错误break;default:result = R.string.errcode_unknown;  // 发送返回break;}Toast.makeText(this, result, Toast.LENGTH_LONG).show();}

重写onNewIntent方法

在WXEntryActivity中将接收到的intent及实现了IWXAPIEventHandler接口的对象传递给IWXAPI接口的handleIntent方法,

    @Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);api.handleIntent(intent, this);}

III.在manifest文件添加WXEntryActivity,并加上exported属性,设置为true,:

        <activityandroid:name=".wxapi.WXEntryActivity"android:exported="true"android:label="@string/app_name"android:launchMode="singleTask"><!--android:launchMode="singleTop">--><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="sdksample" /></intent-filter></activity>

4)根据服务端返回数据进行解析并显示给前端Android页面

获取数据已经跳转代码如上(onResp方法中)。需要前端优化处理

public class WechatUserInfoViewItem extends FragmentActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.wechat_user_info);Bundle bundle = this.getIntent().getExtras();TextView wechatopenid = (TextView) findViewById(R.id.wechatopenid);wechatopenid.setText(bundle.getString("wechatopenid"));TextView wechatnickname = (TextView) findViewById(R.id.wechatnickname);wechatnickname.setText(bundle.getString("wechatnickname"));TextView wechatsex = (TextView) findViewById(R.id.wechatsex);wechatsex.setText(bundle.getString("wechatsex"));TextView wechatprovince = (TextView) findViewById(R.id.wechatprovince);wechatprovince.setText(bundle.getString("wechatprovince"));TextView wechatcity = (TextView) findViewById(R.id.wechatcity);wechatcity.setText(bundle.getString("wechatcity"));TextView wechatcountry = (TextView) findViewById(R.id.wechatcountry);wechatcountry.setText(bundle.getString("wechatcountry"));TextView wechatunionid = (TextView) findViewById(R.id.wechatunionid);wechatunionid.setText(bundle.getString("wechatunionid"));}
}

布局xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"><ImageViewandroid:id="@+id/wechatheadimgurl"android:layout_width="200dp"android:layout_height="100dp"android:scaleType="center"/><!--用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)[这里是一个list]--><!--String privilege;--><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="openid:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatopenid"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="unionid:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatunionid"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="用户昵称:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatnickname"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="85dp"tools:layout_editor_absoluteY="212dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="用户城市:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatcity"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="118dp"tools:layout_editor_absoluteY="302dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="用户性别:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatsex"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="118dp"tools:layout_editor_absoluteY="302dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="省份:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatprovince"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="118dp"tools:layout_editor_absoluteY="302dp" /></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="国家:"tools:layout_editor_absoluteX="158dp"tools:layout_editor_absoluteY="216dp" /><TextViewandroid:id="@+id/wechatcountry"android:layout_width="wrap_content"android:layout_height="wrap_content"tools:layout_editor_absoluteX="118dp"tools:layout_editor_absoluteY="302dp" /></LinearLayout>
</LinearLayout>

2.服务端(Java)

服务端需要做的是:接受Android前端发送的请求,获取code,根据AppId和APPSecret等向微信服务端发送请求,然后获取到Token,再根据Token获取到用户基本信息。最终通过JSON的方式返回给前端。

1).统一返回JSON

@Getter @Setter
public class Result<T> {private int code;private String msg;private T data;/*** 成功时候的调用* */public static <T> Result<T> success(T data){return new  Result<T>(data);}/*** 失败时候的调用* */public static <T> Result<T> error(CodeMsg cm){return new  Result<T>(cm);}private Result(T data) {this.code = 0;this.msg = "success";this.data = data;}private Result(CodeMsg cm) {if(cm == null) {return;}this.code = cm.getCode();this.msg = cm.getMsg();}
}

2).相关参数配置:

# 微信开放平台Android

wechat.open.android.appid =

wechat.open.android.appsecret =

3).请求响应逻辑

@ResponseBody@RequestMapping("/callback/android")public Result openWeChatCallback(HttpServletRequest httpServletRequest) {String code = httpServletRequest.getParameter("code");//String state = httpServletRequest.getParameter("state"); // TODO:String url = null;url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +"appid=" +env.getProperty("wechat.open.android.appid").trim() +"&secret=" +env.getProperty("wechat.open.android.appsecret").trim() +"&code=" +code +"&grant_type=authorization_code";JSONObject wechatAccessToken = HttpClientUtils.httpGet(url);if (wechatAccessToken.get("errcode") != null) {return Result.error(CodeMsg.FAIL_GETTOKEN);}String accessToken = (String) wechatAccessToken.get("access_token");String openid = (String) wechatAccessToken.get("openid");String unionid = (String) wechatAccessToken.get("unionid");if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid) || StringUtils.isEmpty(unionid)) {return Result.error(CodeMsg.FAIL_GETTOKEN);}// TODO:根据Openid或Unionid对数据库进行查询,如果查询到对应的用户数据,则不需要再向微信服务器发送请求去返回数据。// TODO: 建议使用Unionid作为查询条件。WeChatUserInfo weChatUserInfo = null;wechatAccessToken = null;  // FIXME: 这里应该是从数据库中查询获取用户信息逻辑。if (wechatAccessToken == null) {// 新用户weChatUserInfo = getUserInfoByAccessToken(accessToken);// 数据库插入的操作}if (weChatUserInfo != null) {return Result.success(weChatUserInfo);}return Result.error(CodeMsg.FAIL_GETUSERINFO);}

4).根据Token获取用户信息:

/*** 根据accessToken获取用户个人公开信息** @param accessToken* @return*/private WeChatUserInfo getUserInfoByAccessToken(String accessToken) {if (StringUtils.isEmpty(accessToken)) {return null;  //"accessToken为空";}String get_userInfo_url = "https://api.weixin.qq.com/sns/userinfo?" +"access_token=" +accessToken +"&openid=" +env.getProperty("wechat.open.android.appid").trim();String userInfo_result = HttpClientUtils.httpGet(get_userInfo_url, "utf-8");if (!userInfo_result.equals("errcode")) {WeChatUserInfo weChatUserInfo = JSON.parseObject(userInfo_result, new TypeReference<WeChatUserInfo>() {});// TODO: 需要把头像信息下载到文件服务器,然后替换掉头像URL。微信的或许不可靠,假设微信用户更换了头像,旧头像URL是否会保存?而这个URL信息却存放在我们的数据库中,不可靠return weChatUserInfo;}return null;  //"获取用户信息失败"}

五、注意事项:

1.Android4.0以上版本,发送网络请求时,必须是以线程异步的方式发送请求,否则发送请求会失败。

六、应用关键参数位置

微信开放平台开发第三方授权登陆(三):Android客户端相关推荐

  1. 微信开放平台开发第三方授权登陆(二):PC网页端

    微信开放平台开发系列文章: 微信开放平台开发第三方授权登陆(一):开发前期准备 微信开放平台开发第三方授权登陆(二):PC网页端 微信开放平台开发第三方授权登陆(三):Android客户端 微信开放平 ...

  2. 微信开放平台开发第三方授权登陆

    本文转载自网络,原文链接https://blog.csdn.net/qq_34190023/article/details/81133619 目录 一.前期准备流程 二.具体实现步骤 1.注册邮箱账号 ...

  3. 微信开放平台开发第三方授权登陆:微信扫码登录

    一.概述 根据需求,需要拥有第三方微信登录功能,并获取到用户信息. 网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统. 二.前期准备工作 1.注册邮箱账号. 2.根 ...

  4. 蚂蚁开放平台开发第三方授权登陆(一):开发前期准备

    根据需求,需要使用支付宝进行第三方授权登陆获取用户基本信息.支持PC网页.App应用的授权. 其中PC网页只需要添加获取用户信息的功能,成功上线后就可以完成功能. App应用授权登陆则需要有一个生效的 ...

  5. 蚂蚁开放平台开发第三方授权登陆(二):PC端

    在<蚂蚁金服开放平台开发前期准备>准备后,已经获取应用AppID以及应用私钥.支付宝公钥.回调地址.可以进行网站应用的开发. 一.需求 用户点击登录后,选择第三方登录中的"支付宝 ...

  6. 蚂蚁开放平台开发第三方授权登陆(三):Android端

    开发前提: 拥有支付宝账户登录授权业务入参pid值.拥有APPID.App支付宝登录功能并成功签约 一.需求 用户在APP点击登录后,选择第三方登录中的"支付宝",跳转到支付宝客户 ...

  7. 微信开放平台【第三方平台】java开发总结:预授权码(pre_auth_code)(三)

    微信第三方平台预授权码(pre_auth_code)开发说明(全网最详细的微信第三方平台预授权码开发说明) 预授权码 预授权码(pre_auth_code)是第三方平台方实现授权托管的必备信息,每个预 ...

  8. 微信开放平台之第三方平台开发,模板小程序如何提交?

    大家好,我是悟空码字 12月25日,天气晴朗,阳光普照,今天是圣诞节.因为疫情影响,小羊人的增多,街上放眼望去,人烟稀少.楼下除了几个十一二岁的小男孩在玩耍,也没有像往日老人悠闲打牌.小孩嬉戏那般热闹 ...

  9. 微信开放平台【第三方平台】java开发总结:验证票据(component_verify_ticket)(-)

    微信第三方平台验证票据(component_verify_ticket)开发说明(全网最详细的微信第三方平台验证票据开发说明) 概述 微信公众平台-第三方平台(简称第三方平台)开放给所有通过开发者资质 ...

最新文章

  1. 又双叒叕一个软件安装方法
  2. 在计算机软件中 CUI的中文意思是,长江大学 计算机基础11-12上A卷cui
  3. bz1968 1968: [Ahoi2005]COMMON 约数研究
  4. matlab自带SVM算法例子(附函数详解)
  5. 通过.pk8及.pem文件生成Android studio使用的keystore文件。
  6. 南航计算机考研是自主命题吗_什么是自主计算?
  7. java 8 中文字体_jdk安装中文字体,解决Can't read the embedded font LNUHUF+SimSun
  8. python正确判断错误_python之错误、调试和测试
  9. 手写SSH2服务器连接池
  10. 使用shopnc发送qq邮件遇到的坑
  11. 使用安卓原生系统刷机,修改
  12. js操作设置css动画,使用 CSS3 和 JavaScript 制作链接反转 3D 动画 - 文章教程
  13. 运营——线上引流9大方法
  14. Windows10安装MinGW-w64
  15. JavaScript基本原理常识
  16. 将平板作为自己电脑的第二屏幕的方法
  17. Java 生成二维码。
  18. 多视图几何中的三维重建
  19. java读取zip文件,并将json中的反转义斜杆去除
  20. 虚幻四蓝图编辑之开关门

热门文章

  1. routeDone with a webviewId 12 that is not the current page(env: Windows,mp,1.06.2301040; lib: 2.30.0
  2. 【踩坑日记】阿里云内容安全
  3. 微店获得微店商品详情API,使用和获取说明
  4. chrome设置标签页
  5. 宣化科技职业学院计算机网络技术,职业技术学校专业建设-宣化科技职业技术学院-计算机网络技术.doc...
  6. 学python入门基础教程[推荐]
  7. excel筛选后复制粘贴
  8. 基于JAVA图书借阅系统的设计与实现计算机毕业设计源码+系统+lw文档+部署
  9. Windows10文件后缀名不显示·解决方法
  10. 在哪买虚拟服务器,虚拟服务器是购买哪种