前言
由于历史遗留问题,项目中微信登录用的是原生微信的登录,即先请求 code
、再 通过 code
获取 access_token
,然后通过access_token
调用接口,获取微信用户信息。
之前项目中用到了友盟分享,在加入微信登录功能出现了,经常会出现了code been used, hints: [ req_id: FEMAxQaLRa-CSO ]
这个问题。
如果使用友盟获取微信用户信息也不会有这个问题,当然如果后台大佬如果愿意改代码也可以,可现实...,于是只有我们自己动手解决了。
分析
首先,确认问题出在哪里?
于是,先去掉了友盟分享的相关逻辑,发现正常,基本可以确认问题出在友盟上。但是,又不能去掉项目中的友盟分享逻辑,是不是可以判断是分享时,用友盟的逻辑,如果是登录时,使用自己的逻辑?
通过查看微信sdk的源码,我们发现,WXEntryActivity 实现了IWXAPIEventHandler
,而返回的code的回调是方法onResp
public class WXEntryActivity extends Activity implements IWXAPIEventHandler{
@Override
public void onResp(BaseResp resp) {
//这里
}
}
然后,我们去看看友盟sdk的源码
public void a(b var1) {
SLog.I("WXCallbackActivity 分发回调");
if (this.a != null && var1 != null) {
try {
this.a.getWXEventHandler().a(var1);
} catch (Exception var3) {
SLog.error(var3);
}
}
this.finish();
}
public void a(a var1) {
if (this.a != null) {
this.a.getWXEventHandler().a(var1);
}
this.finish();
}
卧槽,还混淆了,只能硬着头皮继续看了
查看b
,和微信sdk的对比,发现b
即微信sdk 中的BaseResp
b
源码,已省略部分代码
public abstract class b {
public void a(Bundle var1) {
var1.putInt("_wxapi_command_type", this.a());
var1.putInt("_wxapi_baseresp_errcode", this.a);
var1.putString("_wxapi_baseresp_errstr", this.b);
var1.putString("_wxapi_baseresp_transaction", this.c);
var1.putString("_wxapi_baseresp_openId", this.d);
}
public void b(Bundle var1) {
this.a = var1.getInt("_wxapi_baseresp_errcode");
this.b = var1.getString("_wxapi_baseresp_errstr");
this.c = var1.getString("_wxapi_baseresp_transaction");
this.d = var1.getString("_wxapi_baseresp_openId");
}
}
BaseResp
源码,已省略部分代码
public abstract class BaseResp {
public void toBundle(Bundle var1) {
var1.putInt("_wxapi_command_type", this.getType());
var1.putInt("_wxapi_baseresp_errcode", this.errCode);
var1.putString("_wxapi_baseresp_errstr", this.errStr);
var1.putString("_wxapi_baseresp_transaction", this.transaction);
var1.putString("_wxapi_baseresp_openId", this.openId);
}
public void fromBundle(Bundle var1) {
this.errCode = var1.getInt("_wxapi_baseresp_errcode");
this.errStr = var1.getString("_wxapi_baseresp_errstr");
this.transaction = var1.getString("_wxapi_baseresp_transaction");
this.openId = var1.getString("_wxapi_baseresp_openId");
}
}
由此,我们可以确认,a(b var1)
此方法为微信的回调方法。
然后,我们再去找找,当我们发送获取code的请求时,怎么取code呢?
if (resp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {
SendAuth.Resp authResp = (SendAuth.Resp)resp;
String code = authResp.code;
}
判断如是SendAuth.Resp
,那就是获取资料请求,然后只执行我们自己的逻辑,否则,则执行友盟原有逻辑。
然后就是去找友盟中的SendAuth.Resp
类,经过查找,发现是友盟中的com.umeng.weixin.umengwx.i
类
public void b(Bundle var1) {
super.b(var1);
this.e = var1.getString("_wxapi_sendauth_resp_token");
this.f = var1.getString("_wxapi_sendauth_resp_state");
this.g = var1.getString("_wxapi_sendauth_resp_url");
this.h = var1.getString("_wxapi_sendauth_resp_lang");
this.i = var1.getString("_wxapi_sendauth_resp_country");
}
public void a(Bundle var1) {
super.a(var1);
var1.putString("_wxapi_sendauth_resp_token", this.e);
var1.putString("_wxapi_sendauth_resp_state", this.f);
var1.putString("_wxapi_sendauth_resp_url", this.g);
var1.putString("_wxapi_sendauth_resp_lang", this.h);
var1.putString("_wxapi_sendauth_resp_country", this.i);
}
SendAuth.Resp
部分代码
public void fromBundle(Bundle var1) {
super.fromBundle(var1);
this.code = var1.getString("_wxapi_sendauth_resp_token");
this.state = var1.getString("_wxapi_sendauth_resp_state");
this.url = var1.getString("_wxapi_sendauth_resp_url");
this.lang = var1.getString("_wxapi_sendauth_resp_lang");
this.country = var1.getString("_wxapi_sendauth_resp_country");
}
public void toBundle(Bundle var1) {
super.toBundle(var1);
var1.putString("_wxapi_sendauth_resp_token", this.code);
var1.putString("_wxapi_sendauth_resp_state", this.state);
var1.putString("_wxapi_sendauth_resp_url", this.url);
var1.putString("_wxapi_sendauth_resp_lang", this.lang);
var1.putString("_wxapi_sendauth_resp_country", this.country);
}
其中,i.e
即为我们需要的code,剩下的就简单了,修改WXEntryActivity.a(b var)
方法
@Override
public void a(com.umeng.weixin.umengwx.b b) {
if (b instanceof i) {
//处理我们自己的逻辑
} else {
super.a(b);
}
}
问题完美解决。