今天给小伙伴们奉上一篇第三方微信登录的实现
工程结构
因为是一个demo做的比较简陋,望小伙伴们见谅
准备工作。我们首先需要去微信平台申请的app应用,绑定一个app,并去申请功能的使用权限
在微信平台的申请的那个app,打包后(非debug包),在打包后的app应用软件里面下载一个app签名工具,在app签名工具里面输入appmanifest里面的包名,包名是package里面的,一定要是这个包名,别把包名弄混了,最后生成一个签名,放在微信开放平台的信息输入框里面)
然后就是调用微信的回调类: WXEntryActivity 而且这个类名必须是这个,而这个类名必须在.wxapi包名下,不然微信无法掉起,并在AndroidManifest.xml配置(小伙伴们包名要用自己的包名哟)
然后去自己申请的app里面拿到appid和secret这两个key(如果小伙伴们的没有申请成功,可以使用我的key)
下面就开始看干货了
WXEntryActivity
package com.example.weixindemo.wxapi;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import org.json.JSONObject;
import okhttp3.Call;
import okhttp3.Response;
import com.example.weixindemo.App;
import com.example.weixindemo.MainActivity;
import com.example.weixindemo.NetUtils;
import com.example.weixindemo.NetUtils.MyNetCall;
import com.example.weixindemo.bean.WeixinBean;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
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.modelmsg.WXTextObject;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
private BaseResp resp = null;
public static String WX_APP_ID = "wx712ebdaa2ff851b6";
// 获取第一步的code后,请求以下链接获取access_token
private String GetCodeRequest = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
// 获取用户个人信息
private String GetUserInfo = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
private String WX_APP_SECRET = "67bc80cf2ee42da9fdcb1d3509fec472";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, WX_APP_ID, false);
api.handleIntent(getIntent(), this);
}
// 微信发送请求到第三方应用时,会回调到该方法
@Override
public void onReq(BaseReq req) {
finish();
}
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
@Override
public void onResp(BaseResp resp) {
String result = "";
if (resp != null) {
resp = resp;
}
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_OK:
result = "发送成功";
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
String code = ((SendAuth.Resp) resp).code;
Log.i("TGA", code + "------------");
/*
* 将你前面得到的AppID、AppSecret、code,拼接成URL 获取access_token等等的信息(微信)
*/
String get_access_token = getCodeRequest(code);
Map reqBody = new ConcurrentSkipListMap<>();
NetUtils netUtils = NetUtils.getInstance();
netUtils.postDataAsynToNet(get_access_token, reqBody,
new NetUtils.MyNetCall() {
@Override
public void success(Call call, Response response)
throws IOException {
String responseData = response.body().string();
parseJSONWithGSON(responseData);
}
@Override
public void failed(Call call, IOException e) {
}
});
finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
result = "发送取消";
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
finish();
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
result = "发送被拒绝";
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
finish();
break;
default:
result = "发送返回";
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
finish();
break;
}
}
/**
* 通过拼接的用户信息url获取用户信息
*
* @param user_info_url
*/
private void getUserInfo(String user_info_url) {
Map reqBody = new ConcurrentSkipListMap<>();
NetUtils netUtils = NetUtils.getInstance();
netUtils.postDataAsynToNet(user_info_url, reqBody,
new NetUtils.MyNetCall() {
@Override
public void success(Call call, Response response) throws IOException{
String str = response.body().string();
parseJSONUser(str);
}
@Override
public void failed(Call call, IOException e) {
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
finish();
}
/**
* 获取access_token的URL(微信)
*
* @param code
* 授权时,微信回调给的
* @return URL
*/
private String getCodeRequest(String code) {
String result = null;
GetCodeRequest = GetCodeRequest.replace("APPID",
urlEnodeUTF8(WX_APP_ID));
GetCodeRequest = GetCodeRequest.replace("SECRET",
urlEnodeUTF8(WX_APP_SECRET));
GetCodeRequest = GetCodeRequest.replace("CODE", urlEnodeUTF8(code));
result = GetCodeRequest;
return result;
}
/**
* 获取用户个人信息的URL(微信)
*
* @param access_token
* 获取access_token时给的
* @param openid
* 获取access_token时给的
* @return URL
*/
private String getUserInfo(String access_token, String openid) {
String result = null;
GetUserInfo = GetUserInfo.replace("ACCESS_TOKEN",
urlEnodeUTF8(access_token));
GetUserInfo = GetUserInfo.replace("OPENID", urlEnodeUTF8(openid));
result = GetUserInfo;
return result;
}
private String urlEnodeUTF8(String str) {
String result = str;
try {
result = URLEncoder.encode(str, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
// 解析返回的数据
private void parseJSONWithGSON(String jsonData) {
// 使用轻量级的Gson解析得到的json
Gson gson = new Gson();
WeixinBean appList = gson.fromJson(jsonData,
new TypeToken() {
}.getType());
// 控制台输出结果,便于查看
String str = getUserInfo(appList.getAccess_token(), appList.getOpenid());
getUserInfo(str);
}
// 解析用户信息
private void parseJSONUser(String jsonData) {
// 使用轻量级的Gson解析得到的json
Gson gson = new Gson();
WeixinBean appList = gson.fromJson(jsonData,
new TypeToken() {
}.getType());
// 控制台输出结果,便于查看
Intent intent=new Intent(WXEntryActivity.this,MainActivity.class);
String str=appList.getSex()==1?" 性别:男" : " 性别:女";
intent.putExtra("username", "微信昵称:"+appList.getNickname());
intent.putExtra("sex", str);
startActivity(intent);
}
}
MainActivity
package com.example.weixindemo;
import com.example.weixindemo.wxapi.WXEntryActivity;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button btnlogin;
private TextView txt;
// 微信api
private IWXAPI api;
// 官方网站申请的appid
// private static final String APP_ID = "wx712ebdaa2ff851b6";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 启动activity时不自动弹出软键盘
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
btnlogin = (Button) findViewById(R.id.btnlogin);
txt= (TextView) findViewById(R.id.txt);
btnlogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
wxLogin();
}
});
}
// 调用微信登录
public void wxLogin() {
// 通过WXAPIFactory工厂获取IWXApI的示例
api = WXAPIFactory.createWXAPI(this, WXEntryActivity.WX_APP_ID, true);
// 将应用的appid注册到微信
api.registerApp(WXEntryActivity.WX_APP_ID);
if (api != null && api.isWXAppInstalled()) {
SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk_demo";
api.sendReq(req);
} else{
Toast.makeText(this, "用户未安装微信", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onResume() {
super.onResume();
App.username=getIntent().getStringExtra("username");
App.sex=getIntent().getStringExtra("sex");
if(!"".equals(App.username) && App.username!=null){
txt.setText(App.username+App.sex);
}
}
}
NetUtils(okhttp网络访问工具类)
package com.example.weixindemo;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class NetUtils {
private static final byte[] LOCKER = new byte[0];
private static NetUtils mInstance;
private OkHttpClient mOkHttpClient;
private NetUtils() {
okhttp3.OkHttpClient.Builder ClientBuilder=new okhttp3.OkHttpClient.Builder();
ClientBuilder.readTimeout(20, TimeUnit.SECONDS);//读取超时
ClientBuilder.connectTimeout(6, TimeUnit.SECONDS);//连接超时
ClientBuilder.writeTimeout(60, TimeUnit.SECONDS);//写入超时
//支持HTTPS请求,跳过证书验证
ClientBuilder.sslSocketFactory(createSSLSocketFactory());
ClientBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
mOkHttpClient=ClientBuilder.build();
}
/**
* 单例模式获取NetUtils
* @return
*/
public static NetUtils getInstance() {
if (mInstance == null) {
synchronized (LOCKER) {
if (mInstance == null) {
mInstance = new NetUtils();
}
}
}
return mInstance;
}
/**
* get请求,同步方式,获取网络数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
* @param url
* @return
*/
public Response getDataSynFromNet(String url) {
//1 构造Request
Request.Builder builder = new Request.Builder();
Request request=builder.get().url(url).build();
//2 将Request封装为Call
Call call = mOkHttpClient.newCall(request);
//3 执行Call,得到response
Response response = null;
try {
response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
/**
* post请求,同步方式,提交数据,是在主线程中执行的,需要新起线程,将其放到子线程中执行
* @param url
* @param bodyParams
* @return
*/
public Response postDataSynToNet(String url,Map bodyParams) {
//1构造RequestBody
RequestBody body=setRequestBody(bodyParams);
//2 构造Request
Request.Builder requestBuilder = new Request.Builder();
Request request = requestBuilder.post(body).url(url).build();
//3 将Request封装为Call
Call call = mOkHttpClient.newCall(request);
//4 执行Call,得到response
Response response = null;
try {
response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
/**
* 自定义网络回调接口
*/
public interface MyNetCall{
void success(Call call, Response response) throws IOException;
void failed(Call call, IOException e);
}
/**
* get请求,异步方式,获取网络数据,是在子线程中执行的,需要切换到主线程才能更新UI
* @param url
* @param myNetCall
* @return
*/
public void getDataAsynFromNet(String url, final MyNetCall myNetCall) {
//1 构造Request
Request.Builder builder = new Request.Builder();
Request request=builder.get().url(url).build();
//2 将Request封装为Call
Call call = mOkHttpClient.newCall(request);
//3 执行Call
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
myNetCall.failed(call,e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
myNetCall.success(call,response);
}
});
}
/**
* post请求,异步方式,提交数据,是在子线程中执行的,需要切换到主线程才能更新UI
* @param url
* @param bodyParams
* @param myNetCall
*/
public void postDataAsynToNet(String url, Map bodyParams, final MyNetCall myNetCall) {
//1构造RequestBody
RequestBody body=setRequestBody(bodyParams);
//2 构造Request
Request.Builder requestBuilder = new Request.Builder();
Request request = requestBuilder.post(body).url(url).build();
//3 将Request封装为Call
Call call = mOkHttpClient.newCall(request);
//4 执行Call
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
myNetCall.failed(call,e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
myNetCall.success(call,response);
}
});
}
/**
* post的请求参数,构造RequestBody
* @param BodyParams
* @return
*/
private RequestBody setRequestBody(Map BodyParams){
RequestBody body=null;
okhttp3.FormBody.Builder formEncodingBuilder=new okhttp3.FormBody.Builder();
if(BodyParams != null){
Iterator iterator = BodyParams.keySet().iterator();
String key = "";
while (iterator.hasNext()) {
key = iterator.next().toString();
formEncodingBuilder.add(key, BodyParams.get(key));
}
}
body=formEncodingBuilder.build();
return body;
}
/**
* 生成安全套接字工厂,用于https请求的证书跳过
* @return
*/
public SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
}
return ssfFactory;
}
/**
* 用于信任所有证书
*/
class TrustAllCerts implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}
最后我把清单文件也贴一下
到此今天的文章就结束啦,感谢大家支持。
我的博客主页
附demo下载地址