一、首先在微信开放平台申请移动应用
1、通过微信开放平台创建移动应用,获取到AppID和AppSecret
2、参考文档:安卓接入微信登录指南
二、安卓端接入微信SDK(通过as工具)
1、微信登录回调核心类:WXEntryActivity,微信主要微信登录回调。
package 包名.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
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.unity3d.player.UnityPlayer;
import com.xzq.LittleBell.util.Constants;
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
///通知Unity哪个物体GameObjectName 哪个方法CallBackFuncName
public static String GameObjectName = "GameObjectName";//GameObjectName 的 WXPayCallback方法
public static String CallBackFuncName = "WXPayCallback";//
//监听支付回调的对象
private IWXAPI api;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建微信API对象
api = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID);
//把接受到的Intent给wxapi这个对象,它会解析回调结果,通过我们实现的IWXAPIEventHandler接口回调给我们
api.handleIntent(getIntent(), this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
// 微信发送请求到第三方应用时,会回调到该方法
@Override
public void onReq(BaseReq req) {
switch (req.getType()) {
case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
break;
case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
break;
case ConstantsAPI.COMMAND_LAUNCH_BY_WX:
break;
default:
break;
}
}
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
@Override
public void onResp(BaseResp resp) {
// UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName, "回调响应");
switch (resp.getType()) {
case ConstantsAPI.COMMAND_LAUNCH_BY_WX:
break;
case ConstantsAPI.COMMAND_SENDAUTH:
onSendAuthResp(resp);
break;
default:
break;
}
finish();
}
/**
* 授权回调,获取code后发往服务端,获取access_token
* @param resp
*/
public void onSendAuthResp(BaseResp resp) {
int errorCode = resp.errCode;
switch (errorCode)
{
case BaseResp.ErrCode.ERR_OK:
//用户同意
//SendAuth.Resp authResp = (SendAuth.Resp) resp;
String code = ((SendAuth.Resp) resp).code;
UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName, "0;"+code);
UnityPlayer.UnitySendMessage(GameObjectName,"ShowText", "用户同意");
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
//用户拒绝
UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName, "-4;用户拒绝");
UnityPlayer.UnitySendMessage(GameObjectName,"ShowText", "用户拒绝");
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
//用户取消
UnityPlayer.UnitySendMessage(GameObjectName,CallBackFuncName, "-2;用户取消");
UnityPlayer.UnitySendMessage(GameObjectName,"ShowText", "用户取消");
break;
}
}
}
2、MainActivity类中发起微信登录请求事件
package 包名;
import android.os.Bundle;
import com.tencent.mm.opensdk.modelmsg.SendAuth;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import com.xzq.LittleBell.util.Constants;
import com.xzq.LittleBell.wxapi.WXEntryActivity;
import com.xzq.LittleBell.wxapi.WXPayEntryActivity;
public class MainActivity extends UnityPlayerActivity {
//这个对象用于封装支付参数 微信封装好的一个类
private PayReq req = new PayReq();
//调起微信支付API的对象
private IWXAPI msgApi =null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//创建微信API对象
msgApi = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID);
//在这里 把我们的APP注册进来
msgApi.registerApp(Constants.WX_APP_ID);
}
/**
* 调用微信登录
*/
public void openWechatLogin(String callBackBackObjectName,String CallBackFuncName) {
WXEntryActivity.GameObjectName = callBackBackObjectName;
WXEntryActivity.CallBackFuncName = CallBackFuncName;
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "wechat_sdk";
msgApi.sendReq(req);
}
}
3、一个Constans类
package 包名.util;
public class Constants {
public static String WX_APP_ID = "***";//从微信开放平台申请得到的APPID
}
4、然后接下来主要就是build.gradle配置
apply plugin: 'com.android.library'//注意这里的更改
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
// applicationId "***"//这个屏蔽掉
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
// testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
afterEvaluate {
generateReleaseBuildConfig.enabled = false
generateDebugBuildConfig.enabled = false
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.alibaba:fastjson:1.1.54.android'
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:5.3.1'
implementation files('libs/classes.jar')//unity的与安卓交互的classes.jar
implementation files('libs/libammsdk.jar')//微信登录或支付的sdk jar包
}
5、AndroidMainifest配置
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden">
解压来就可以Build------>Rebuild Project.会在项目目录outputs下生成一个app-debug.aar文件。
三、Unity端配置
1、声明一个LoginController.cs类挂载到Login_Panel面板上
//声明变量
#if UNITY_ANDROID && !UNITY_EDITOR
private AndroidJavaObject _androidObj = null;
#endif
//初始化
private void Awake()
{
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
_androidObj = jc.GetStatic("currentActivity");
#endif
}
//调起微信授权登录处理
public void SendWxLogin()
{
try {
object[] objs = new object[] { "Login_Panel", "LoginCallBack" };
#if UNITY_ANDROID && !UNITY_EDITOR
_androidObj.Call("openWechatLogin", objs);
#endif
}
catch (Exception err)
{
Debug.Log("微信授权异常:"+err.Message);
}
}
///
/// 登录回调,将获取到的code,去服务器经过二次签名。
///
///
public void LoginCallBack(string msg)
{
if (msg !=null && msg != "" && msg.Contains(";"))
{
string[] str = msg.Split(';');
if (str != null && str.Length == 2)
{
switch (str[0])
{
case "-1":
PublicUtils.ShowAndroidToastMessage(str[1]);
break;
case "-2":
PublicUtils.ShowAndroidToastMessage(str[1]);
break;
case "0":
PublicUtils.ShowAndroidToastMessage("授权成功");
BaseController.LoadingWaiting();
string SERVICE_URL = PublicEntity.HTTP_SERVICE_URL + "wxpay/getAccessToken.do";
string LOGIN_FLAG = PublicEntity.LOGIN_FLAG;
WWWForm form = new WWWForm();
form.AddField("code", str[1]);
form.AddField("LOGIN_FLAG", LOGIN_FLAG);
StartCoroutine(HttpManager.SendHttpRequest(SERVICE_URL, form, msg, null));
break;
default:
PublicUtils.ShowAndroidToastMessage("授权失败");
break;
}
}
else
{
PublicUtils.ShowAndroidToastMessage("微信授权失败");
}
}
else
{
PublicUtils.ShowAndroidToastMessage("微信授权失败");
}
}
2、这里要注意一个问题,微信登录token是有时间限制,如果时间没有到,即token还有效,可以直接去登陆。即在授权登录之前先判断下是否token有效
///
/// 通过access_token调用接口,以下参数可以在第一次授权登录成功后,保存起来。
/// @param openid ---应用唯一标识,在微信开放平台提交应用审核通过获得
/// @param access_token---接口调用凭证
/// @param expires_in---接口调用凭证超时时间,单位(秒)
/// @param refresh_token---用户刷新access_token
/// @param LIMIT_TIME----到期时间
///
public void isAccessTokenIsInvalid(string openid, string access_token, long expires_in, string refresh_token,string LIMIT_TIME)
{
BaseController.LoadingWaiting();
string SERVICE_URL = SERVICE_URL = PublicEntity.HTTP_SERVICE_URL + "wxpay/isAccessTokenIsInvalid.do";
string LOGIN_FLAG = PublicEntity.LOGIN_FLAG;
WWWForm form = new WWWForm();
form.AddField("openid", openid);
form.AddField("access_token", access_token);
form.AddField("expires_in", expires_in.ToString());
form.AddField("refresh_token", refresh_token);
form.AddField("LIMIT_TIME", LIMIT_TIME);
StartCoroutine(HttpManager.SendHttpRequest(SERVICE_URL, form, openid, null));
}
3、token有效直接登录,token重新获取新的token
///
/// 微信Openid登录,token有效,则去登陆
///
public void wxOpenIdLogin(string OpenId)
{
BaseController.LoadingWaiting();
string SERVICE_URL = PublicEntity.HTTP_SERVICE_URL + "wxpay/wxOpenIdLogin.do";
string LOGIN_FLAG = PublicEntity.LOGIN_FLAG;
WWWForm form = new WWWForm();
form.AddField("OpenId", OpenId);
form.AddField("LOGIN_FLAG", LOGIN_FLAG);
StartCoroutine(HttpManager.SendHttpRequest(SERVICE_URL, form, OpenId, null));
}
///token无效,则重新获取刷新token
public void refreshAccessToken(string openid,string refresh_token,long expires_in)
{
BaseController.LoadingWaiting();
string SERVICE_URL = PublicEntity.HTTP_SERVICE_URL + "wxpay/refreshAccessToken.do";
WWWForm form = new WWWForm();
form.AddField("openid", openid);
form.AddField("refresh_token", refresh_token);
form.AddField("expires_in", expires_in.ToString());
StartCoroutine(HttpManager.SendHttpRequest(SERVICE_URL, form, openid, null));
}
四、服务端配置(java:springmvc+mybatis)
1、核心工具类(AuthUtil.java)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import com.alibaba.fastjson.JSONObject;
/**
* 微信授权登录调用Util
* 参考网址:https://www.cnblogs.com/benwu/articles/5705604.html
*/
public class AuthUtil {
//通过code获取access_token地址
public final static String WXLOGIN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
//验证access_token是否有效地址
public final static String WXACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/auth?access_token=";
//通过access_token调用接口,获取用户信息
public final static String WXGETUSER_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=";
//refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权
public final static String WXREFRESH_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=";
//应用唯一标识,在微信开放平台提交应用审核通过获得
public static final String APPID = "wx********";
//应用秘钥AppSecret,在微信开放平台提交应用审核通过后获得
public static final String APPSECRET = "1c87*********************";
//获取access_token
public static JSONObject doGetJson(String URL) throws IOException {
JSONObject jsonObject = null;
HttpURLConnection conn = null;
InputStream is = null;
BufferedReader br = null;
StringBuilder result = new StringBuilder();
try {
//创建远程url连接对象
URL url = new URL(URL);
//通过远程url连接对象打开一个连接,强转成HTTPURLConnection类
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//设置连接超时时间和读取超时时间
conn.setConnectTimeout(15000);
conn.setReadTimeout(60000);
conn.setRequestProperty("Accept", "application/json");
//发送请求
conn.connect();
//通过conn取得输入流,并使用Reader读取
if (200 == conn.getResponseCode()) {
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
result.append(line);
System.out.println(line);
}
} else {
System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
conn.disconnect();
}
jsonObject = JSONObject.parseObject(result.toString());
return jsonObject;
}
/**
* 微信重复登录
* @param accessToken
* @param openID
* @return
*/
public static boolean isAccessTokenIsInvalid(String accessToken,String openID) {
try{
String url = WXACCESS_TOKEN_URL + accessToken + "&openid=" + openID+"&lang=zh_CN";
JSONObject jsonObject = doGetJson(url);
System.out.println("isAccessTokenIsInvalid:"+jsonObject.toString());
int errorCode = Integer.parseInt(jsonObject.get("errcode").toString());
if(errorCode == 0)
{
return true;
}
}
catch(Exception err)
{
System.out.println("isAccessTokenIsInvalid is error:"+err.getMessage());
}
return false;
}
/**
* 刷新AccessToken
*/
public static JSONObject refreshAccessToken(String refreshToken) {
try{
String uri = WXREFRESH_URL + APPID + "&grant_type=refresh_token&refresh_token=" + refreshToken;
System.out.println("uri="+uri);
return doGetJson(uri);
}
catch(Exception err)
{
System.out.println("refreshAccessToken is error:"+err.getMessage());
}
return null;
}
}
2、服务端与unity客户端交互WXLoginController.java
/**
* 通过code获取access_token
* @param code
* @param LOGIN_FLAG
* @return
* @throws Exception
*/
@RequestMapping(value="/getAccessToken")
@ResponseBody
public Object getAccessToken() throws Exception{
logBefore(logger, "通过code获取access_token");
Map map = new HashMap();
PageData pd = new PageData();
pd = this.getPageData();
String result = WeixinConsts.FAIL;
try{
String code = pd.getString("code");
System.out.println("code="+code);
//1、通过第一步获得的code,2、获取微信授权信息access_token
//参数说明:
//appid:应用唯一标识,在微信开放平台提交应用审核通过获得
//secret:应用秘钥AppSecret,在微信开放平台提交应用审核通过后获得
//code :填写第一步获取的code参数
//grant_type:填authorization_code
String url = AuthUtil.WXLOGIN_URL+"?appid=" + AuthUtil.APPID + "&secret="
+ AuthUtil.APPSECRET + "&code=" + code + "&grant_type=authorization_code";
JSONObject jsonObject = AuthUtil.doGetJson(url);
if(jsonObject != null && jsonObject.toString().contains("access_token"))
{
String openid = jsonObject.getString("openid");//授权用户唯一标识
String access_token = jsonObject.getString("access_token");//接口调用凭证
long expires_in = Long.parseLong(jsonObject.get("expires_in").toString());//接口调用凭证超时时间,单位(秒)
String LIMIT_TIME = DateUtil.getAfterDataSS(-expires_in);
String refresh_token = jsonObject.getString("refresh_token");//用户刷新access_token
String unionid = jsonObject.getString("unionid");
System.out.println("openid="+openid+";access_token"+access_token+";expires_in="+expires_in+";refresh_token="+refresh_token+";unionid="+unionid);
System.out.println("LIMIT_TIME="+LIMIT_TIME+";expires_in="+expires_in);
map.put("openid", openid);
map.put("access_token", access_token);
map.put("expires_in", expires_in);
map.put("refresh_token", refresh_token);
map.put("LIMIT_TIME", LIMIT_TIME);//获得n秒后的时间
map.put("message", "获取用户接口调用凭证成功!");
result = ClientConsts.GET_TOKEN_SUCCESS;
}
else
{
System.out.println("获取微信授权信息access_token失败..url="+url);
map.put("message", "获取用户接口调用凭证失败!");
result = ClientConsts.GET_TOKEN_FAIL;
}
}
catch (Exception e){
logger.error(e.toString(), e);
result = ClientConsts.ERROR;
map.put("message", "微信登录失败,请求异常!");
}finally{
map.put("LoginMethod", "1");//微信
map.put("result", result);
logAfter(logger);
}
return AppUtil.returnObject(new PageData(), map);
}
/**
* 验证access_token是否有效
*
* @param access_token
* @param openid
*@param expires_in到期时长
* @param refresh_token
* @param LIMIT_TIME到期时间
* @return
* @throws Exception
*/
@RequestMapping(value="/isAccessTokenIsInvalid")
@ResponseBody
public Object isAccessTokenIsInvalid() throws Exception{
logBefore(logger, "微信验证access_token是否有效");
Map map = new HashMap();
PageData pd = new PageData();
pd = this.getPageData();
String result = WeixinConsts.FAIL;
try{
String access_token = pd.getString("access_token");
String openid = pd.getString("openid");
long expires_in = Long.parseLong(pd.getString("expires_in"));//接口调用凭证超时时间,单位(秒)&& System.currentTimeMillis() < expires_in
String LIMIT_TIME = pd.getString("LIMIT_TIME");
boolean flag = false;
if(LIMIT_TIME!=null && !"".equals(LIMIT_TIME))
{
flag = DateUtil.compareDate2(LIMIT_TIME, DateUtil.getTime());//有效期间
}
System.out.println("LIMIT_TIME:"+LIMIT_TIME+";flag="+flag);
if(AuthUtil.isAccessTokenIsInvalid(access_token,openid) && flag)
{
String infoUrl = AuthUtil.WXGETUSER_URL + access_token + "&openid="+openid;
JSONObject userJson = AuthUtil.doGetJson(infoUrl);
String nickname = userJson.getString("nickname");
// String headimgurl = userJson.getString("headimgurl");
// headimgurl = headimgurl.replace("\\", "");
// //String unionid = jsonObject.getString("unionid");
System.out.println("nickname="+nickname);
result = ClientConsts.ACCESS_TOKEN_SUCCESS;
map.put("message", "access_token有效");
map.put("STUNAME", nickname);
map.put("openid", openid);
}
else
{
result = ClientConsts.ACCESS_TOKEN_FAIL;
map.put("refresh_token", pd.getString("refresh_token"));
map.put("openid", pd.getString("openid"));
map.put("expires_in", expires_in);
map.put("message", "access_token无效");
}
}
catch (Exception e){
logger.error(e.toString(), e);
result = ClientConsts.ERROR;
map.put("message", "微信登录失败,请求异常!");
}finally{
map.put("LoginMethod", "1");//微信
map.put("result", result);
logAfter(logger);
}
return AppUtil.returnObject(new PageData(), map);
}
/**
* 重新获取access_token
*
* @param refresh_token
* @param openid
* @param expires_in
* @return access_token
* @throws Exception
*/
@RequestMapping(value="/refreshAccessToken")
@ResponseBody
public Object refreshAccessToken() throws Exception{
logBefore(logger, "重新获取access_token");
Map map = new HashMap();
PageData pd = new PageData();
pd = this.getPageData();
String result = WeixinConsts.FAIL;
try{
String refresh_token = pd.getString("refresh_token");
String openid = pd.getString("openid");
JSONObject refreshTokenJson = AuthUtil.refreshAccessToken(refresh_token);
if(refreshTokenJson != null)
{
String access_token = refreshTokenJson.getString("access_token");//重新获取到access_token
long expires_in = 0l;
if(pd.getString("expires_in")!=null && !"".equals(pd.getString("expires_in")))
{
expires_in = Long.parseLong(pd.getString("expires_in"));//接口调用凭证超时时间,单位(秒)
}
String LIMIT_TIME = DateUtil.getAfterDataSS(-expires_in);
result = ClientConsts.REGET_TOKEN_SUCCESS;
map.put("access_token", access_token);
map.put("LIMIT_TIME", LIMIT_TIME);
map.put("message", "重新获取accessToken成功");
}
else
{
result = ClientConsts.ACCESS_TOKEN_FAIL;
map.put("message", "重新获取accessToken失败");
}
}
catch (Exception e){
logger.error(e.toString(), e);
result = ClientConsts.ERROR;
map.put("message", "重新获取accessToken失败,请求异常!");
}finally{
map.put("LoginMethod", "1");//微信
map.put("result", result);
logAfter(logger);
}
return AppUtil.returnObject(new PageData(), map);
}
/**
* 微信Openid登录
* @param ACCOUNT
* @return
* @throws Exception
*/
@RequestMapping(value="/wxOpenIdLogin")
@ResponseBody
public Object wxOpenIdLogin() throws Exception{
logBefore(logger, "微信OPENID登录");
Map map = new HashMap();
PageData pd = new PageData();
pd = this.getPageData();
String result = WeixinConsts.FAIL;
try{
//接下来跟后台交互判断是否有该用户,如果有则查询进行登录,如果没有进行注册后登录
if(wxPd != null)//登录
{
//更新登录信息
FHLOG.save(wxPd.getString("ACCOUNT"), "微信登录成功,移动端"+LOGIN_FLAG);
}else{//注册逻辑
//注册
}
}
catch (Exception e){
logger.error(e.toString(), e);
result = ClientConsts.ERROR;
map.put("message", "微信登录失败,请求异常!");
}finally{
map.put("LoginMethod", "1");//微信
map.put("result", result);
logAfter(logger);
}
return AppUtil.returnObject(new PageData(), map);
}
到这里就已经彻底的实现微信登录的逻辑了。
相关文档:
Unity IOS 接入微信登录
如有问题可以微信咨询,可扫描下方微信添加互相沟通:
如果对你有帮助,请给点赞助支持下奥!