友盟分享与原生微信获取code冲突

前言

由于历史遗留问题,项目中微信登录用的是原生微信的登录,即先请求 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);
        }
}

问题完美解决。

你可能感兴趣的:(友盟分享与原生微信获取code冲突)