#if WEBGL_WX using System; using System.Collections.Generic; using System.Linq; using HC; using HC.MiniJSON; using HC.Plugins; using UnityEngine; using UnityEngine.UI; using WeChatWASM; public class GameClubDataCallback { public int Code; public string Msg; public string PlatformMsg; /// **type说明** /// | type取值 | 说明 | subKey | GameClubDataByType.value | /// | ------- | -------------------------------------- | -------- | -------- | /// | 1 | 加入该游戏圈时间 | 无需传入 | 秒级Unix时间戳 | /// | 3 | 用户禁言状态 | 无需传入 | 0:正常 1:禁言 | /// | 4 | 当天(自然日)点赞贴子数 | 无需传入 | | /// | 5 | 当天(自然日)评论贴子数 | 无需传入 | | /// | 6 | 当天(自然日)发表贴子数 | 无需传入 | | /// | 7 | 当天(自然日)发表视频贴子数 | 无需传入 | | /// | 8 | 当天(自然日)赞官方贴子数 | 无需传入 | | /// | 9 | 当天(自然日)评论官方贴子数 | 无需传入 | | /// | 10 | 当天(自然日)发表到本圈子话题的贴子数 | 传入话题id,从mp-游戏圈话题管理处获取 | | public Dictionary Data; } public class ShowGameClubCallback { public const int CODE_ERROR = -1; public const int CODE_SUCCESS = 0; public const int CODE_CLICK = 1; public const int CODE_BACK_GAME = 99; public int Code; public string Msg; public bool IsClick; } public class WxPrivacyCallback { public int Code; public string PrivacyContractName; public bool NeedAuthorization; public string Msg; } public class WxAuthAuthorizeCallback { public string Msg; public Dictionary AuthSettingDictionary; public Dictionary SubscriptionsSettingDictionary; public Dictionary MiniprogramAuthSettingDictionary; public bool SubscriptionsSettingMainSwitch = false; } public class WxUserInfo { public const int CODE_AUTH_DENY = -2; public const int CODE_ERROR = -1; public const int CODE_SUCCESS = 0; public const int CODE_NOT_AUTHORIZE_1 = 1; public const int CODE_NOT_AUTHORIZE_2 = 2; public int Code; public string Msg; public string AvatarUrl { get; set; } public string City { get; set; } public string Country { get; set; } public double Gender { get; set; } public string Language { get; set; } public string NickName { get; set; } public string Province { get; set; } } public class BoxPosition { public readonly int Width; public readonly int Height; public readonly int X; public readonly int Y; public BoxPosition(RectTransform pRect, Camera pCam = null, bool isPixelRatio = false) { var tWorldCorners = new Vector3[4]; pRect.GetWorldCorners(tWorldCorners); var tTopLeft = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[1]); var tBottomRight = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[3]); var tWidth = Mathf.Abs(tBottomRight.x - tTopLeft.x); var tHeight = Mathf.Abs(tBottomRight.y - tTopLeft.y); var left = tTopLeft.x; var top = Screen.height - tTopLeft.y; var scaleSize = 1.0; if (isPixelRatio) { scaleSize = WX.GetSystemInfoSync().pixelRatio; } // 这个地方,wx的js代码会自己除以一个换算比例,所以C#代码这里就不除了。 // 真实宽度 Width = (int)(tWidth / scaleSize); // 真实高度 Height = (int)(tHeight / scaleSize); // 真实x X = (int)(left / scaleSize); // 真实y Y = (int)(top / scaleSize); } } [System.Serializable] public class OpenDataMessage { public const string TypeShowFriendsRank = "showFriendsRank"; public const string TypeSetUserRecord = "setUserRecord"; public const string TypeShowGroupFriendsRank = "showGroupFriendsRank"; // type 用于表明事件类型 public string type; public string scoreKey; public int score; } public partial class HCSDKManager { private Dictionary _cacheWxGameClubButton = new(); private static Action _ShowGameClubCallback; private static Action OnShowListener = _ => { _ShowGameClubCallback?.Invoke(new ShowGameClubCallback { Code = ShowGameClubCallback.CODE_BACK_GAME, IsClick = true, Msg = "回到游戏" }); if (OnShowListener != null) { WX.OffShow(OnShowListener); } }; #region 排行榜 /// /// 设置用户排行榜的分数 /// /// 记录 /// 回调【保留】 /// 排行榜key【保留】 /// 额外记录【保留】 public void SetUserRecord(int score, Action callback = null, string key = "hc_score", Dictionary extra = null) { HCDebugger.LogDebug($"[ShowFriendsRank] SetUserRecord score {score}"); // var wxgame = new Dictionary // { // ["score"] = score, // ["update_time"] = HCTimeTools.GetCurrentTimestamp() // }; // var value = new Dictionary // { // ["wxgame"] = wxgame // }; // if (extra != null) // { // foreach (var keyValuePair in extra) // { // value.AddIfNotExists(keyValuePair.Key, keyValuePair.Value); // } // } // var valueString = Json.Serialize(value); // HCDebugger.LogDebug($"[SetUserRecord] key = {key} value = {value}"); // SetUserCloudStorage(new Dictionary // { // ["key"] = key, // ["value"] = valueString // }, callback); var openDataMessage = new OpenDataMessage() { type = OpenDataMessage.TypeSetUserRecord, // scoreKey = key, score = score }; WXBase.GetOpenDataContext().PostMessage(JsonUtility.ToJson(openDataMessage)); } /// /// 检查权限 /// /// public void CheckWxFriendInteraction(Action callback) { HCDebugger.LogDebug("[ShowFriendsRank] CheckWxFriendInteraction"); #if UNITY_EDITOR if (HCTools.GetPlayerPrefsInt("CheckWxFriendInteraction") == 0) { HCTools.SavePlayerPrefsInt("CheckWxFriendInteraction", 1); callback.Invoke(false); } else { callback.Invoke(true); } return; #endif GetSetting(result => { callback.Invoke(result.AuthSettingDictionary.TryGetValue("scope.WxFriendInteraction", out var isHave) && isHave); }); } /// /// 申请权限 /// /// public void ApplyForWxFriendInteraction(Action callback) { HCDebugger.LogDebug("[ShowFriendsRank] ApplyForWxFriendInteraction"); #if UNITY_EDITOR callback.Invoke(true); return; #endif RequestAuthorize("scope.WxFriendInteraction", callback); } /// /// 显示排行榜 /// /// 挂载点 /// 回调 主要用于显示失败,没有权限的时候,游戏处理逻辑 /// 相机 /// 排行榜key【保留】 public void ShowFriendsRankAndRequestAuthorize(GameObject gameObject, Action callback = null, Camera pCam = null, string key = "hc_score") { CheckWxFriendInteraction(result => { if (result) { FriendsRank(); } else { ApplyForWxFriendInteraction(applyResult => { if (applyResult) { FriendsRank(); } else { callback?.Invoke(-1, "no permission"); } }); } }); return; void FriendsRank() { ShowFriendsRank(gameObject, pCam, key); callback?.Invoke(0, "success"); } } public void ShowFriendsRank(GameObject gameObject, Camera pCam = null, string key = "hc_score") { HCDebugger.LogDebug($"[ShowFriendsRank] show open data start key = {key}"); const string prefabName = "Prefabs/hc_FriendsRank"; RawImage rawImage = null; var tempComponent = gameObject.GetComponent(); if (tempComponent != null) { rawImage = tempComponent; } var target = gameObject.transform.Find(prefabName.Replace("/", "_")); if (rawImage == null) { if (target == null) { var loadedPrefab = Resources.Load(prefabName) as GameObject; if (loadedPrefab == null) return; // 实例化加载的Prefab var instantiatedPrefab = Instantiate(loadedPrefab, gameObject.transform, true); // 设置实例化后的Prefab的名称为自定义名称 instantiatedPrefab.name = prefabName.Replace("/", "_"); // 设置实例化后的Prefab的位置 // 获取实例化后的Prefab的RectTransform组件 var rectTransform = instantiatedPrefab.GetComponent(); // 将边距设置为0 rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; instantiatedPrefab.transform.localScale = Vector3.one; rawImage = instantiatedPrefab.GetComponent(); } else { rawImage = target.GetComponent(); } } if (rawImage == null) { HCDebugger.LogError("排行榜 - 获取RawImage异常"); return; } var pRect = gameObject.GetComponent(); if (pRect == null) { HCDebugger.LogError("排行榜 - 获取盒子位置信息失败"); return; } #if UNITY_EDITOR if (!ColorUtility.TryParseHtmlString("#FF0000", out var color)) return; rawImage.texture = null; rawImage.color = color; return; #endif var boxPosition = new BoxPosition(pRect, pCam); HCDebugger.LogDebug($"[ShowFriendsRank] show open data {boxPosition.X} {boxPosition.Y} {boxPosition.Width} {boxPosition.Height}"); var openDataMessage = new OpenDataMessage() { type = OpenDataMessage.TypeShowFriendsRank, scoreKey = key }; WXBase.ShowOpenData(rawImage.texture, boxPosition.X, boxPosition.Y, boxPosition.Width, boxPosition.Height); HCDebugger.LogDebug($"[ShowFriendsRank] show open data {JsonUtility.ToJson(openDataMessage)}"); WXBase.GetOpenDataContext().PostMessage(JsonUtility.ToJson(openDataMessage)); } public void CloseFriendsRank() { HCDebugger.LogDebug("[ShowFriendsRank] CloseFriendsRank"); #if UNITY_EDITOR return; #endif WXBase.HideOpenData(); } #endregion /// /// 获取当前设置的权限 /// /// 回调内容 /// 是否同时获取用户订阅消息的订阅状态,默认不获取。 public void GetSetting(Action callback, bool withSubscriptions = false) { WX.GetSetting(new GetSettingOption { withSubscriptions = withSubscriptions, success = result => { var errMsg = result.errMsg; var authSetting = result.authSetting; var subscriptionsSetting = result.subscriptionsSetting; var miniprogramAuthSetting = result.miniprogramAuthSetting; var authSettingDictionary = new Dictionary(); var subscriptionsSettingDictionary = new Dictionary(); var miniprogramAuthSettingDictionary = new Dictionary(); if (authSetting != null) { foreach (var keyValuePair in authSetting) { authSettingDictionary.Add(keyValuePair.Key, keyValuePair.Value); } } var subscriptionsSettingMainSwitch = false; if (subscriptionsSetting is { itemSettings: not null }) { subscriptionsSettingMainSwitch = subscriptionsSetting.mainSwitch; foreach (var keyValuePair in subscriptionsSetting.itemSettings) { subscriptionsSettingDictionary.Add(keyValuePair.Key, keyValuePair.Value); } } if (miniprogramAuthSetting != null) { foreach (var keyValuePair in miniprogramAuthSetting) { miniprogramAuthSettingDictionary.Add(keyValuePair.Key, keyValuePair.Value); } } callback.Invoke(new WxAuthAuthorizeCallback { Msg = errMsg, AuthSettingDictionary = authSettingDictionary, SubscriptionsSettingDictionary = subscriptionsSettingDictionary, MiniprogramAuthSettingDictionary = miniprogramAuthSettingDictionary, SubscriptionsSettingMainSwitch = subscriptionsSettingMainSwitch }); }, fail = result => { callback.Invoke(new WxAuthAuthorizeCallback { Msg = result.errMsg, AuthSettingDictionary = new Dictionary(), SubscriptionsSettingDictionary = new Dictionary(), MiniprogramAuthSettingDictionary = new Dictionary() }); }, }); } public void SetUserCloudStorage(Dictionary saveData, Action callback) { var kvDataList = saveData.Select(kv => new KVData { key = kv.Key, value = kv.Value }).ToArray(); WX.SetUserCloudStorage(new SetUserCloudStorageOption { KVDataList = kvDataList, success = result => { callback?.Invoke(true, result.errMsg); }, fail = result => { HCDebugger.LogError($"[SetUserCloudStorage] error msg = {result.errMsg}"); callback?.Invoke(false, result.errMsg); } }); } public void RequestAuthorize(string scope, Action callback) { WX.Authorize(new AuthorizeOption { scope = scope, success = _ => { callback.Invoke(true); }, fail = result => { HCDebugger.LogError($"[RequestAuthorize] fail = {result.errMsg}"); callback.Invoke(false); } }); } /// /// 打开设置权限 /// /// 设置权限内容 /// 是否同时获取用户订阅消息的订阅状态,默认不获取。 public void OpenSetting(Action callback, bool withSubscriptions = false) { WX.OpenSetting(new OpenSettingOption { withSubscriptions = withSubscriptions, fail = result => { callback.Invoke(new WxAuthAuthorizeCallback { Msg = result.errMsg, AuthSettingDictionary = new Dictionary(), SubscriptionsSettingDictionary = new Dictionary(), MiniprogramAuthSettingDictionary = new Dictionary() }); }, success = result => { var errMsg = result.errMsg; var authSetting = result.authSetting; var subscriptionsSetting = result.subscriptionsSetting; var authSettingDictionary = new Dictionary(); var subscriptionsSettingDictionary = new Dictionary(); var miniprogramAuthSettingDictionary = new Dictionary(); if (authSetting != null) { foreach (var keyValuePair in authSetting) { authSettingDictionary.Add(keyValuePair.Key, keyValuePair.Value); } } var subscriptionsSettingMainSwitch = false; if (subscriptionsSetting is { itemSettings: not null }) { subscriptionsSettingMainSwitch = subscriptionsSetting.mainSwitch; foreach (var keyValuePair in subscriptionsSetting.itemSettings) { subscriptionsSettingDictionary.Add(keyValuePair.Key, keyValuePair.Value); } } callback.Invoke(new WxAuthAuthorizeCallback { Msg = errMsg, AuthSettingDictionary = authSettingDictionary, SubscriptionsSettingDictionary = subscriptionsSettingDictionary, MiniprogramAuthSettingDictionary = miniprogramAuthSettingDictionary, SubscriptionsSettingMainSwitch = subscriptionsSettingMainSwitch }); } }); } public void GetUserInfo(Action callback) { GetSetting(result => { if (result.AuthSettingDictionary.TryGetValue("scope.userInfo", out var hasAuthorize)) { if (hasAuthorize) { WX.GetUserInfo(new GetUserInfoOption { success = result => { var errMsg = result.errMsg; var userInfo = result.userInfo; var userInfoAvatarUrl = userInfo.avatarUrl; var userInfoCity = userInfo.city; var userInfoCountry = userInfo.country; var userInfoGender = userInfo.gender; var userInfoLanguage = userInfo.language; var userInfoNickName = userInfo.nickName; var userInfoProvince = userInfo.province; callback.Invoke(new WxUserInfo { Code = WxUserInfo.CODE_SUCCESS, Msg = result.errMsg, AvatarUrl = userInfoAvatarUrl, City = userInfoCity, Country = userInfoCountry, Gender = userInfoGender, Language = userInfoLanguage, NickName = userInfoNickName, Province = userInfoProvince, }); }, fail = result => { callback.Invoke(new WxUserInfo { Code = WxUserInfo.CODE_ERROR, Msg = result.errMsg }); }, complete = result => { var errMsg = result.errMsg; } }); } else { callback.Invoke(new WxUserInfo { Code = WxUserInfo.CODE_NOT_AUTHORIZE_2, Msg = result.Msg }); } } else { callback.Invoke(new WxUserInfo { Code = WxUserInfo.CODE_NOT_AUTHORIZE_1, Msg = result.Msg }); } }); } WXUserInfoButton _wxUserInfoButton; public void CreateUserInfoButton(RectTransform pRect, Action callback, Camera pCam = null, string lang = "zh_CN", bool withCredentials = false) { var boxPosition = new BoxPosition(pRect, pCam); _wxUserInfoButton = WXBase.CreateUserInfoButton(boxPosition.X, boxPosition.Y, boxPosition.Width, boxPosition.Height, lang, withCredentials); _wxUserInfoButton.OnTap(result => { if (result.errCode != 0) { callback.Invoke(new WxUserInfo { Code = WxUserInfo.CODE_AUTH_DENY, Msg = result.errMsg, AvatarUrl = "", City = "", Country = "", Gender = 0, Language = "", NickName = "", Province = "", }); return; } var errMsg = result.errMsg; var userInfo = result.userInfo; var userInfoAvatarUrl = userInfo.avatarUrl; var userInfoCity = userInfo.city; var userInfoCountry = userInfo.country; var userInfoGender = userInfo.gender; var userInfoLanguage = userInfo.language; var userInfoNickName = userInfo.nickName; var userInfoProvince = userInfo.province; var wxUserInfo = new WxUserInfo { Code = WxUserInfo.CODE_SUCCESS, Msg = result.errMsg, AvatarUrl = userInfoAvatarUrl, City = userInfoCity, Country = userInfoCountry, Gender = userInfoGender, Language = userInfoLanguage, NickName = userInfoNickName, Province = userInfoProvince, }; var hciBaseAnalytics = HCAnalyticsManager.Instance.GetAnalyticsPlugin(TrackEventPlatform.TD); ((HCTDAnalyticsWebGL)hciBaseAnalytics)?.TrackWxUserInfo(wxUserInfo); callback.Invoke(wxUserInfo); }); _wxUserInfoButton.Show(); } public void CloseUserInfoButton() { _wxUserInfoButton?.Hide(); _wxUserInfoButton?.Destroy(); _wxUserInfoButton = null; } public void GetWxPrivacySetting(Action callback) { WX.GetPrivacySetting(new GetPrivacySettingOption { success = result => { var resultPrivacyContractName = result.privacyContractName; var resultNeedAuthorization = result.needAuthorization; var errMsg = result.errMsg; callback?.Invoke(new WxPrivacyCallback { Code = 0, Msg = errMsg, NeedAuthorization = resultNeedAuthorization, PrivacyContractName = resultPrivacyContractName, }); }, fail = result => { var errMsg = result.errMsg; callback?.Invoke(new WxPrivacyCallback { Code = -1, Msg = errMsg }); }, complete = result => { var errMsg = result.errMsg; } }); } /// /// /// /// 按钮的url /// 显示位置 /// /// /// /// 显示/点击回调 public void ShowGameClubButton(string buttonImageUrl, RectTransform pRect, Camera pCam = null, string openlink = null, bool? hasRedDot = null, Action callback = null) { #if UNITY_EDITOR callback?.Invoke(new ShowGameClubCallback { Code = ShowGameClubCallback.CODE_SUCCESS, IsClick = false }); return; #endif if (_cacheWxGameClubButton.ContainsKey(pRect)) { HCDebugger.LogError("游戏圈子Icon正在显示"); callback?.Invoke(new ShowGameClubCallback { Code = ShowGameClubCallback.CODE_ERROR, Msg = "游戏圈子Icon正在显示" }); return; } var tWorldCorners = new Vector3[4]; pRect.GetWorldCorners(tWorldCorners); var tTopLeft = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[1]); var tBottomRight = RectTransformUtility.WorldToScreenPoint(pCam, tWorldCorners[3]); var tWidth = Mathf.Abs(tBottomRight.x - tTopLeft.x); var tHeight = Mathf.Abs(tBottomRight.y - tTopLeft.y); var left = tTopLeft.x; var top = Screen.height - tTopLeft.y; // 0.5 var scaleSize = WX.GetSystemInfoSync().pixelRatio; // 真实宽度 var width = (int)(tWidth / scaleSize); // 真实高度 var height = (int)(tHeight / scaleSize); // 真实x var x = (int)(left / scaleSize); // 真实y var y = (int)(top / scaleSize); var gameClubButton = WXBase.CreateGameClubButton(new WXCreateGameClubButtonParam { type = GameClubButtonType.image, image = buttonImageUrl, style = new GameClubButtonStyle { left = x, top = y, width = width, height = height, }, openlink = openlink, hasRedDot = hasRedDot }); callback?.Invoke(new ShowGameClubCallback { Code = ShowGameClubCallback.CODE_SUCCESS, Msg = "show success" }); gameClubButton.OnTap(() => { callback?.Invoke(new ShowGameClubCallback { Code = ShowGameClubCallback.CODE_CLICK, Msg = "click success", IsClick = true }); _ShowGameClubCallback = callback; WX.OnShow(OnShowListener); }); _cacheWxGameClubButton.Add(pRect, gameClubButton); } /// /// 关闭指定位置的button,如果不传,关闭所有button /// 要和传入的是同一个对象 /// /// public void CloseGameClubButton(RectTransform pRect = null) { if (pRect == null) { foreach (var wxGameClubButton in _cacheWxGameClubButton.Values) { wxGameClubButton?.Hide(); wxGameClubButton?.OffTap(); wxGameClubButton?.Destroy(); } _cacheWxGameClubButton.Clear(); } else { if (_cacheWxGameClubButton.TryGetValue(pRect, out var button)) { button?.Hide(); button?.OffTap(); button?.Destroy(); _cacheWxGameClubButton.Remove(pRect); } else { HCDebugger.LogError($"传入的RectTransform 不存在 {pRect}"); } } } public void GetGameClubData(Action call = null, string sessionId = "") { var list = new List { new() { type = 1 }, new() { type = 3 }, new() { type = 4 }, new() { type = 5 }, new() { type = 6 }, new() { type = 7 }, new() { type = 8 }, new() { type = 9 } }; if (!string.IsNullOrEmpty(sessionId)) { list.Add(new DataType { type = 10, subKey = sessionId }); } var dataTypeList = list.ToArray(); WX.RequirePrivacyAuthorize(new RequirePrivacyAuthorizeOption { complete = result => { HCDebugger.LogDebug($"[RequirePrivacyAuthorize] [complete] errMsg = {result.errMsg}"); }, fail = result => { call?.Invoke(new GameClubDataCallback { Code = -1, Msg = "RequirePrivacyAuthorize fail", PlatformMsg = result.errMsg, Data = new Dictionary() }); HCDebugger.LogDebug($"[RequirePrivacyAuthorize] [fail] errMsg = {result.errMsg}"); }, success = result => { HCDebugger.LogDebug($"[RequirePrivacyAuthorize] [success] errMsg = {result.errMsg}"); WX.GetGameClubData(new GetGameClubDataOption { dataTypeList = dataTypeList, complete = generalCallbackResult => { var errMsg = generalCallbackResult.errMsg; HCDebugger.LogDebug($"[GetGameClubData] [complete] errMsg = {errMsg}"); }, fail = generalCallbackResult => { var errMsg = generalCallbackResult.errMsg; call?.Invoke(new GameClubDataCallback { Code = -2, Msg = "GetGameClubData fail", PlatformMsg = errMsg, Data = new Dictionary() }); HCDebugger.LogDebug($"[GetGameClubData] [fail] errMsg = {errMsg}"); }, success = getGameClubDataSuccessCallbackResult => { var errMsg = getGameClubDataSuccessCallbackResult.errMsg; var signature = getGameClubDataSuccessCallbackResult.signature; var iv = getGameClubDataSuccessCallbackResult.iv; var encryptedData = getGameClubDataSuccessCallbackResult.encryptedData; var cloudID = getGameClubDataSuccessCallbackResult.cloudID; HCDebugger.LogDebug($"[GetGameClubData] [success] errMsg = {errMsg} signature = {signature} iv = {iv} encryptedData = {encryptedData}"); // 需要传递给川哥解析 if (string.IsNullOrEmpty(iv) || string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(encryptedData)) { call?.Invoke(new GameClubDataCallback { Code = -3, Msg = "GameClubData is Null", PlatformMsg = errMsg, Data = new Dictionary() }); return; } HCServer.Instance.WxDataDecrypt(iv, encryptedData, signature, (code, msg, result) => { if (code == 0) { try { var resultContent = result.content; var contentData = (Dictionary)Json.Deserialize(resultContent); var watermark = contentData["watermark"]; var dataList = (List)contentData["dataList"]; var resultData = new Dictionary(); foreach (Dictionary item in dataList) { var dataType = (Dictionary)item["dataType"]; var type = dataType["type"]; var value = item["value"]; resultData.Add(int.Parse("" + type), value); } call?.Invoke(new GameClubDataCallback { Code = 0, Msg = "success", PlatformMsg = msg, Data = resultData }); } catch (Exception e) { call?.Invoke(new GameClubDataCallback { Code = -4, Msg = "Server Data Exception", PlatformMsg = e.Message, Data = new Dictionary() }); } } else { call?.Invoke(new GameClubDataCallback { Code = code, Msg = "Server Fail", PlatformMsg = msg, Data = new Dictionary() }); } }); }, }); } }); } } #endif