using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace SmartBowSDK
{
public class SmartBowNetwork : MonoBehaviour
{
public SmartBowHelper smartBowHelper;
// 本地 IP 地址(只在本地环境下生效)
static string localIPAddress = "192.168.0.108";
//是否使用本地环境
static bool isLocal = false;
// 服务器路径
static string serverPath = "/SmartBowBusinessServer";
// 最终服务器地址
static string serverURL => isLocal
? $"http://{localIPAddress}:11432{serverPath}"
: $"https://xmjssvr.cn{serverPath}";
//private string serverURL = "https://xmjssvr.cn/SmartBowBusinessServer";
//private const string serverURL = "http://127.0.0.1:11332/SmartBowBusinessServer";
private string loginToken;
///
/// 运行时设置本地 IP 并启用本地环境
///
public static void SetLocal(string ip)
{
isLocal = true;
localIPAddress = ip;
Debug.Log($"[SmartBowNetwork] 设置IP: {ip}");
}
///
/// 发送手机验证码
///
public void SendPhoneValidateCode(string phone, int language, Action callback)
{
string url = $"{serverURL}/phoneValidate/sendPhoneValidateCode" +
$"?phone={UnityWebRequest.EscapeURL(phone)}&language={language}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 验证手机验证码
///
public void ValidatePhoneCode(string phone, int code, Action callback)
{
string url = $"{serverURL}/phoneValidate/validatePhone" +
$"?phone={UnityWebRequest.EscapeURL(phone)}&code={code}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 发送邮箱验证码
///
public void SendEmailValidateCode(string email, int language, Action callback)
{
string url = $"{serverURL}/emailValidate/sendEmailValidateCode" +
$"?email={UnityWebRequest.EscapeURL(email)}&language={language}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 验证邮箱验证码
///
public void ValidateEmailCode(string email, int code, Action callback)
{
string url = $"{serverURL}/emailValidate/validateEmail" +
$"?email={UnityWebRequest.EscapeURL(email)}&code={code}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 用户注册
///
/// 服务器索引
/// 用户名
/// 密码
/// 邮箱
/// 手机号
/// 当前接收的code,海外用邮箱 serverIndex = 1,国内 serverIndex = 0用手机号
/// 回调
public void RegisterByCode(int serverIndex, string username, string password, string email, string phone,int code, Action callback)
{
string url = $"{serverURL}/gameLogin/registerByCode" +
$"?serverIndex={serverIndex}" +
$"&username={UnityWebRequest.EscapeURL(username)}" +
$"&password={UnityWebRequest.EscapeURL(password)}" +
$"&email={UnityWebRequest.EscapeURL(email)}" +
$"&phone={UnityWebRequest.EscapeURL(phone)}" +
$"&code={code}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
//public IEnumerator ListUsernamesByEmail(string email, long timestamp, string sign, Action callback)
//{
// string url = serverURL + "/gameLogin/listUsernamesByEmail";
// WWWForm form = new WWWForm();
// form.AddField("email", email);
// form.AddField("timestamp", timestamp.ToString());
// form.AddField("sign", sign);
// using (UnityWebRequest request = UnityWebRequest.Post(url, form))
// {
// yield return request.SendWebRequest();
// RequestResult requestResult = JsonConvert.DeserializeObject(request.downloadHandler.text);
// if (callback != null) callback(requestResult);
// }
//}
//public IEnumerator ListUsernamesByPhone(string phone, long timestamp, string sign, Action callback)
//{
// string url = serverURL + "/gameLogin/listUsernamesByPhone";
// WWWForm form = new WWWForm();
// form.AddField("phone", phone);
// form.AddField("timestamp", timestamp.ToString());
// form.AddField("sign", sign);
// using (UnityWebRequest request = UnityWebRequest.Post(url, form))
// {
// yield return request.SendWebRequest();
// RequestResult requestResult = JsonConvert.DeserializeObject(request.downloadHandler.text);
// if (callback != null) callback(requestResult);
// }
//}
//public IEnumerator ResetPassword(string sign, long timestamp, string username, string password, Action callback)
//{
// string url = serverURL + "/gameLogin/resetPassword";
// WWWForm form = new WWWForm();
// form.AddField("sign", sign);
// form.AddField("timestamp", timestamp.ToString());
// form.AddField("username", username);
// form.AddField("password", password);
// using (UnityWebRequest request = UnityWebRequest.Post(url, form))
// {
// yield return request.SendWebRequest();
// RequestResult requestResult = JsonConvert.DeserializeObject(request.downloadHandler.text);
// if (callback != null) callback(requestResult);
// }
//}
//重置密码
public void ResetPasswordByAccount(int serverIndex,string account, string codeAccount, int code, string newPassword, Action callback)
{
StartCoroutine(ResetPasswordByAccountCoroutine(serverIndex,account, codeAccount, code, newPassword, callback));
}
///
/// 重置密码流程,先验证Code,在获取list,再重置对应的账号。
/// 基本和弓箭app流程一样
///
///
///
///
///
///
///
///
private IEnumerator ResetPasswordByAccountCoroutine(int serverIndex,string account,string codeAccount, int code, string newPassword, Action callback)
{
RequestResult validateResult = null;
if (!(serverIndex >= 0 && serverIndex <= 2))
{
callback?.Invoke(new RequestResult
{
code = -10,
msg = "serverIndex 错误!",
});
yield break;
}
bool isPhone = serverIndex == 0 ? true : false;
// 1. 验证验证码
string validateUrl = isPhone
? $"{serverURL}/phoneValidate/validatePhone?phone={UnityWebRequest.EscapeURL(codeAccount)}&code={code}"
: $"{serverURL}/emailValidate/validateEmail?email={UnityWebRequest.EscapeURL(codeAccount)}&code={code}";
yield return Post(validateUrl, new WWWForm(), result => validateResult = result);
if (validateResult == null || validateResult.code != 0)
{
callback?.Invoke(new RequestResult
{
code = -10,
msg = isPhone ? "手机号验证码验证失败" : "邮箱验证码验证失败"
});
yield break;
}
// 2. 提取验证信息
JObject data = validateResult.data as JObject;
string verifiedAccount = data.Value(isPhone ? "phone" : "email");
long timestamp = data.Value("timestamp");
string sign = data.Value("sign");
// 3. 查询用户名
RequestResult listResult = null;
string listUrl = isPhone
? $"{serverURL}/gameLogin/listUsernamesByPhone"
: $"{serverURL}/gameLogin/listUsernamesByEmail";
WWWForm listForm = new WWWForm();
listForm.AddField(isPhone ? "phone" : "email", verifiedAccount);
listForm.AddField("timestamp", timestamp.ToString());
listForm.AddField("sign", sign);
yield return Post(listUrl, listForm, result => listResult = result);
if (listResult == null || listResult.code != 0)
{
callback?.Invoke(new RequestResult { code = -11, msg = "未找到绑定的账号" });
yield break;
}
// 4. 精确匹配账号名再重置密码
JArray users = listResult.data as JArray;
bool matched = false;
foreach (var item in users)
{
string username = item.Value("username");
long ts = item.Value("timestamp");
string sgn = item.Value("sign");
SmartBowLogger.Log(this,$"server: {username} vs account: {account}");
if (account.ToLower() == username.ToLower())
{
matched = true;
SmartBowLogger.Log(this,"匹配成功:" + username.ToLower());
// 5. 请求重置密码
string resetUrl = $"{serverURL}/gameLogin/resetPassword";
WWWForm resetForm = new WWWForm();
resetForm.AddField("sign", sgn);
resetForm.AddField("timestamp", ts.ToString());
resetForm.AddField("username", username);
resetForm.AddField("password", newPassword);
yield return Post(resetUrl, resetForm, callback);
break;
}
}
// 6. 如果没有匹配账号,提示
if (!matched)
{
callback?.Invoke(new RequestResult { code = -12, msg = "未找到对应账号绑定" });
}
}
///
/// 登录
/// gameID和channelID请询问插件给予者给予
///
///
///
///
///
///
public void Login(string gameID, string channelID, string username, string password, Action callback)
{
WWWForm form = new WWWForm();
form.AddField("gameID", gameID);
form.AddField("channelID", channelID);
form.AddField("username", username);
form.AddField("password", password);
StartCoroutine(Post(serverURL + "/SmartBowSDK/login", form, (res) =>
{
bool loginSuccess = res.code == 0;
if (loginSuccess) loginToken = res.data as string;
LoginResult loginResult = new LoginResult();
loginResult.success = loginSuccess;
loginResult.message = res.msg;
callback?.Invoke(loginResult);
}));
}
///
/// 登出
///
///
public void Logout(Action callback)
{
loginToken = null;
callback?.Invoke(true);
}
///
/// 获取用户信息
///
///
public void GetUserInfo(Action callback)
{
GetUserInfoResult getUserInfoResult = new GetUserInfoResult();
if (loginToken == null)
{
getUserInfoResult.message = "尚未登录";
callback?.Invoke(getUserInfoResult);
return;
}
WWWForm form = new WWWForm();
form.AddField("token", loginToken);
StartCoroutine(Post(serverURL + "/SmartBowSDK/getUserInfo", form, (res) =>
{
if (res.code == 0)
{
UserInfo userInfo = (res.data as JObject).ToObject();
getUserInfoResult.success = true;
getUserInfoResult.userInfo = userInfo;
}
getUserInfoResult.message = res.msg;
callback?.Invoke(getUserInfoResult);
}));
}
///
/// 设置用户名
///
/// 用户名字
///
public void SaveUserName(string nickname, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/saveUserName?token={loginToken}&nickname={UnityWebRequest.EscapeURL(nickname)}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 设置用户的多个信息
///
/// 用户信息对象
///
public void SaveUserInfo(UserInfoExtended userInfo, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string json = JsonConvert.SerializeObject(userInfo);
UnityWebRequest request = new UnityWebRequest($"{serverURL}/SmartBowSDK/saveUserInfo?token={loginToken}", "POST");
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
StartCoroutine(SendRequest(request, callback));
}
///
/// 根据密钥上传分数
///
///
///
///
public void UploadSeasonSinglePlayerGameRes(string secret, int score, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/UploadSeasonSinglePlayerGameRes?token={loginToken}&secret={UnityWebRequest.EscapeURL(secret)}&score={score}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 上传赛季PK分数
///
/// PK房间ID
/// 密钥,游戏类型(解析得到)
/// 对手ID
/// 结果(0:我赢;1:他赢;2:平局)
/// 回调
public void UploadSeasonPKGameRes(string roomKey, string secret, int p2ID, int gameRes, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/UploadSeasonPKGameRes" +
$"?token={loginToken}" +
$"&roomKey={UnityWebRequest.EscapeURL(roomKey)}" +
$"&secret={UnityWebRequest.EscapeURL(secret)}" +
$"&p2ID={p2ID}" +
$"&gameRes={gameRes}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 根据密钥获取排行榜
///
/// 密钥
/// 排行区域 3:国,1:省,2市,其他:全球
/// 国家
/// 省
/// 城市
///
public void GetSeasonRankListByGameType(string secret, int rankArea, string country, string state, string city, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/GetSeasonRankListByGameType?" +
$"token={loginToken}" +
$"&rankArea={rankArea}" +
$"&secret={UnityWebRequest.EscapeURL(secret)}" +
$"&countryCode={UnityWebRequest.EscapeURL(country)}" +
$"&stateCode={UnityWebRequest.EscapeURL(state)}" +
$"&cityCode={UnityWebRequest.EscapeURL(city)}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 根据密钥获取自定义排行榜
///
/// 密钥
/// 排行区域 3:国,1:省,2市,其他:全球
/// 国家
/// 省
/// 市
/// 1是降序,其他是升序(不能小于0)
/// 数量:不能小于0
///
public void GetSeasonRankListByCustom(string secret, int rankArea, string country, string state, string city, int rankType, int count, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/GetSeasonRankListByCustom?" +
$"token={loginToken}" +
$"&rankArea={rankArea}" +
$"&secret={UnityWebRequest.EscapeURL(secret)}" +
$"&countryCode={UnityWebRequest.EscapeURL(country)}" +
$"&stateCode={UnityWebRequest.EscapeURL(state)}" +
$"&cityCode={UnityWebRequest.EscapeURL(city)}" +
$"&rankType={rankType}" +
$"&count={count}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 获取自己的用户信息
///
/// 密钥
/// 排行区域 3:国,1:省,2市,其他:全球
/// 国家
/// 省
/// 市
/// 1是降序,其他是升序(不能小于0)
/// 数量:不能小于0
///
public void GetUserRankByGameType(string secret, int rankArea, string country, string state, string city, int rankType, int count, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/getUserRankByGameType?" +
$"token={loginToken}" +
$"&rankArea={rankArea}" +
$"&secret={UnityWebRequest.EscapeURL(secret)}" +
$"&countryCode={UnityWebRequest.EscapeURL(country)}" +
$"&stateCode={UnityWebRequest.EscapeURL(state)}" +
$"&cityCode={UnityWebRequest.EscapeURL(city)}" +
$"&rankType={rankType}" +
$"&count={count}";
StartCoroutine(Post(url, new WWWForm(), callback));
}
///
/// 上传排行榜分数(定制)
///
/// 密钥
/// 任务类型
/// 难度
/// 模式
/// 设备类型
/// 分数(>=0)
/// 回调
public void UploadCustomLeaderboardScore(string secret, int taskId, int difficultType, int modeType, int deviceType, int score, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
if (score < 0)
{
callback?.Invoke(new RequestResult { msg = "分数不能小于0" });
return;
}
string url = $"{serverURL}/SmartBowSDK/UploadCustomLeaderboardScore";
WWWForm form = new WWWForm();
form.AddField("token", loginToken);
form.AddField("secret", secret);
form.AddField("taskId", taskId);
form.AddField("difficultType", difficultType);
form.AddField("modeType", modeType);
form.AddField("deviceType", deviceType);
form.AddField("score", score);
StartCoroutine(Post(url, form, callback));
}
///
/// 获取排行榜(自定义)
///
/// 密钥
/// 任务类型
/// 难度
/// 模式
/// 设备类型
/// 时间维度
/// 回调
public void GetCustomLeaderboard(string secret, int taskId, int difficultType, int modeType, int deviceType, int timeType, Action callback)
{
if (loginToken == null)
{
callback?.Invoke(new RequestResult { msg = "尚未登录" });
return;
}
string url = $"{serverURL}/SmartBowSDK/GetCustomLeaderboard";
WWWForm form = new WWWForm();
form.AddField("token", loginToken);
form.AddField("secret", secret);
form.AddField("taskId", taskId);
form.AddField("difficultType", difficultType);
form.AddField("modeType", modeType);
form.AddField("deviceType", deviceType);
form.AddField("timeType", timeType);
StartCoroutine(Post(url, form, callback));
}
private string GetCalibrateDataStorageLocalKey(string mac)
{
string key = "CalibrateDataStorage";
string version = "1.0.0";
return key + "_" + mac + "_" + version;
}
internal void SaveCalibrateRecord(string mac, string record)
{
if (smartBowHelper.calibrateDataStorageMode == CalibrateDataStorageMode.Local)
{
PlayerPrefs.SetString(GetCalibrateDataStorageLocalKey(mac), record == null ? "" : record);
}
else if (smartBowHelper.calibrateDataStorageMode == CalibrateDataStorageMode.Remote)
{
WWWForm form = new WWWForm();
form.AddField("mac", mac);
form.AddField("record", record);
StartCoroutine(Post(serverURL + "/SmartBowSDK/saveCalibrateRecord", form, null));
}
}
internal void GetCalibrateRecord(string mac, Action callback)
{
if (smartBowHelper.calibrateDataStorageMode == CalibrateDataStorageMode.Local)
{
callback?.Invoke(PlayerPrefs.GetString(GetCalibrateDataStorageLocalKey(mac), ""));
}
else if (smartBowHelper.calibrateDataStorageMode == CalibrateDataStorageMode.Remote)
{
WWWForm form = new WWWForm();
form.AddField("mac", mac);
StartCoroutine(Post(serverURL + "/SmartBowSDK/getCalibrateRecord", form, (res) =>
{
if (res.code == 0) callback?.Invoke(res.data as string);
}));
}
}
public static IEnumerator Post(string url, WWWForm form, Action callback)
{
using (UnityWebRequest request = UnityWebRequest.Post(url, form))
{
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
callback?.Invoke(JsonConvert.DeserializeObject(request.downloadHandler.text));
else
callback?.Invoke(new RequestResult());
}
}
public static IEnumerator LoadSprite(string url, Action callback)
{
using (UnityWebRequest uwr = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET))
{
uwr.downloadHandler = new DownloadHandlerTexture();
yield return uwr.SendWebRequest();
if (uwr.result != UnityWebRequest.Result.Success) yield break;
Texture2D texture = DownloadHandlerTexture.GetContent(uwr);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
callback?.Invoke(sprite);
}
}
private IEnumerator SendRequest(UnityWebRequest request, Action callback)
{
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
callback?.Invoke(JsonConvert.DeserializeObject(request.downloadHandler.text));
else
callback?.Invoke(new RequestResult());
}
}
public class RequestResult
{
public int code = -9999;
public object data;
public string msg = "网络出错";
}
public class LoginResult
{
///
/// 是否登录成功
///
public bool success;
///
/// 消息描述
///
public string message;
}
public class GetUserInfoResult
{
///
/// 是否获取成功
///
public bool success;
///
/// 消息描述
///
public string message;
///
/// 用户信息
///
public UserInfo userInfo;
}
public class UserInfo
{
///
/// 昵称
///
public string nickname;
///
/// 头像地址
///
public string avatarUrl;
///
/// 性别(1表示男,2表示女)
///
public int gender;
}
///
/// 用户数据
///
public class UserInfoExtended
{
///
/// //头像url
///
public string avatarUrl;
///
/// //名字
///
public string nickname;
///
/// //性别 1 男,2女
///
public int gender;
///
/// 生日
///
public string birthday;
///
/// 国家
///
public string country;
///
/// 省
///
public string state;
///
/// 城市
///
public string city;
}
}