相信很多第三方应用都使用到微信登陆,今天来详细讲解微信登陆的流程及实现。
1:微信登陆都有一个点击事件:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.get_verification:
sendVerificationCode();
break;
case R.id.phone_register:
Intent phoneRegisterIntent = new Intent(this, RegisterActivity.class);
startActivity(phoneRegisterIntent);
finish();
break;
case R.id.wechat_login:
WeiXinUtil.wxLogin();
break;
case R.id.login_layout:
checkThenLogin();
break;
default:
break;
}
}
2:按照1的步骤我们新建WeiXinUtil,并在其中实现wxLogin()方法
/**
* 微信登陆
* Created by acer-pc on 2018/8/20.
*/
public class WeiXinUtil {
public static void wxLogin() {
if (!WinnerApplication.mWxApi.isWXAppInstalled()) {
ToastUtil.toast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = BuildConfig.Weixin.state;
WinnerApplication.mWxApi.sendReq(req);
}
/**
* 绑定微信
*/
public static void wxBind() {
if (!WinnerApplication.mWxApi.isWXAppInstalled()) {
ToastUtil.toast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = BuildConfig.Weixin.state_bind;
WinnerApplication.mWxApi.sendReq(req);
}
public static void wxShareImg(Bitmap bitmap, int type) {
shareBitmapToWx(bitmap, type);
}
/**
* 分享图片到微信
* @param bmp
* @param type
*/
private static void shareBitmapToWx(Bitmap bmp, int type) {
try {
if (bmp == null) {
ToastUtil.toast("分享图片失败");
return;
}
WXImageObject imageObject = new WXImageObject(bmp);
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = imageObject;
Bitmap thumb = Bitmap.createScaledBitmap(bmp, 300, 300, true);
bmp.recycle();
msg.setThumbImage(thumb);
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = "img";
req.message = msg;
req.scene = type;
WinnerApplication.mWxApi.sendReq(req);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
3:定义全局变量和微信申请的应用开发账号和密码
/**
* 关于微信和APP之间的对接
* Created by acer-pc on 2018/8/16.
*/
public class BuildConfig {
public static class Weixin{
//自定义两个字段,用于微信登陆和绑定的时候调用微信接口的数据
public static final String state = "superwinner_wx_login_123";
public static final String state_bind = "superwinner_wx_bind_123";
//APP注册微信接口时申请的
public static final String APP_ID = "wx04583164f67d466d";
private static final String APP_SECRET = "6a6b5ed812b7c0b62f44e096f25a60fe";
public static final String ACCESS_TOKEN_URL_GET = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
APP_ID +
"&secret=" +
APP_SECRET +
"&code=" +
"CODE" +
"&grant_type=authorization_code";
public static final String ACCESS_TOKEN_VALID_URL_GET = "https://api.weixin.qq.com/sns/auth?access_token=" +
"ACCESS_TOKEN" +
"&openid=" +
"OPENID";
public static final String REFRESH_ACCESS_TOKEN_URL_GET = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" +
APP_ID +
"&grant_type=refresh_token&" +
"refresh_token=" +
"REFRESH_TOKEN";
public static final String USER_INFO_URL_GET = "https://api.weixin.qq.com/sns/userinfo?access_token=" +
"ACCESS_TOKEN" +
"&openid=" +
"OPENID";
public static String getAccessTokenUrl(String APP_ID, String APP_SECRET, String CODE){
return ACCESS_TOKEN_URL_GET.replace("APPID", APP_ID)
.replace("APPSECRET", APP_SECRET)
.replace("CODE", CODE);
}
}
}
4:微信登陆都会有一个返回的结果,需要我们自己定义
/**
* 定义一个接受微信返回的数据的Activity
* * Created by acer-pc on 2018/8/16.
*/
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//
try {
WinnerApplication.mWxApi.handleIntent(getIntent(), this);
finish();
} catch (Exception ex) {
ex.printStackTrace();
finish();
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Log.i("微信启动", "onNewIntent");
WinnerApplication.mWxApi.handleIntent(intent, this);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public void onReq(BaseReq baseReq) {
Log.i("微信请求发起","微信请求");
}
@Override
public void onResp(final BaseResp baseResp) {
Log.i("微信返回码", ((SendAuth.Resp) baseResp).errCode + "");
final boolean isLogin = BuildConfig.Weixin.state.equals(((SendAuth.Resp) baseResp).state);
final boolean isBind = BuildConfig.Weixin.state_bind.equals(((SendAuth.Resp) baseResp).state);
switch (((SendAuth.Resp) baseResp).errCode) {
case ERR_OK:
if (!(isLogin || isBind)) {
ToastUtil.toast("微信授权失败");
return;
} else {
break;
}
case ERR_USER_CANCEL:
ToastUtil.toast("用户取消");
finish();
return;
case ERR_AUTH_DENIED:
ToastUtil.toast("拒绝登陆");
break;
default:
finish();
return;
}
final String code = ((SendAuth.Resp) baseResp).code;
APIConfig.getDataIntoView(new Runnable() {
@Override
public void run() {
String rs = HttpUtil.GetDateFromNetByGet(BuildConfig.Weixin.ACCESS_TOKEN_URL_GET.replace("CODE", code), null);
final AccessToken accessToken = GsonUtil.parseJson(rs, AccessToken.class);
Log.d("AccessToken",accessToken.getAccess_token());
if (accessToken != null && accessToken.getErrcode() == null) {
RuntimeConfig.accessToken = accessToken;
final String userRs = HttpUtil.GetDateFromNetByGet(BuildConfig.Weixin.USER_INFO_URL_GET
.replace("ACCESS_TOKEN", RuntimeConfig.accessToken.getAccess_token())
.replace("OPENID", RuntimeConfig.accessToken.getOpenid())
, null);
WeixinUser weixinUser = GsonUtil.parseJson(userRs, WeixinUser.class);
if (weixinUser != null && weixinUser.getErrcode() == null) {
LogUtil.i("WXEntryActivity", "微信授权成功");
RuntimeConfig.weixinUser = weixinUser;
if (isBind) {
APIUtil.bindWeixin(WXEntryActivity.this);
} else if (isLogin) {
APIUtil.socialLogin(WXEntryActivity.this);
}
} else {
ToastUtil.toast("微信授权失败");
}
} else {
ToastUtil.toast("微信授权失败");
}
}
});
finish();
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}
5:定义全局的类用来保存获取到的用户信息等
**
* 保存一些全局变量,在整个应用中使用,避免过多的网络请求加载
* Created by acer-pc on 2018/7/26.
*/
public class APIUtil {
private final static String APPLICATION_CACHE_PATH = WinnerApplication.getContext().getCacheDir().getAbsolutePath();
public interface CallBack<T extends BaseResult> {
void handleResult(T result);
}
/**
* 保存用户打开APP的时候的token信息
* @param token 用户
*/
public static void saveToken(String token) {
RuntimeConfig.token = token;
String absolutePath = WinnerApplication.getContext().getCacheDir().getAbsolutePath();
AndroidFileUtil.writeStringToFile("true", absolutePath, DataConfig.PUSH_FILE_NAME);
AndroidFileUtil.writeStringToFile(token, absolutePath, DataConfig.TOKEN_FILE_NAME);
RuntimeConfig.FIRST_STARTUP = true;
}
/**
* 全局获取Token
* @return token
*/
public static String getToken() {
if (RuntimeConfig.token != null && !"".equals(RuntimeConfig.token)) {
return RuntimeConfig.token;
}
String token = AndroidFileUtil.readFileByLines(APPLICATION_CACHE_PATH + "/" + DataConfig.TOKEN_FILE_NAME);
RuntimeConfig.token = token;
return token;
}
/**
* 清空Token
*/
public static void clearToken() {
RuntimeConfig.token = "";
File file = new File(APPLICATION_CACHE_PATH + "/" + DataConfig.TOKEN_FILE_NAME);
AndroidFileUtil.deleteFile(file);
}
/**
* @return 判断是否拥有Token
*/
public static boolean hasToken() {
String token = getToken();
return token != null && !"".equals(token);
}
/**
* @return 当前用户是否登录
*/
public static boolean isLogin() {
User user = getUser();
return user != null && user.getId() != 0;
}
/**
* 设置用户信息
*/
public static void setUser(User user) {
RuntimeConfig.user = user;
String userJson = GsonUtil.toJson(user);
File diskCache = new File(APPLICATION_CACHE_PATH + "/" + DataConfig.USER_FILE_NAME);
AndroidFileUtil.deleteFile(diskCache);
AndroidFileUtil.writeStringToFile(userJson, APPLICATION_CACHE_PATH, DataConfig.USER_FILE_NAME);
}
/**
* @return 当前登录用户的信息
*/
public static User getUser() {
if (RuntimeConfig.user != null) {
return RuntimeConfig.user;
}
String userJson = AndroidFileUtil.readFileByLines(APPLICATION_CACHE_PATH + "/" + DataConfig.USER_FILE_NAME);
if (!"".equals(userJson)) {
RuntimeConfig.user = GsonUtil.parseJson(userJson, User.class);
}
return RuntimeConfig.user;
}
/**
* 清除用户缓存
*/
public static void clearUser() {
File diskCache = new File(APPLICATION_CACHE_PATH + "/" + DataConfig.USER_FILE_NAME);
AndroidFileUtil.deleteFile(diskCache);
RuntimeConfig.user = null;
}
/**
* 绑定微信
* @param activity
*/
public static void bindWeixin(final Activity activity) {
final String weixinId = RuntimeConfig.weixinUser.getOpenid();
APIConfig.getDataIntoView(new Runnable() {
@Override
public void run() {
String rs = HttpUtil.GetDataFromNetByPost(APIConfig.getORIGINALAPIUrl(APIConfig.API_USER_BIND_WEIXIN),
new ParamsBuilder()
.addParam("token", APIUtil.getToken())
.addParam("weixinId", weixinId)
.getParams());
RuntimeConfig.weixinUser = null;
LoginResult loginResult = GsonUtil.fromJson(rs, LoginResult.class);
if (loginResult != null && loginResult.getResult() == APIConfig.CODE_SUCCESS) {
RuntimeConfig.user = loginResult.getData();
}
activity.finish();
ToastUtil.toastByCode(loginResult);
}
});
}
/**
* 社交账号微信登录
*/
public static void socialLogin(final Activity activity) {
final String weixinId = RuntimeConfig.weixinUser.getOpenid();
final String userName = RuntimeConfig.weixinUser.getNickname();
final String sex = String.valueOf(RuntimeConfig.weixinUser.getSex());
final String headImgUrl = RuntimeConfig.weixinUser.getHeadimgurl();
APIConfig.getDataIntoView(new Runnable() {
@Override
public void run() {
Map<String,String> map=new HashMap<>();
map.put("weixinId", weixinId);
map.put("nickName", userName);
map.put("sex", sex);
map.put("headImgUrl", headImgUrl);
map.put("token",APIUtil.getToken());
//把分页信息传过去
String paramJson = EncryptUtil.encrypt(map);
String url = APIConfig.getORIGINALAPIUrl(APIConfig.API_USER_SSOBYWEIXIN);
String rs = HttpUtil.GetDataFromNetByPost(url, new ParamsBuilder().addParam("paramJson", paramJson).getParams());
RuntimeConfig.weixinUser = null;
LoginResult loginResult = EncryptUtil.decrypt(rs, LoginResult.class);
if (loginResult != null && loginResult.getResult() == APIConfig.CODE_SUCCESS) {
saveUserToken(loginResult.getData());
activity.finish();
} else {
ToastUtil.toastByCode(loginResult);
}
}
});
}
/**
* 保存用户登录信息
*
* @param user 用户
*/
public static void saveUserToken(User user) {
RuntimeConfig.user = user;
String absolutePath = WinnerApplication.getContext().getCacheDir().getAbsolutePath();
AndroidFileUtil.writeStringToFile("true", absolutePath, DataConfig.PUSH_FILE_NAME);
AndroidFileUtil.writeStringToFile(user.getToken(), absolutePath, DataConfig.TOKEN_FILE_NAME);
RuntimeConfig.FIRST_STARTUP = true;
}
}
6:微信登陆基本完成。