提交
This commit is contained in:
@@ -79,11 +79,12 @@ namespace ScrewsMaster
|
|||||||
is_first_login_go_to_h5 = false;
|
is_first_login_go_to_h5 = false;
|
||||||
GameHelper.is_first_login = loginModel.new_player;
|
GameHelper.is_first_login = loginModel.new_player;
|
||||||
|
|
||||||
if (GameHelper.IsGiftSwitch() && !loginModel.new_player && is_first_login_go_to_h5)
|
// if (GameHelper.IsGiftSwitch() && !loginModel.new_player && is_first_login_go_to_h5)
|
||||||
{
|
// {
|
||||||
GotoH5();
|
// GotoH5();
|
||||||
}
|
// }
|
||||||
else if (GameHelper.IsGiftSwitch() && loginModel.new_player)
|
// else
|
||||||
|
if (loginModel.new_player)
|
||||||
{
|
{
|
||||||
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.FirstRewardUI_Open);
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.FirstRewardUI_Open);
|
||||||
loginModel.new_player = false;
|
loginModel.new_player = false;
|
||||||
|
|||||||
@@ -139,13 +139,19 @@ namespace ScrewsMaster
|
|||||||
ui.btn_cash.SetClick(() =>
|
ui.btn_cash.SetClick(() =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (UIManager.Instance.IsExistUI(UIConst.SheepPlayUI))
|
||||||
|
{
|
||||||
|
CtrlCloseUI();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var level = ShowScrews.Instance.gameMode == GameHome.Mode_difficult ? 1 : GameHelper.GetLevel(); ;
|
||||||
|
ShowScrews.Instance.InitLogic(level);
|
||||||
|
AudioManager.Instance.PlayBGM(AudioConst.PlayingBg);
|
||||||
|
CtrlCloseUI();
|
||||||
|
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.GameHomeUI_Close);
|
||||||
|
}
|
||||||
|
|
||||||
var level = ShowScrews.Instance.gameMode == GameHome.Mode_difficult ? 1 : GameHelper.GetLevel(); ;
|
|
||||||
ShowScrews.Instance.InitLogic(level);
|
|
||||||
|
|
||||||
AudioManager.Instance.PlayBGM(AudioConst.PlayingBg);
|
|
||||||
CtrlCloseUI();
|
|
||||||
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.GameHomeUI_Close);
|
|
||||||
// UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.BuygoldUI_Open, false);
|
// UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.BuygoldUI_Open, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ using System.Collections;
|
|||||||
namespace ScrewsMaster
|
namespace ScrewsMaster
|
||||||
{
|
{
|
||||||
using DG.Tweening;
|
using DG.Tweening;
|
||||||
|
using MYp0ZVTT2QSDK;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class LoginSystem : BaseSystem
|
public class LoginSystem : BaseSystem
|
||||||
@@ -103,6 +105,7 @@ namespace ScrewsMaster
|
|||||||
|
|
||||||
private void OnLoginSuccess(LoginModel loginData)
|
private void OnLoginSuccess(LoginModel loginData)
|
||||||
{
|
{
|
||||||
|
Debug.Log(JsonConvert.SerializeObject(loginData));
|
||||||
var loginModel = GameHelper.GetLoginModel();
|
var loginModel = GameHelper.GetLoginModel();
|
||||||
loginModel.cdn_url = loginData.cdn_url;
|
loginModel.cdn_url = loginData.cdn_url;
|
||||||
loginModel.setting = loginData.setting;
|
loginModel.setting = loginData.setting;
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ namespace ScrewsMaster
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetRequestContentType(loginRequest);
|
SetRequestContentType(loginRequest);
|
||||||
Debug.Log($"request url1======= {url1}");
|
// Debug.Log($"request url1======= {url1}");
|
||||||
yield return loginRequest.SendWebRequest();
|
yield return loginRequest.SendWebRequest();
|
||||||
Debug.Log($"requestData11111======={url1}=={requestJson}");
|
// Debug.Log($"requestData11111======={url1}=={requestJson}");
|
||||||
Debug.Log($"requestData22222====={url1}==={JsonConvert.SerializeObject(loginRequest)}");
|
// Debug.Log($"requestData22222====={url1}==={JsonConvert.SerializeObject(loginRequest)}");
|
||||||
if (loginRequest.result is not UnityWebRequest.Result.Success)
|
if (loginRequest.result is not UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
onCompleted?.Invoke(false, default);
|
onCompleted?.Invoke(false, default);
|
||||||
@@ -85,7 +85,7 @@ namespace ScrewsMaster
|
|||||||
receiveContent = Base64Kit.Decode(receiveContent);
|
receiveContent = Base64Kit.Decode(receiveContent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Debug.Log(receiveContent);
|
// Debug.Log(receiveContent);
|
||||||
var response = SerializeUtil.ToObject<ResponseData>(receiveContent);
|
var response = SerializeUtil.ToObject<ResponseData>(receiveContent);
|
||||||
|
|
||||||
|
|
||||||
@@ -181,10 +181,10 @@ namespace ScrewsMaster
|
|||||||
};
|
};
|
||||||
|
|
||||||
statusDic.Add(reqData.type, true);
|
statusDic.Add(reqData.type, true);
|
||||||
Debug.Log($"PostFunnelLogin requestData1111========={reqData.type}");
|
// Debug.Log($"PostFunnelLogin requestData1111========={reqData.type}");
|
||||||
Post<RespLoginFunnelData>("event/funnelLogin", requestData, (isSuccess, data) =>
|
Post<RespLoginFunnelData>("event/funnelLogin", requestData, (isSuccess, data) =>
|
||||||
{
|
{
|
||||||
Debug.Log($"PostFunnelLogin responseData2222========={isSuccess} {reqData.type}");
|
// Debug.Log($"PostFunnelLogin responseData2222========={isSuccess} {reqData.type}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static void SendLogToServer(RespDebugData reqData)
|
public static void SendLogToServer(RespDebugData reqData)
|
||||||
@@ -273,7 +273,7 @@ namespace ScrewsMaster
|
|||||||
androidPointObject.@event = eventname;
|
androidPointObject.@event = eventname;
|
||||||
androidPointObject.property = eventproperty;
|
androidPointObject.property = eventproperty;
|
||||||
androidPointObject.n = integer;
|
androidPointObject.n = integer;
|
||||||
Debug.Log("打点" + JsonConvert.SerializeObject(androidPointObject));
|
// Debug.Log("打点" + JsonConvert.SerializeObject(androidPointObject));
|
||||||
PostWithHeader<AndroidPointObject>("/event/incrN", androidPointObject, (isSuccess, obj) =>
|
PostWithHeader<AndroidPointObject>("/event/incrN", androidPointObject, (isSuccess, obj) =>
|
||||||
{
|
{
|
||||||
});
|
});
|
||||||
|
|||||||
Binary file not shown.
@@ -1,40 +1,51 @@
|
|||||||
Welcome to Twist & Turn ("we," "our," or "us"). We value your privacy and are committed to safeguarding your personal information. This Privacy Policy outlines how we collect, use, store, and share your information, as well as your rights under applicable privacy laws, including the California Consumer Privacy Act (CCPA) and the Children's Online Privacy Protection Act (COPPA).
|
Welcome to **Our game**! We take your privacy extremely seriously. This Privacy Policy outlines how we collect, use, store, and protect your personal data. Please read this policy thoroughly to understand how we manage your personal information.
|
||||||
1. Information Collection
|
|
||||||
We may collect the following types of information while you use Twist & Turn:
|
1. Introduction
|
||||||
- Device Information: Information about your device, such as device model, operating system version, unique identifiers (e.g., IDFA, GAID), IP address, browser type, language settings, and mobile network information.
|
Thank you for using **Our game**! We are committed to protecting your privacy and ensuring that your data is handled appropriately, providing you with a safe and enjoyable gaming experience.
|
||||||
- Game Usage Data: Information about your interactions with the game, such as progress, scores, achievements, in-game items, friends, activities, login times, and play duration.
|
|
||||||
- Location Information: With your consent, we may collect location data to provide location-based services, such as leaderboards or friend recommendations.
|
2. Information We Collect
|
||||||
- Payment Information: When purchasing in-game items or services, we may collect transaction details. Payment processing is handled by third-party services, and we only receive confirmation of payment.
|
We may gather the following types of data:
|
||||||
- Social Media Information: If you log in via social media or share game experiences, we may access publicly available information from your social account.
|
- Personal Details: Personal information you provide when creating an account or using the game, such as your name, email address, and phone number.
|
||||||
2. Information Use
|
- Device Data: Technical specifications like device model, operating system version, and unique device identifiers (e.g., IMEI, IDFA).
|
||||||
We use the collected data for the following purposes:
|
- Usage Logs: Activity records, game progress, purchase history, achievements, and rankings within the game.
|
||||||
- Game Operation and Maintenance: Ensuring the smooth operation of the game, fixing bugs, backing up data, and providing technical support.
|
- Location Data: Geographical location information if you authorize us to collect it, to provide more tailored services.
|
||||||
- Customer Support: Assisting you when you contact our customer service.
|
- Third-Party Data: Information gathered through social media platforms or other external services, such as linked social accounts.
|
||||||
- Personalization: Tailoring content, recommendations, advertisements, and offers based on your preferences and usage.
|
|
||||||
- Marketing Communications: Sending updates, event notifications, or promotional information, which you can opt-out of anytime.
|
3. Purpose of Using Information
|
||||||
- Analytics and Improvement: Conducting data analysis to improve game features and develop new services.
|
We collect and use your data for the following reasons:
|
||||||
3. Information Sharing
|
- Provide and Enhance Services: To deliver game services, optimize user experience, fix errors, and improve features, ensuring the stability and performance of the game.
|
||||||
We do not sell your personal information to third parties. We may share data in these cases:
|
- Personalized Content: To offer customized game content and recommendations based on your interests and preferences, enhancing your gaming experience.
|
||||||
- Legal Compliance: If required by law or government authorities.
|
- Marketing and Promotion: To send game updates, promotional activities, and news, boosting user engagement.
|
||||||
- Business Transfers: In the event of a merger, acquisition, or transfer of assets.
|
- Data Analysis: To analyze user behavior, assess game performance, and conduct market research, continuously refining game quality.
|
||||||
- Service Providers: Trusted partners for payment processing, analytics, or advertising services, bound by confidentiality agreements.
|
- Legal Compliance: To meet legal requirements and protect our legitimate interests, ensuring the lawful and compliant operation of the game.
|
||||||
4. Data Security and Retention
|
|
||||||
We take data protection seriously:
|
4. Information Sharing and Disclosure
|
||||||
- Retention: We retain your data only as long as necessary to fulfill the purposes outlined.
|
We do not sell your personal information. We may share your data with third parties in the following scenarios:
|
||||||
- Security Measures: We use encryption and other methods to protect your data.
|
- Service Providers: With third-party service providers who assist us in operating the game, such as data analytics firms, payment processors, and cloud service providers.
|
||||||
- Data Transfers: When transferring data outside your jurisdiction, we comply with relevant privacy laws.
|
- Partners: With partners to offer joint services or activities, enhancing user value.
|
||||||
5. Your Rights Under CCPA
|
- Legal Requirements: When required by law or to protect our legitimate interests, we may disclose your data to ensure legal compliance.
|
||||||
If you are a California resident, you have the following rights under CCPA:
|
|
||||||
- Right to Know: Request information about data collection, usage, and sharing.
|
5. Data Security
|
||||||
- Right to Delete: Request deletion of your personal information, with some exceptions.
|
We implement reasonable security measures to protect your personal data from unauthorized access, disclosure, alteration, or destruction. While no internet transmission method or electronic storage method is completely secure, we continuously improve our security measures to ensure your data is as secure as possible.
|
||||||
- Right to Opt-Out: Prevent the sale of your data.
|
|
||||||
- Right to Non-Discrimination: Exercise your rights without facing discrimination.
|
6. Your Rights
|
||||||
To exercise these rights, contact us at mtop17600@gmail.com.
|
You have the right to access, correct, delete your personal data, or withdraw your consent to certain data processing. You can contact us through the following methods:
|
||||||
6. Children's Privacy Under COPPA
|
- Email: maxsource2031@outlook.com
|
||||||
If we discover a user is under 13, we will obtain parental consent before collecting data, and process data only for game-related purposes.
|
- In-Game Support: Submit requests through the in-game customer support system, and we will process your requests as soon as possible.
|
||||||
7. Cookies and Tracking
|
|
||||||
We use cookies and similar tools for personalization and analytics. You can manage cookies through browser settings.
|
7. Third-Party Services
|
||||||
8. Policy Changes
|
Our game may integrate third-party services, such as social media platforms and advertising networks. These third-party services may collect your data. We recommend that you review the privacy policies of these third-party services to understand how they handle your data. We are not responsible for the actions or policies of third-party services, but we strive to ensure that our partners adhere to high standards of data protection.
|
||||||
We may update this Privacy Policy to reflect changes in legal requirements or our practices. Significant changes will be communicated via email or in-app notification.
|
|
||||||
9. Contact Us
|
8. Children's Privacy
|
||||||
For any questions, email us at mtop17600@gmail.com.
|
We do not intentionally collect personal data from children under the age of 13. If we discover that we have collected personal data from a child under 13, we will immediately delete that data and take necessary measures to prevent similar occurrences.
|
||||||
|
|
||||||
|
9. International Data Transfer
|
||||||
|
Your personal data may be transferred to and stored on servers located outside your country of residence. The data protection laws in these countries may differ from those in your country. By using our game, you agree to such transfers and storage, and you understand the potential legal differences.
|
||||||
|
|
||||||
|
10. Changes to the Privacy Policy
|
||||||
|
We reserve the right to update this Privacy Policy at any time. We will notify you of any changes by posting the new policy within the game. We recommend that you regularly review this Privacy Policy to stay informed about the latest terms and conditions. If we make significant changes, we may provide additional notice, such as in-game notifications or emails, to ensure you are aware of the changes.
|
||||||
|
|
||||||
|
11. Contact Us
|
||||||
|
If you have any questions or concerns about this Privacy Policy, please contact us through the following methods:
|
||||||
|
- Email: maxsource2031@outlook.com
|
||||||
|
- In-Game Support: Submit requests through the in-game customer support system, and we will respond to your inquiries as soon as possible to ensure your issues are resolved promptly.
|
||||||
@@ -1,34 +1,25 @@
|
|||||||
Welcome to Twist & Turn ("the Game" or "we"). Please read this User Agreement ("Agreement") carefully before using the Game. By downloading, installing, or using the Game, you indicate that you have read and agree to be bound by this Agreement. If you do not agree with any part of this Agreement, please do not use the Game.
|
By downloading, installing, or playing (“the Game”), you agree to be bound by these Terms of Service.
|
||||||
1. Acceptance of Terms
|
1. The Service
|
||||||
1.1 This Agreement constitutes a legal agreement between you and Twist & Turn, governing your use of the Game.
|
The game is a casual puzzle game inspired by tile-matching mechanics. The Game is provided for your personal, non-commercial entertainment.
|
||||||
1.2 We may modify or update this Agreement from time to time. The updated Agreement will be communicated via in-app notifications or other appropriate means. If you continue using the Game after the Agreement has been updated, it is considered acceptance of the updated terms.
|
2. No Account Required
|
||||||
2. Rules of Use
|
You may play the Game without creating an account or providing any personal information.
|
||||||
2.1 Account Creation and Management: You may need to create an account to access certain features of the Game. You must ensure that the information provided is accurate and up-to-date.
|
3. No In-App Purchases or Ads
|
||||||
2.2 Age Restrictions: The Game is intended for users aged 13 and above. If you are under 18, parental or guardian consent is required before using the Game.
|
The game contains no in-app purchases, no outbound links, and no third-party advertisements. The Game is a one-time download with no ongoing costs or distractions.
|
||||||
2.3 Game Conduct Rules: You agree to comply with all applicable laws and refrain from engaging in the following behaviors while using the Game:
|
4. User Conduct
|
||||||
- Violating the legal rights of others.
|
You agree to use the Game only for its intended purpose. You may not:
|
||||||
- Using unauthorized third-party software or tools.
|
- Reverse engineer, modify, or create derivative works of the Game.
|
||||||
- Distributing malware or viruses.
|
- Use the Game for any illegal or unauthorized purpose.
|
||||||
- Cheating or disrupting the fairness of the Game.
|
- Attempt to disrupt or damage the Game’s functionality.
|
||||||
- Posting inappropriate, offensive, or illegal content.
|
5. Intellectual Property
|
||||||
2.4 Intellectual Property: All content within the Game (including but not limited to images, text, music, code) is protected by copyright and other intellectual property laws. You may not copy, modify, distribute, or use it for commercial purposes without authorization.
|
All content in The game – including but not limited to the game name, artwork, sound effects, tile designs, and code – is the exclusive property of the developer. You may not copy, redistribute, or commercially exploit any part of the Game without explicit permission.
|
||||||
3. Payments and Virtual Items
|
6. No Warranties
|
||||||
3.1 Virtual Items and Currency: The Game may include virtual items or currency. Virtual items are for in-game use only, have no real-world monetary value, and cannot be transferred, traded, or exchanged for actual money.
|
The Game is provided “as is.” We do not guarantee that it will be error-free or uninterrupted. To the fullest extent permitted by law, we disclaim all warranties, express or implied.
|
||||||
3.2 Purchases and Refunds: When purchasing virtual items, you must comply with the payment rules of the app store. All purchases are final and non-refundable unless otherwise required by law or specifically stated by us.
|
7. Limitation of Liability
|
||||||
4. User-Generated Content
|
In no event shall we be liable for any damages arising from your use or inability to use the Game, including but not limited to loss of progress, device issues, or emotional frustration.
|
||||||
4.1 Content License: If you publish, upload, or share content (such as text, images, videos) in the Game, you grant us a worldwide, non-exclusive, perpetual, royalty-free license to use it for purposes related to promoting and improving the Game.
|
8. Changes to These Terms
|
||||||
4.2 Content Responsibility: You are responsible for the content you publish and must ensure it does not infringe any third-party rights or violate applicable laws.
|
We may update these Terms from time to time. If we make material changes, we will post the revised version online. Continued use of the Game after changes take effect constitutes your acceptance.
|
||||||
5. Privacy Protection
|
9. Termination
|
||||||
We value your privacy. Please refer to our [Privacy Policy] for details on how we collect, use, and protect your personal information.
|
We reserve the right to discontinue the Game at any time. You may stop using the Game at any time by uninstalling it.
|
||||||
6. Disclaimer of Warranties
|
10. Contact Us
|
||||||
6.1 Service Provided "As Is" and "As Available": The Game is provided on an "as is" and "as available" basis. We do not guarantee that the Game will be uninterrupted or error-free.
|
For any questions regarding these Terms, please contact:
|
||||||
6.2 Limitation of Liability: To the maximum extent permitted by applicable law, we shall not be liable for any direct, indirect, incidental, or consequential damages arising from your use of the Game.
|
bingotornad0game@gmail.com
|
||||||
7. Termination
|
|
||||||
7.1 User Termination: You may stop using the Game and delete your account at any time.
|
|
||||||
7.2 Our Termination: We may suspend or terminate your use of the Game without prior notice if you violate the terms of this Agreement.
|
|
||||||
8. Governing Law and Dispute Resolution
|
|
||||||
8.1 Governing Law: This Agreement is governed by the laws of your jurisdiction.
|
|
||||||
8.2 Dispute Resolution: In case of any disputes arising from this Agreement, both parties should seek to resolve them amicably. If resolution cannot be reached, the dispute should be submitted to the court in your jurisdiction.
|
|
||||||
9. Contact Us
|
|
||||||
If you have any questions about this Agreement, please contact us at:
|
|
||||||
- Email: mtop17600@gmail.com
|
|
||||||
@@ -126,7 +126,7 @@ namespace BingoBrain
|
|||||||
|
|
||||||
if (!json.StartsWith("{"))
|
if (!json.StartsWith("{"))
|
||||||
{
|
{
|
||||||
json = Encoding.UTF8.GetString(Base64Kit_sdk.Decrypt(Encoding.UTF8.GetBytes(json),
|
json = Encoding.UTF8.GetString(Base64Kit_sdk.DecryptJson(Encoding.UTF8.GetBytes(json),
|
||||||
NetworkManager.packName));
|
NetworkManager.packName));
|
||||||
}
|
}
|
||||||
Debug.Log("转化后的json" + json);
|
Debug.Log("转化后的json" + json);
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ public class LoginSystem_sdk
|
|||||||
// device_id ="E742FE8B-C32E-56A7-8F8A-6B3BC0F3169",
|
// device_id ="E742FE8B-C32E-56A7-8F8A-6B3BC0F3169",
|
||||||
pack_name = NetworkManager.packName,
|
pack_name = NetworkManager.packName,
|
||||||
app_version = Application.version,
|
app_version = Application.version,
|
||||||
// channel = BingoBea.Instance.attribution,
|
secret = "FJC3WBAF2", // 这里的值要和你们项目约定的 Secret 保持一致
|
||||||
// sim = WebviewManager.haveSimCard
|
|
||||||
};
|
};
|
||||||
Debug.Log(JsonConvert.SerializeObject(requestLoginData));
|
Debug.Log(JsonConvert.SerializeObject(requestLoginData));
|
||||||
Debug.Log(SystemInfo.deviceUniqueIdentifier);
|
Debug.Log(SystemInfo.deviceUniqueIdentifier);
|
||||||
@@ -77,7 +77,7 @@ public class LoginSystem_sdk
|
|||||||
|
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
NetworkKit_sdk.CDNUrl = $"{loginData.cdn_url}/";
|
NetworkKit_sdk.CDNUrl = $"{loginData.cdn_url}/";
|
||||||
NetworkKit_sdk.SetCacheToken(loginData.token);
|
NetworkKit_sdk.SetCacheToken(loginData.token);
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ public class LoginSystem_sdk
|
|||||||
// {
|
// {
|
||||||
// RequestHeart();
|
// RequestHeart();
|
||||||
|
|
||||||
// GameHelper.PostFunnelLogin("loginRecv", true);
|
// GameHelper.PostFunnelLogin("loginRecv", true);
|
||||||
ConfigSystem_sdk.Instance.OnRequestGetConfig();
|
ConfigSystem_sdk.Instance.OnRequestGetConfig();
|
||||||
// if (GameHelper.IsGiftSwitch())
|
// if (GameHelper.IsGiftSwitch())
|
||||||
// {
|
// {
|
||||||
@@ -170,4 +170,5 @@ public class RequestLoginData_sdk
|
|||||||
public string app_version;
|
public string app_version;
|
||||||
public string channel;
|
public string channel;
|
||||||
public bool sim;
|
public bool sim;
|
||||||
|
public string secret;
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ using System.Linq;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using FutureCore;
|
using FutureCore;
|
||||||
using ScrewsMaster;
|
using ScrewsMaster;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -35,16 +36,16 @@ public class NetworkKit_sdk
|
|||||||
PlayerPrefs.SetString(JarvisToken_SDK, token);
|
PlayerPrefs.SetString(JarvisToken_SDK, token);
|
||||||
}
|
}
|
||||||
public const string DomainDebugUrl = @"https://sdkapi.jsoncompare.online/";
|
public const string DomainDebugUrl = @"https://sdkapi.jsoncompare.online/";
|
||||||
public static string DomainRelease = "zoomatchsolo.top";
|
public static string DomainRelease = "web.zoomatchsolo.top";
|
||||||
|
// https://web.zoomatchsolo.top
|
||||||
// 改为只读属性,实时获取(等调用时 DomainRelease 早就初始化好了)
|
// 改为只读属性,实时获取(等调用时 DomainRelease 早就初始化好了)
|
||||||
public static string DomainReleaseUrl => $"https://{DomainRelease}/sdkapi/";
|
public static string DomainReleaseUrl => $"https://{DomainRelease}/api/";
|
||||||
|
|
||||||
// 改为只读属性,实时获取
|
// 改为只读属性,实时获取
|
||||||
#if JarvisRelease
|
#if JarvisRelease
|
||||||
public static string CrazyUrl => DomainReleaseUrl;
|
public static string CrazyUrl => DomainReleaseUrl;
|
||||||
#else
|
#else
|
||||||
public static string CrazyUrl => DomainDebugUrl;
|
public static string CrazyUrl => DomainDebugUrl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -54,10 +55,10 @@ public class NetworkKit_sdk
|
|||||||
string requestJson = JsonConvert.SerializeObject(requestData);
|
string requestJson = JsonConvert.SerializeObject(requestData);
|
||||||
|
|
||||||
string url2 = url;
|
string url2 = url;
|
||||||
#if JarvisRelease
|
// #if JarvisRelease
|
||||||
url2 = Base64Kit_sdk.Encode(url);
|
// url2 = Base64Kit_sdk.Encode(url);
|
||||||
requestJson = Base64Kit_sdk.Encode(requestJson);
|
// requestJson = Base64Kit_sdk.Encode(requestJson);
|
||||||
#endif
|
// #endif
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes(requestJson);
|
byte[] bytes = Encoding.UTF8.GetBytes(requestJson);
|
||||||
string url1 = CrazyUrl + url2;
|
string url1 = CrazyUrl + url2;
|
||||||
Debug.Log($"Url: {url1}");
|
Debug.Log($"Url: {url1}");
|
||||||
@@ -79,22 +80,24 @@ public class NetworkKit_sdk
|
|||||||
yield return loginRequest.SendWebRequest();
|
yield return loginRequest.SendWebRequest();
|
||||||
if (loginRequest.result is not UnityWebRequest.Result.Success)
|
if (loginRequest.result is not UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
|
string receiveContent = loginRequest.downloadHandler.text;
|
||||||
onCompleted?.Invoke(false, default);
|
onCompleted?.Invoke(false, default);
|
||||||
|
Debug.Log(url + "cuowude--------" + JsonConvert.SerializeObject(loginRequest));
|
||||||
|
Debug.Log(url + "cuowude--------" + receiveContent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string receiveContent = loginRequest.downloadHandler.text;
|
string receiveContent = loginRequest.downloadHandler.text;
|
||||||
|
Debug.Log(url + "--------" + receiveContent);
|
||||||
#if JarvisRelease
|
#if JarvisRelease
|
||||||
if (!receiveContent.IsNullOrWhiteSpace())
|
if (!receiveContent.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
receiveContent = receiveContent.Substring(0, receiveContent.Length - 1);
|
receiveContent = Base64Kit_sdk.Decrypt(receiveContent, DomainRelease);
|
||||||
receiveContent = receiveContent.Substring(1);
|
|
||||||
receiveContent = Base64Kit_sdk.Decode(receiveContent);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Debug.Log(url + "--------" + loginRequest.downloadHandler.text);
|
|
||||||
Debug.Log(url + "--------" + receiveContent);
|
Debug.Log(url + "--------" + receiveContent);
|
||||||
|
|
||||||
var response = JsonConvert.DeserializeObject<ResponseData_sdk>(receiveContent);
|
var response = JsonConvert.DeserializeObject<ResponseData_sdk>(receiveContent);
|
||||||
|
|
||||||
if (response?.code == 0)
|
if (response?.code == 0)
|
||||||
@@ -347,72 +350,82 @@ public class NetworkKit_sdk
|
|||||||
}
|
}
|
||||||
public class Base64Kit_sdk
|
public class Base64Kit_sdk
|
||||||
{
|
{
|
||||||
public static string Base64Encode(string source)
|
public static string Decrypt(string encryptedBase64, string secret)
|
||||||
{
|
{
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes(source);
|
try
|
||||||
string encode = Convert.ToBase64String(bytes);
|
|
||||||
return encode;
|
|
||||||
}
|
|
||||||
public static string Encode(string data, bool is_apple_pay = false)
|
|
||||||
{
|
|
||||||
var key = NetworkKit_sdk.DomainRelease;
|
|
||||||
//if (is_apple_pay) key = "com.leisuregames.crazygourmet";
|
|
||||||
|
|
||||||
var keyMD5 = MD5Kit.MD5String1(key);
|
|
||||||
//UnityEngine.Debug.Log("Base64 Encode Key: " + keyMD5);
|
|
||||||
var str = Base64EncodeUtil.Base64Encode(data + keyMD5);
|
|
||||||
|
|
||||||
var bytes = Encoding.UTF8.GetBytes(str);
|
|
||||||
for (int i = 0, j = bytes.Length - 1; i < j; i += 1, j -= 1)
|
|
||||||
{
|
{
|
||||||
if (i % 2 == 0)
|
if (string.IsNullOrEmpty(encryptedBase64)) return string.Empty;
|
||||||
|
|
||||||
|
// 1. 容错处理:如果密文首尾有双引号,先去掉
|
||||||
|
encryptedBase64 = encryptedBase64.Trim();
|
||||||
|
if (encryptedBase64.StartsWith("\"") && encryptedBase64.EndsWith("\""))
|
||||||
{
|
{
|
||||||
(bytes[i], bytes[j]) = (bytes[j], bytes[i]);
|
encryptedBase64 = encryptedBase64.Substring(1, encryptedBase64.Length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 将 URL 安全的 Base64 替换为标准 Base64 字符
|
||||||
|
string standardBase64 = encryptedBase64.Replace('-', '+').Replace('_', '/');
|
||||||
|
int mod4 = standardBase64.Length % 4;
|
||||||
|
if (mod4 > 0)
|
||||||
|
{
|
||||||
|
standardBase64 += new string('=', 4 - mod4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 将 Base64 转换为字节数组
|
||||||
|
byte[] cipherData = Convert.FromBase64String(standardBase64);
|
||||||
|
|
||||||
|
if (cipherData.Length < 16)
|
||||||
|
{
|
||||||
|
throw new Exception("密文长度过短,不满足 AES 块大小要求");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 【生成 Key】将 Secret 进行 SHA256 哈希,得到 32 字节的 AES Key
|
||||||
|
byte[] keyBytes;
|
||||||
|
using (SHA256 sha256 = SHA256.Create())
|
||||||
|
{
|
||||||
|
keyBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 【提取 IV】密文的前 16 字节是随机生成的初始化向量 (IV)
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
Array.Copy(cipherData, 0, iv, 0, 16);
|
||||||
|
|
||||||
|
// 6. 【提取实际密文】16 字节之后的数据才是真正的加密数据
|
||||||
|
int encryptedDataLength = cipherData.Length - 16;
|
||||||
|
byte[] encryptedData = new byte[encryptedDataLength];
|
||||||
|
Array.Copy(cipherData, 16, encryptedData, 0, encryptedDataLength);
|
||||||
|
|
||||||
|
// 7. 进行 AES-256-CBC 解密
|
||||||
|
using (Aes aes = Aes.Create())
|
||||||
|
{
|
||||||
|
aes.KeySize = 256;
|
||||||
|
aes.BlockSize = 128;
|
||||||
|
aes.Mode = CipherMode.CBC;
|
||||||
|
aes.Padding = PaddingMode.PKCS7; // 对应 Go 的 PKCS7Padding
|
||||||
|
|
||||||
|
aes.Key = keyBytes;
|
||||||
|
aes.IV = iv;
|
||||||
|
|
||||||
|
using (ICryptoTransform decryptor = aes.CreateDecryptor())
|
||||||
|
{
|
||||||
|
using (MemoryStream ms = new MemoryStream(encryptedData))
|
||||||
|
{
|
||||||
|
using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
|
||||||
|
{
|
||||||
|
using (StreamReader sr = new StreamReader(cs, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
return sr.ReadToEnd(); // 解密出来的明文 JSON 字符串
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
var loginData = Encoding.UTF8.GetString(bytes);
|
|
||||||
return loginData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Decode(string data)
|
|
||||||
{
|
|
||||||
var bytes = Encoding.UTF8.GetBytes(data);
|
|
||||||
for (int i = 0, j = bytes.Length - 1; i < j; i += 1, j -= 1)
|
|
||||||
{
|
{
|
||||||
if (i % 2 == 0)
|
UnityEngine.Debug.LogError("解密失败: " + ex.Message);
|
||||||
{
|
return string.Empty;
|
||||||
(bytes[i], bytes[j]) = (bytes[j], bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var str = Encoding.UTF8.GetString(bytes);
|
|
||||||
var str1 = Base64EncodeUtil.Base64Decode(str);
|
|
||||||
var key = NetworkKit_sdk.DomainRelease;
|
|
||||||
var keyMD5 = MD5Kit.MD5String1(key);
|
|
||||||
// Debug.Log("Base64 Decode Key: " + keyMD5);
|
|
||||||
// Debug.Log("Base64 Decode str1: " + str1);
|
|
||||||
var result = str1.Replace(keyMD5, string.Empty);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string Decode(string data, string key)
|
|
||||||
{
|
|
||||||
var bytes = Encoding.UTF8.GetBytes(data);
|
|
||||||
for (int i = 0, j = bytes.Length - 1; i < j; i += 1, j -= 1)
|
|
||||||
{
|
|
||||||
if (i % 2 == 0)
|
|
||||||
{
|
|
||||||
(bytes[i], bytes[j]) = (bytes[j], bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var str = Encoding.UTF8.GetString(bytes);
|
|
||||||
var str1 = Base64EncodeUtil.Base64Decode(str);
|
|
||||||
// var key = NetworkManager.DomainRelease;
|
|
||||||
var keyMD5 = MD5Kit.MD5String1(key);
|
|
||||||
var result = str1.Replace(keyMD5, string.Empty);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
private static byte[] GenerateKey(string secret)
|
private static byte[] GenerateKey(string secret)
|
||||||
{
|
{
|
||||||
@@ -420,30 +433,7 @@ public class Base64Kit_sdk
|
|||||||
return sha256.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
return sha256.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static byte[] Encrypt(byte[] plainText, string secret)
|
internal static byte[] DecryptJson(byte[] encryptedBase64, string secret)
|
||||||
{
|
|
||||||
if (plainText == null || plainText.Length == 0) return plainText;
|
|
||||||
var key = GenerateKey(secret);
|
|
||||||
using var aes = Aes.Create();
|
|
||||||
aes.Key = key;
|
|
||||||
aes.Mode = CipherMode.CBC;
|
|
||||||
aes.Padding = PaddingMode.None;
|
|
||||||
aes.GenerateIV();
|
|
||||||
var iv = aes.IV;
|
|
||||||
var blockSize = aes.BlockSize / 8;
|
|
||||||
var padding = blockSize - plainText.Length % blockSize;
|
|
||||||
var padded = new byte[plainText.Length + padding];
|
|
||||||
Buffer.BlockCopy(plainText, 0, padded, 0, plainText.Length);
|
|
||||||
for (var i = plainText.Length; i < padded.Length; i++) padded[i] = (byte)padding;
|
|
||||||
using var encryptor = aes.CreateEncryptor();
|
|
||||||
var encrypted = encryptor.TransformFinalBlock(padded, 0, padded.Length);
|
|
||||||
var result = new byte[iv.Length + encrypted.Length];
|
|
||||||
Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
|
|
||||||
Buffer.BlockCopy(encrypted, 0, result, iv.Length, encrypted.Length);
|
|
||||||
return ToUrlSafeBase64(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static byte[] Decrypt(byte[] encryptedBase64, string secret)
|
|
||||||
{
|
{
|
||||||
if (encryptedBase64 == null || encryptedBase64.Length == 0) return encryptedBase64;
|
if (encryptedBase64 == null || encryptedBase64.Length == 0) return encryptedBase64;
|
||||||
var key = GenerateKey(secret);
|
var key = GenerateKey(secret);
|
||||||
@@ -464,36 +454,6 @@ public class Base64Kit_sdk
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用双引号包裹字节数组
|
|
||||||
private static byte[] QuoteBytes(byte[] input)
|
|
||||||
{
|
|
||||||
var result = new byte[input.Length + 2];
|
|
||||||
result[0] = (byte)'"';
|
|
||||||
Buffer.BlockCopy(input, 0, result, 1, input.Length);
|
|
||||||
result[result.Length - 1] = (byte)'"';
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 去除双引号(如果存在)
|
|
||||||
internal static byte[] UnquoteBytes(byte[] input)
|
|
||||||
{
|
|
||||||
if (input.Length >= 2 && input[0] == (byte)'"' && input[input.Length - 1] == (byte)'"')
|
|
||||||
{
|
|
||||||
var result = new byte[input.Length - 2];
|
|
||||||
Buffer.BlockCopy(input, 1, result, 0, result.Length);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] ToUrlSafeBase64(byte[] data)
|
|
||||||
{
|
|
||||||
var base64 = Convert.ToBase64String(data);
|
|
||||||
var urlSafe = base64.Replace('+', '-').Replace('/', '_');
|
|
||||||
return Encoding.UTF8.GetBytes(urlSafe);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] FromUrlSafeBase64(byte[] urlSafe)
|
private static byte[] FromUrlSafeBase64(byte[] urlSafe)
|
||||||
{
|
{
|
||||||
var base64 = Encoding.UTF8.GetString(urlSafe).Replace('-', '+').Replace('_', '/');
|
var base64 = Encoding.UTF8.GetString(urlSafe).Replace('-', '+').Replace('_', '/');
|
||||||
|
|||||||
Reference in New Issue
Block a user