Android-微信登录坑(+友盟微信登录)
一开始本来打算用友盟登录,因为之前接入的就是友盟,什么推送呀,什么分享呀,都是友盟的。主要是使用起来比较方便。 当然微信支付还是接的原生的啦。。。
后来增加了第三方登录,而友盟也可以,而且使用起来很方便:
来个友盟登录接入链接:http://dev.umeng.com/social/android/login-page
只要回调里面获取后台需要的字段即可,看后台需要什么再获取就是了...我们家没有要头像..
@Override
public void onComplete(SHARE_MEDIA share_media, int i, Map<String, String> map) {
uid = map.get("uid");
switch (share_media){
case QQ:
type = "2";
break;
case WEIXIN:
type = "3";
break;
case SINA:
type = "4";
break;
}
presenter.loginThird(type, uid);
}
然后呢?AppID? appSecret? 如果你之前有集成过友盟的分享,你应该配置过:
image没问题的话,回调就妥妥的呢。但是我调试了一个上午都不回调?网上找相关问题,各种尝试都不行? 这个密钥我也是从之前的二手项目拷贝过来的。到了下午,我和ios进行了密钥对比,发现我的和它不一样,appid倒是一样的。我去。。赶紧试试,果然可以了? 我的天啦。。。。
微信复杂麻烦的地方就是这些错误导致的不回调,没有什么日志可看。。哎! 记得14年前接微信支付的时候,折腾了一个星期,那个官方demo貌似是人事部写的一样,那个乱呀。。。我就搞不懂了一个这么大的团队,demo如此之乱,让我们这些小白还如何仰望星空??支付宝接了一天就搞定,微信愣是各种折腾....
好吧!不吐槽了。。。我吐槽也是因为至少我们都是付费了都,你要是免费我们就不说了,对吧。。。哈哈。。。
回归正题,我下午调试的时候就想着采用微信原生的登录再试试吧!看看到底是友盟有点问题还是说我自己写的哪里有问题...
So, 微信的原生登录也是不简单的呢? 可能人家那样设计比较安全吧...
想看文档的可以看看,不想看的就算了,写的说明还行,不过具体还是得看demo或者有人实践过的资料。。。 不过呀!网上的资料也是五花八门,各种问题,有些代码贴出来你粘贴过来还需要修改,有些代码用到了别的工具类,但是呢?人家没有贴出来。。有的说是不能用post方法,但是呢?我试了可以呀。。 反正各种奇怪的的都有。。。
这里我就基于OkHttp3来搞下了哈。。。也懒得去搞什么工具类了。。。
主要就是一个回调处理, 一个请求处理, xxxx得地方需要注意。另外NotGuard的类我之前有文章(混淆那个地方提过... - 你可以去掉,没有关系); Json解析我用的是fastjson,后面我贴出来....
请求:
/**
* 微信的登录
*/
private IWXAPI api;
onCreate里面:
{
///< 报名服务
api = WXAPIFactory.createWXAPI(this, "替换为你的appid", true);
api.registerApp("替换为你的appid");
}
然后请求:
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo_test";
api.sendReq(req);
回调(WXEntryActivity.java, 这个文件做了一些的再熟悉不过了):
//package com.xxxxxxx.app.wxapi;
//
//import android.app.Activity;
//import android.os.Bundle;
//import android.support.annotation.Nullable;
//import android.util.Log;
//
//import com.xxxxxxx.app.bean.Constants;
//import com.tencent.mm.opensdk.modelbase.BaseReq;
//import com.tencent.mm.opensdk.modelbase.BaseResp;
//import com.tencent.mm.opensdk.modelmsg.SendAuth;
//import com.tencent.mm.opensdk.openapi.IWXAPI;
//import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
//import com.tencent.mm.opensdk.openapi.WXAPIFactory;
//import com.umeng.socialize.weixin.view.WXCallbackActivity;
//
//import java.io.IOException;
//
//import okhttp3.Call;
//import okhttp3.Callback;
//import okhttp3.FormBody;
//import okhttp3.OkHttpClient;
//import okhttp3.Request;
//import okhttp3.RequestBody;
//import okhttp3.Response;
//
///**
// * Created by hl on 2018/3/19.
// */
//
//public class WXEntryActivity extends WXCallbackActivity {
//}
package com.xxxxxxx.app.wxapi;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.xxxxxxx.app.bean.AccessToken;
import com.xxxxxxx.app.bean.Constants;
import com.xxxxxxx.app.bean.WXUserInfo;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by hl on 2018/3/19.
*/
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = "WXEntryActivity";
private static final int RETURN_MSG_TYPE_LOGIN = 1; ///< 登录
private static final int RETURN_MSG_TYPE_SHARE = 2; ///< 分享
private IWXAPI api;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
///< 这句没有写,是不能执行回调的方法的
api = WXAPIFactory.createWXAPI(this, Constants.APP_ID, false);
api.handleIntent(getIntent(), this);
}
@Override
public void onReq(BaseReq baseReq) {
Log.e(TAG, "onReq" + baseReq.getType());
}
@Override
public void onResp(BaseResp baseResp) {
Log.e(TAG, "onResp:------>");
Log.e(TAG, "error_code:---->" + baseResp.errCode);
int type = baseResp.getType(); //类型:分享还是登录
switch (baseResp.errCode) {
case BaseResp.ErrCode.ERR_AUTH_DENIED:
///< 用户拒绝授权
finish();
case BaseResp.ErrCode.ERR_USER_CANCEL:
///< 用户取消
String message = "";
if (type == RETURN_MSG_TYPE_LOGIN) {
message = "取消了微信登录";
} else if (type == RETURN_MSG_TYPE_SHARE) {
message = "取消了微信分享";
}
finish();
break;
case BaseResp.ErrCode.ERR_OK:
if (type == RETURN_MSG_TYPE_LOGIN) {
///< 用户换取access_token的code,仅在ErrCode为0时有效
String code = ((SendAuth.Resp) baseResp).code;
///< 这里拿到了这个code,去做2次网络请求获取access_token和用户个人信息
getAccessToken(code);
} else if (type == RETURN_MSG_TYPE_SHARE) {
///< "微信分享成功"
finish();
}
break;
}
}
/**
* @param code 根据code再去获取AccessToken
*/
private void getAccessToken(String code) {
// String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
OkHttpClient mOkHttpClient = new OkHttpClient();
///< Post方式也可以...
// RequestBody body = new FormBody.Builder()
// .add("appid", "替换为你的appid")
// .add("secret", "替换为你的app密钥")
// .add("code", code)
// .add("grant_type", "authorization_code")
// .build();
url += "?appid=" + "替换为你的appid" + "&secret=xxxxxxxx"
+ "&code=" + code + "&grant_type=authorization_code";
final Request request = new Request.Builder()
.url(url)
//.post(body)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
finish();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String json = response.body().string();
AccessToken accessToken = JSONObject.parseObject(json, new TypeReference<AccessToken>() {
});
getUserInfo(accessToken.getAccess_token(), accessToken.getOpenid());
}
});
}
/**
* @param access_token 根据access_token再去获取UserInfo
*/
private void getUserInfo(String access_token, String openid) {
// String url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
String url = "https://api.weixin.qq.com/sns/userinfo";
OkHttpClient mOkHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("access_token", access_token)
.add("openid", openid)
.build();
final Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
finish();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String json = response.body().string();
WXUserInfo wxUserInfo = JSONObject.parseObject(json, new TypeReference<WXUserInfo>() {
});
///< 发送广播到登录界面,把数据带过去; 可用EventBus
finish();
}
});
}
}
涉及到的几个实体类:
package com.xxxxxx.app.bean;
import com.xxxxxx.app.anotation.NotProguard;
@NotProguard
public class AccessToken {
/**
* access_token : xxxx
* expires_in : xxxx
* refresh_token : xxxxx
* openid : xxxxx
* scope : xxxxx
* unionid : xxxxx
*/
private String access_token;
private int expires_in;
private String refresh_token;
private String openid;
private String scope;
private String unionid;
private AccessToken(){}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
}
WXUserInfo.java
package com.xxxxxx.app.bean;
import com.xxxxxx.app.anotation.NotProguard;
@NotProguard
public class WXUserInfo {
/**
* openid : xxxxxxx
* nickname : xxxxxxx
* sex : 1
* language : zh_CN
* city : Chengdu
* province : Sichuan
* country : CN
* headimgurl :xxxxxx
* privilege : []
* unionid : xxxxxxx
*/
private String openid;
private String nickname;
private int sex;
private String language;
private String city;
private String province;
private String country;
private String headimgurl;
private String unionid;
private WXUserInfo(){}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getHeadimgurl() {
return headimgurl;
}
public void setHeadimgurl(String headimgurl) {
this.headimgurl = headimgurl;
}
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
}
一些库:
///< fastjson
compile 'com.alibaba:fastjson:1.1.68.android'
So, 告一个段落....无聊的xxx信...哼哼哈哈...