今天项目中集成微信登录,以为非常顺利的事情,却还是多多少少出现了一些问题。所以记录一下集成过程中出现的问题。
开发环境:
[x] 系统环境:
windows10
[x] AndroidStudio 版本:
3.3.2
[x] Gradle 版本:
4.10.1
集成过程(参照微信接入指南(https://open.weixin.qq.com/cgibin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=60cf535dd0331502a793d5f32051b033b24b9e9d&lang=zh_CN))
- 在项目gradle添加依赖
//微信
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
2.注册申请好的AppId到微信(必须在调用登录功能之前)
// APP_ID
private static final String APP_ID = "自己的appId";
api = WXAPIFactory.createWXAPI(context, APP_ID, true);
// 将应用的appId注册到微信
api.registerApp(APP_ID);
3.发送登录请求()
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "111";
api.sendReq(req);
参数说明
来源: https://open.weixin.qq.com/cgi-bin/showdocument?action=doc&id=open1419317851&t=0.2650837650069082
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
scope | 是 | 应用授权作用域,如获取用户个人信息则填写snsapi_userinfo( 什么是授权域? ) |
state | 否 | 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
4.在项目包名下创建wxapi包并且创建WXEntryActivity,并且在AndroidManifest中配置,配置必须与下图中一致。
5.在WXEntryActivity中,实现 IWXAPIEventHandler 接口。在oncreate方法中注册回调
api.handleIntent(getIntent(), this);
如果不注册,则收不到回调(我刚开始没有注册该回调,导致一直收不到回调信息)。
6.在项目gradle中配置签名文件,必须与平台中的签名一致。
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
}
debug{
signingConfig signingConfigs.debug // 配置debug包的签名
}
}
signingConfigs {
debug {
storeFile file("签名路径/debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
}
到这里就集成成功了,我遇到的问题主要是没有注册回调,导致收不到信息。
关于WXEntryActivity中,实现 IWXAPIEventHandler 接口后,根据微信提供的文档以及业务需要继续下去就好了:
@Override
public void onReq(BaseReq baseReq) {
}
@Override
public void onResp(BaseResp baseResp) {
Log.e(TAG, ((SendAuth.Resp) baseResp).code +
"--" + ((SendAuth.Resp) baseResp).url +
"--" + baseResp.getType() +
"--" + baseResp.errCode +
"--" + ((SendAuth.Resp) baseResp).state +
"--" + ((SendAuth.Resp) baseResp).lang);
}
返回说明
用户点击授权后,微信客户端会被拉起,跳转至授权界面,用户在该界面点击允许或取消,SDK通过SendAuth的Resp返回数据给调用方。
返回值 | 说明 |
---|---|
ErrCode | ERR_OK = 0(用户同意) ERR_AUTH_DENIED = -4(用户拒绝授权) ERR_USER_CANCEL = -2(用户取消) |
code | 用户换取access_token的code,仅在ErrCode为0时有效 |
state | 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K |
lang | 微信客户端当前语言 |
country | 微信用户当前国家信息 |
第二步:通过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
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
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 | 当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段 |
错误返回样例:
{"errcode":40029,"errmsg":"invalid code"}
刷新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失效的后,需要用户重新授权。
请求方法
获取第一步的code后,请求以下链接进行refresh_token:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 应用唯一标识 |
grant_type | 是 | 填refresh_token |
refresh_token | 是 | 填写通过access_token获取到的refresh_token参数 |
返回说明
正确的返回:
{"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"}
注意:
1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。
建议将Appsecret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。
第三步:通过access_token调用接口
获取access_token后,进行接口调用,有以下前提:
- access_token有效且未超时;
- 微信用户已授权给第三方应用帐号相应接口作用域(scope)。
对于接口作用域(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,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。
接口调用方法可查阅《微信授权关系接口调用指南》
F.A.Q
1. 什么是授权临时票据(code)?
答:第三方通过code进行获取access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。code的临时性和一次保障了微信授权登录的安全性。第三方可通过使用https和state参数,进一步加强自身授权登录的安全性。
2. 什么是授权作用域(scope)?
答:授权作用域(scope)代表用户授权给第三方的接口权限,第三方应用需要向微信开放平台申请使用相应scope的权限后,使用文档所述方式让用户进行授权,经过用户授权,获取到相应access_token后方可对接口进行调用。
3.开放平台移动应用微信登录目前是否收费?
答:“微信登录”和第三方网站共享微信庞大的用户价值,同时为微信用户提供更便捷服务和更优质内容,实现双向共赢,目前不收取任何费用。
文章部分内容转载微信开放平台 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=60cf535dd0331502a793d5f32051b033b24b9e9d&lang=zh_CN