项目慢慢的推进,逐渐的做到了微信第三方登录的功能模块了。其实我想说Orz,我等这一天等了好久了,想做个微信验证登录都等了两个多星期咧(其实是我们这边出了点问题),先要申请微信开放平台的帐号,在里面创建一个应用,通过审核之后再交300软妹币,是的,你没有听错,上交300软妹币(听说会成为传说中的认证开发者)才可以获得应用第三方登录的权限,否则只能够分享到盆友圈。中间也是遇到了一些小问题,微信那边的文档写的也不是特别的清楚,还有一些关于微信分享到朋友圈和好友方面的,下面就把问题和解决方法给大家呈上来。
在之前只有微信分享的功能,到后来慢慢的发展出了微信登录的模块,分享的功能比较好做,按照微信给的文档构造好需要传递的信息,再调用微信分享接口,即可跳转至微信的页面进行分享了。登录的功能比分享稍微复杂,需要和微信服务器进行至少三次的数据交换(第一步获取code, 第二步通过code获取access_token以及其他的凭证, 第三步再通过access_token来调用微信的接口)。
如需帐号申请,请跟随链接移步,注册一个帐号后在管理中心—>移动应用找到创建移动应用。
进入后在里面填写各种需要的信息,要注意的是这里的应用审核通过后,应用名称不允许修改,所以各位给自己心爱的应用选一个好听的名字咯(貌似都被注册光了)。
下一步后,会看到要填写应用官网,应用下载地址,应用签名,应用包名等资料。
应用包名就是项目文件AndroidManifest.xml文件里面的package="com.ldx.microtravelnotes"
这个东西。获取应用签名需要先在手机上面安装好应用的release签名版app,再安装一个微信提供的签名生成工具,这个工具安装在手机上后,输入app的应用包名,即可生成应用签名,填写后提交给微信,等待审核的通过。
通过审核之后,会得到微信分配给申请app的appId和appSecret,以及一些能够免费使用的权限(例如分享至微信朋友圈等),如果需要微信验证登录,则要上交300软妹币,成为传说中的验证开发者才可以使用。
在开始做登录和分享之前,还需要下载微信提供的SDK开发包,将这个包导入到项目的libs文件夹里面,再add as library就可以正常的使用了。还需要注意的一点就是要在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"/>
既然微信登录那边还需要再次验证开发者,我们就先来说说微信分享的实现步骤吧,其实小达在做分享的时候还是挺顺利的(相对于登录来说)。实现微信分享功能分为以下几个步骤:
第一步
public static IWXAPI api;
private void registerToWx() {
api = WXAPIFactory.createWXAPI(this, AppConstant.APP_ID, false);
api.registerApp(AppConstant.APP_ID);
}
上面的AppConstant.APP_ID即字符串常量,也就是申请得到的appId,将这些代码放在应用启动时候的Activity或者Application类里面,onCreate()方法调用的时候,顺带的调用registerToWx(),小达这边是有一个在app启动时候绑定的一个Application类,放在了onCreate()里面,贴上一小部分代码,
AndroidManifest.xml
<application
android:name=".global.MTNApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
public class MTNApplication extends CommonApplication {
public static IWXAPI api;
private void registerToWx() {
api = WXAPIFactory.createWXAPI(this, AppConstant.APP_ID, false);
api.registerApp(AppConstant.APP_ID);
}
@Override
public void onCreate() {
super.onCreate();
registerToWx();
}
}
当然也可以写在Activity的onCreate()方法里面,个人觉得放在欢迎页面里面也不错哦。
第二步
private void shareArticleToWx(final int flag) {
if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
WXWebpageObject webPage = new WXWebpageObject();
webPage.webpageUrl = ArticleApi.getDisplayArticleUrl(mArticleId, mArticleTemp);
WXMediaMessage msg = new WXMediaMessage(webPage);
msg.title = "笔记";
msg.description = mArticleTitle;
msg.setThumbImage(loadedImage);
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = String.valueOf(System.currentTimeMillis());
req.message = msg;
req.scene = flag == 0 ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
MTNApplication.api.sendReq(req);
}
上面的代码也就是按照微信给的结构,构造了一个微信分享信息,在这个微信分享信息中,可以设置点击跳转的url,这条分享信息的标题等,其中有一个flag参数,这个参数是用来确定分享给朋友圈(flag == 1)还是分享给好友(flag == 0)的。最后通过一个已经注册过的IWXAPI类的实例来发送出分享请求。
第三步
android:exported="true"
。
创建的WXEntryActivity.java继承自Activity,实现IWXAPIEventHandler接口,该接口即处理微信和app通信的不同event:
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
//这两个参数在文档中没有找到,可能是瞎了,,,自己在代码里面找了会才找到,这两个常量代表了微信返回的消息类型,是对登录的处理还是对分享的处理,登录会在后面介绍到
private static final int RETURN_MSG_TYPE_LOGIN = 1;
private static final int RETURN_MSG_TYPE_SHARE = 2;
private static final String TAG = "WXEntryActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wxentry);
//如果没回调onResp,八成是这句没有写
MTNApplication.api.handleIntent(getIntent(), this);
}
//微信发送消息给app,app接受并处理的回调函数
@Override
public void onReq(BaseReq baseReq) {
}
//app发送消息给微信,微信返回的消息回调函数,根据不同的返回码来判断操作是否成功
@Override
public void onResp(BaseResp resp) {
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_AUTH_DENIED:
case BaseResp.ErrCode.ERR_USER_CANCEL:
showToast("微信失败");
break;
case BaseResp.ErrCode.ERR_OK:
switch (resp.getType()) {
case RETURN_MSG_TYPE_SHARE:
showToast("微信分享成功");
finish();
break;
}
break;
}
}
}
微信分享到这里就做完了,需要上面的三个步骤即可实现,需要注意的是第二步构造分享信息,以及第三步在设置微信回调页面的时候。
在上面微信分享的基础上,再来做微信登录的功能。微信登录前的准备工作和微信分享一样,先将app注册到微信端,app也是通过WXEntryActivity来处理返回的消息。分下面几个步骤进行:
第一步
第二步
if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "diandi_wx_login";
MTNApplication.api.sendReq(req);
上面构造并通过注册好了的api发送了一个请求,请求中scope是固定的形式,用来请求微信验证登录,官方解释:
授权作用域(scope)代表用户授权给第三方的接口权限,第三方应用需要向微信开放平台申请使用相应scope的权限后,使用文档所述方式让用户进行授权,经过用户授权,获取到相应access_token后方可对接口进行调用。如获取用户个人信息则填写snsapi_userinfo
参数state是可以自定义的,官方解释:
用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验
效果大概是这样的:
这个页面就是WXEntryActivity,上面加了一个按钮,用来点击之后执行上面的那一段代码,
点击之后,向微信发送了请求,会自动跳转到微信的界面,也就是下面的这张图片,这个界面是微信已经写好了的,我们就不用操心了。
小达实验了一下,先开始将这个微信验证登录的按钮放在了WXEntryActivity.java中,点击了微信界面登录之后会返回到WXEntryActivity界面中去,后来又想了下,如果不放在WXEnrtyActivity中会怎么样,于是另外写了一个Activity专门用来登录,结果是从微信确认登录之后又返回了WXEnrtyActivity,所以个人认为还是直接放在WXEnrtyActivity里面比较好。反正去了总是要回到这个界面进行处理的。
第三步
{"errcode":40029,"errmsg":"invalid code"}
这种问题了。也是构造一个请求发送给微信,可以直接接在获取code之后,立马把这个请求发送出去,因为是属于微信登录的中间操作。通过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 |
问我在那里获取微信返回的code?肯定是在WXEntryActivity里面咯,前面提到了这个activity是专门用来给微信调用的,附上WXEnrtyActivity.java里面的代码:
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private Button checkLogin;
private static final int RETURN_MSG_TYPE_LOGIN = 1;
private static final int RETURN_MSG_TYPE_SHARE = 2;
private static final String TAG = "WXEntryActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wxentry);
checkLogin = (Button) findViewById(R.id.check_login);
checkLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "diandi_wx_login";
MTNApplication.api.sendReq(req);
}
});
//如果没回调onResp,八成是这句没有写
MTNApplication.api.handleIntent(getIntent(), this);
}
//微信直接发送给app的消息处理回调
@Override
public void onReq(BaseReq baseReq) {
}
//app发送消息给微信,处理返回消息的回调
@Override
public void onResp(BaseResp resp) {
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_AUTH_DENIED:
case BaseResp.ErrCode.ERR_USER_CANCEL:
if (RETURN_MSG_TYPE_SHARE == resp.getType()) AppData.showToast("分享失败");
else AppData.showToast("登录失败");
break;
case BaseResp.ErrCode.ERR_OK:
switch (resp.getType()) {
case RETURN_MSG_TYPE_LOGIN:
//拿到了微信返回的code,立马再去请求access_token
String code = ((SendAuth.Resp) resp).code;
//就在这个地方,用网络库什么的或者自己封的网络api,发请求去咯,注意是get请求
break;
case RETURN_MSG_TYPE_SHARE:
AppData.showToast("微信分享成功");
finish();
break;
}
break;
}
}
}
请求返回回来的参数形式如下:
{
"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 | 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 |
微信验证登录到这里就差不多了,验证的主要目的就是拿到微信给的这个access_token,用来调用微信的各种接口,可以获取用户的基本信息等等。下面就来说说在做的过程中遇到了那些坑的地方(其实就是在自己坑自己Orz)。
在做微信登录模块的时候,遇到了一些小的问题如下,现在给出一些小的建议:
MTNApplication.api.handleIntent(getIntent(), this);
以上就是对微信登录以及分享的一些小心得,拿出来和大家分享一下,有什么错误的地方还望多多指教。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/jing_unique_da/article/details/47254993