Compare commits
No commits in common. "2fa583de83eb8ea07c71c31db36a5b5c7447fac0" and "8d0362c9bcec6cfa82644f280e06ee9f978eaee0" have entirely different histories.
2fa583de83
...
8d0362c9bc
|
|
@ -121,14 +121,6 @@ namespace WZ
|
||||||
{
|
{
|
||||||
StaticValue.AdmobCollapsibleBannerId = valueTemp;
|
StaticValue.AdmobCollapsibleBannerId = valueTemp;
|
||||||
}
|
}
|
||||||
else if (_configs[i].Key.ToLower() == KEY_TF_IAP_CHECK_ORDER.ToLower())
|
|
||||||
{
|
|
||||||
StaticValue.CheckOrderUrl = valueTemp;
|
|
||||||
}
|
|
||||||
else if (_configs[i].Key.ToLower() == KEY_TF_IAP_REPORT.ToLower())
|
|
||||||
{
|
|
||||||
StaticValue.VerifyPurchaseUrl = valueTemp;
|
|
||||||
}
|
|
||||||
else if (_configs[i].Key.ToLower() == KEY_Admob_NormalBannerId.ToLower())
|
else if (_configs[i].Key.ToLower() == KEY_Admob_NormalBannerId.ToLower())
|
||||||
{
|
{
|
||||||
StaticValue.AdmobNormalBannerId = valueTemp;
|
StaticValue.AdmobNormalBannerId = valueTemp;
|
||||||
|
|
@ -331,8 +323,6 @@ namespace WZ
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public const string KEY_TF_IAP_CHECK_ORDER = "TF_IAP_CHECK_ORDER";
|
|
||||||
public const string KEY_TF_IAP_REPORT = "TF_IAP_REPORT";
|
|
||||||
public const string KEY_Admob_CollapsibleBannerId = "Admob_Banner_ID1";
|
public const string KEY_Admob_CollapsibleBannerId = "Admob_Banner_ID1";
|
||||||
public const string KEY_Admob_NormalBannerId = "Admob_Banner_ID2";
|
public const string KEY_Admob_NormalBannerId = "Admob_Banner_ID2";
|
||||||
public const string KEY_Admob_SplashId = "Admob_APPOPEN_ID";
|
public const string KEY_Admob_SplashId = "Admob_APPOPEN_ID";
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ namespace WZ
|
||||||
|
|
||||||
public static class StaticValue
|
public static class StaticValue
|
||||||
{
|
{
|
||||||
public static string CheckOrderUrl = "";
|
|
||||||
public static string VerifyPurchaseUrl = "";
|
|
||||||
public static string AdmobCollapsibleBannerId = "";
|
public static string AdmobCollapsibleBannerId = "";
|
||||||
|
|
||||||
public static string AdmobNormalBannerId = "";
|
public static string AdmobNormalBannerId = "";
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ using System.Threading.Tasks;
|
||||||
using AdjustSdk;
|
using AdjustSdk;
|
||||||
using ThinkingData.Analytics;
|
using ThinkingData.Analytics;
|
||||||
using Unity.VisualScripting;
|
using Unity.VisualScripting;
|
||||||
using Unity.VisualScripting.Antlr3.Runtime.Tree;
|
|
||||||
using UnityEditor.ShaderKeywordFilter;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using WZ;
|
using WZ;
|
||||||
|
|
||||||
|
|
@ -20,11 +18,6 @@ public class AdjustManager : D_MonoSingleton<AdjustManager>
|
||||||
private string callbackNetwork = "";
|
private string callbackNetwork = "";
|
||||||
bool m_start = false;
|
bool m_start = false;
|
||||||
private int callGetTimes = 0;
|
private int callGetTimes = 0;
|
||||||
private string _adjustNetwork = "_adjustNetwork";
|
|
||||||
private string _adjustCampaign = "_adjustCampaign";
|
|
||||||
private string _adjustAdgroup = "_adjustAdgroup";
|
|
||||||
private string _adjustCreative = "_adjustCreative";
|
|
||||||
private string _adjustClickLabel = "_adjustClickLabel";
|
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
|
|
@ -179,37 +172,8 @@ public class AdjustManager : D_MonoSingleton<AdjustManager>
|
||||||
});
|
});
|
||||||
|
|
||||||
RushSDKManager.Instance.OnUserSourceListener?.Invoke(IsOrganic(network), network);
|
RushSDKManager.Instance.OnUserSourceListener?.Invoke(IsOrganic(network), network);
|
||||||
PlayerPrefsUtils.SavePlayerPrefsString(_adjustNetwork, network);
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsString(_adjustCampaign, campaign);
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsString(_adjustAdgroup, adgroup);
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsString(_adjustCreative, creative);
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsString(_adjustClickLabel, attribution?.ClickLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAdjustNetwork()
|
|
||||||
{
|
|
||||||
return PlayerPrefsUtils.GetPlayerPrefsString(_adjustNetwork);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAdjustCampaign()
|
|
||||||
{
|
|
||||||
return PlayerPrefsUtils.GetPlayerPrefsString(_adjustCampaign);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAdjustAdgroup()
|
|
||||||
{
|
|
||||||
return PlayerPrefsUtils.GetPlayerPrefsString(_adjustAdgroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAdjustCreative()
|
|
||||||
{
|
|
||||||
return PlayerPrefsUtils.GetPlayerPrefsString(_adjustCreative);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAdjustClickLabel()
|
|
||||||
{
|
|
||||||
return PlayerPrefsUtils.GetPlayerPrefsString(_adjustClickLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsOrganic(string _network)
|
private bool IsOrganic(string _network)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2ebf62044324047e78f251d34185ff48
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: ca2f9d75394fd4e859f89e488d422e80
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
public enum IAPDataStateType
|
|
||||||
{
|
|
||||||
// 未处理
|
|
||||||
def,
|
|
||||||
// 处理中
|
|
||||||
deal
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 0595ab8f5ac6241689d314aec6c7a3ab
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
|
|
||||||
public enum IAPResultType
|
|
||||||
{
|
|
||||||
PurchasingUnavailable, // 无法使用系统购买功能
|
|
||||||
ExistingPurchasePending, // 请求新购买时正在进行前一项购买
|
|
||||||
ProductUnavailable, // 无法在商店购买商品
|
|
||||||
SignatureInvalid, // 购买收据的签名验证失败
|
|
||||||
UserCancelled, // 用户选择取消而不是继续购买
|
|
||||||
PaymentDeclined, // 付款出现问题
|
|
||||||
DuplicateTransaction, // 当交易已经成功完成时出现的重复交易错误
|
|
||||||
Unknown, // 未识别的购买问题的通用原因
|
|
||||||
ServerRequestFailed, // 客户端购买成功请求服务端失败
|
|
||||||
ServerAuthenticationFailed, // 客户端购买成功服务端验证失败
|
|
||||||
PurchasingSuccess,
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 2aa385284497442cebdff40e44bad707
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,236 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
#if UNITY_PURCHASE
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
public static class IAPEvent
|
|
||||||
{
|
|
||||||
public static void LogPurchaseInit()
|
|
||||||
{
|
|
||||||
var eventName = "Purchase_Init";
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName);
|
|
||||||
ShuShuEvent.Instance.Track(eventName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogPurchaseInit(bool success, string message = "")
|
|
||||||
{
|
|
||||||
var eventName = success ? "Purchase_Init_Success" : "Purchase_Init_Fail";
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName);
|
|
||||||
ShuShuEvent.Instance.Track(eventName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, new Dictionary<string, object> { { "fail_reason", message } });
|
|
||||||
ShuShuEvent.Instance.Track(eventName, new Dictionary<string, object> { { "fail_reason", message } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogPurchaseSuccess(PurchaseInfo info,string environment)
|
|
||||||
{
|
|
||||||
// 总支付次数
|
|
||||||
int payTimes = PlayerPrefsUtils.GetPlayerPrefsInt("PAY_TIME", 0);
|
|
||||||
if (!info.orderAlreadyExists)
|
|
||||||
{
|
|
||||||
payTimes += 1;
|
|
||||||
}
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var args = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "Price", fPrice },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "game_extra", info.gameExtra },
|
|
||||||
{ "is_first", PlayerPrefsUtils.GetPlayerPrefsInt(First_Purchase, 0) == 0},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "product_type", info.productType },
|
|
||||||
{ "orderAlreadyExists", info.orderAlreadyExists }
|
|
||||||
};
|
|
||||||
if (string.IsNullOrEmpty(environment)) environment = "";
|
|
||||||
var eventName = environment.Equals("sandbox") ? "IAP_Success_Sandbox" : "IAP_Success";
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, args);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, args);
|
|
||||||
// 首次订单 设置支付次数/累计支付次数/累计支付金额
|
|
||||||
if (!info.orderAlreadyExists)
|
|
||||||
{
|
|
||||||
fPrice = fPrice + PlayerPrefsUtils.GetPlayerPrefsFloat(PURCHASE_PRICE, 0.0f);
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsFloat(PURCHASE_PRICE, fPrice);
|
|
||||||
|
|
||||||
ShuShuEvent.Instance.UserSet(new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "total_pay_amount", fPrice },
|
|
||||||
{ "total_pay_times", payTimes }
|
|
||||||
});
|
|
||||||
|
|
||||||
ShuShuEvent.Instance.SetSuperProperties(new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "pay_times", payTimes }
|
|
||||||
});
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsInt(First_Purchase, 1);
|
|
||||||
ShuShuEvent.Instance.UserSet(new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "first_pay_time", DateTime.Now }
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerPrefsUtils.SavePlayerPrefsInt(PAY_TIME, payTimes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogPurchaseFail(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "IAP_Fail";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var para = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "pay_amount", fPrice },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "game_extra", info.gameExtra ?? ""},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "fail_reason", info.failReason }
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, para);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, para);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogIAPButtonClick(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "IAP_Button_Click";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var args = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName},
|
|
||||||
{ "product_id", info.productID},
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "Price", fPrice },
|
|
||||||
{ "game_extra", info.gameExtra},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, args);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogClientComplete(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "Client_Finish_Channel";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var para = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "Price", fPrice },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "game_extra", info.gameExtra ?? ""},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "product_type",info.productType},
|
|
||||||
{ "is_first", PlayerPrefsUtils.GetPlayerPrefsInt(First_Purchase, 0) == 0 }
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, para);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, para);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogSaveOrderBySdk(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "IAP_SDK_Save_Order";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var para = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "price", fPrice },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "game_extra", info.gameExtra ?? ""},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "product_type",info.productType},
|
|
||||||
{ "is_first", PlayerPrefsUtils.GetPlayerPrefsInt(First_Purchase, 0) == 0 }
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, para);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, para);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogStarVerifyOrderBySdk(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "IAP_Cache_Order";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var para = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "price", fPrice },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "game_extra", info.gameExtra},
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "product_type",info.productType},
|
|
||||||
{ "is_first", PlayerPrefsUtils.GetPlayerPrefsInt(First_Purchase, 0) == 0 }
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, para);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, para);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogRemoveOrderBySdk(PurchaseInfo info)
|
|
||||||
{
|
|
||||||
var eventName = "IAP_SDK_Remove_Order";
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(info.price, out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
var para = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "price", fPrice },
|
|
||||||
{ "product_id", info.productID },
|
|
||||||
{ "IAP", info.productName },
|
|
||||||
{ "order_id", info.orderID },
|
|
||||||
{ "currency", info.currency },
|
|
||||||
{ "payment_method", "googleplay" },
|
|
||||||
{ "game_extra", info.gameExtra},
|
|
||||||
{ "product_type", info.productType}
|
|
||||||
};
|
|
||||||
FireBaseAnalyticsManager.Instance.LogEvent(eventName, para);
|
|
||||||
ShuShuEvent.Instance.Track(eventName, para);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string First_Purchase = "First_purchase";
|
|
||||||
public static string PAY_TIME = "PAY_TIME";
|
|
||||||
public static string PURCHASE_PRICE = "PURCHASE_PRICE";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 273e000ea028247038e5e7f8f756fbc0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
public struct PurchaseInfo
|
|
||||||
{
|
|
||||||
public string productName;
|
|
||||||
public string productID;
|
|
||||||
public string orderID;
|
|
||||||
public string currency;
|
|
||||||
public string price;
|
|
||||||
public string gameExtra;
|
|
||||||
public string productType;
|
|
||||||
public string failReason;
|
|
||||||
public bool orderAlreadyExists;
|
|
||||||
public bool purchaseResult;
|
|
||||||
public IAPResultType resultType;
|
|
||||||
public PurchaseInfo(string productName, string productID, string orderID,
|
|
||||||
string currency, string price, string gameExtra,
|
|
||||||
string productType, string failReason, bool orderAlreadyExists, bool purchaseResult,
|
|
||||||
IAPResultType resultType)
|
|
||||||
{
|
|
||||||
this.productName = productName;
|
|
||||||
this.productID = productID;
|
|
||||||
this.orderID = orderID;
|
|
||||||
this.currency = currency;
|
|
||||||
this.price = price;
|
|
||||||
this.gameExtra = gameExtra;
|
|
||||||
this.productType = productType;
|
|
||||||
this.failReason = failReason;
|
|
||||||
this.orderAlreadyExists = orderAlreadyExists;
|
|
||||||
this.purchaseResult = purchaseResult;
|
|
||||||
this.resultType = resultType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d2378dd12f2d41c190fc63f6016b4d8
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,395 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
|
|
||||||
public class IAPOrderManager : D_MonoSingleton<IAPOrderManager>
|
|
||||||
{
|
|
||||||
private static string _purchaseOrderMap = "PurchaseOrderMap";
|
|
||||||
private List<int> NotRetryCode = new List<int> { 0, 430, 900, 901, 902, 903, 904, 905 };
|
|
||||||
private Dictionary<string, int> mRepeatCountDic;
|
|
||||||
|
|
||||||
#region 订单验证
|
|
||||||
public void VerifyPurchase(IAPDataConfig args)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] Start VerifyPurchase orderid:" + args.info["order_id"] + "status:" + args.state);
|
|
||||||
if (args.state == IAPDataStateType.def)
|
|
||||||
{
|
|
||||||
// 记录订单处理次数,处理5次还是失败就不处理了
|
|
||||||
if (mRepeatCountDic.ContainsKey(args.info["order_id"]))
|
|
||||||
{
|
|
||||||
mRepeatCountDic[args.info["order_id"]] = mRepeatCountDic[args.info["order_id"]] + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mRepeatCountDic.Add(args.info["order_id"], 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开始处理,设置正在处理的状态
|
|
||||||
RefreshOrderStatue(args, IAPDataStateType.deal);
|
|
||||||
args.info.TryGetValue("mGameExtraParam", out var gameExtraParam);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(gameExtraParam))
|
|
||||||
{
|
|
||||||
gameExtraParam = IAPPurchaseManager.Instance._gameExtraParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] IAP VerifyPurchase start");
|
|
||||||
var requestArgs = args.info.ToDictionary(kv => kv.Key, kv => (object)kv.Value);
|
|
||||||
ServerMgr.Instance.VerifyPurchase(requestArgs, (code, msg, data) =>
|
|
||||||
{
|
|
||||||
RefreshOrderStatue(args, IAPDataStateType.def);
|
|
||||||
LoggerUtils.Debug("IAP VerifyPurchase CODE:" + code + " illegal:" + data.illegal_order + " env:" + data.environment);
|
|
||||||
LoggerUtils.Debug("IAP VerifyPurchase msg:" + msg);
|
|
||||||
|
|
||||||
if ((code == 0 || code == 430) && data.illegal_order == 0)
|
|
||||||
{
|
|
||||||
// 将订阅商品信息存储到本地
|
|
||||||
if (!IAPPurchaseManager.Instance._productArgs.ContainsKey(args.info["product_id"].ToString()) && args.info["product_type"].ToString().Equals("Subscription"))
|
|
||||||
{
|
|
||||||
IAPPurchaseManager.Instance._productArgs.Add(args.info["product_id"].ToString(), requestArgs);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (IAPPurchaseManager.Instance._productArgs.ContainsKey(args.info["product_id"].ToString()) && args.info["product_type"].ToString().Equals("Subscription"))
|
|
||||||
{
|
|
||||||
IAPPurchaseManager.Instance._productArgs[args.info["product_id"].ToString()] = requestArgs;
|
|
||||||
}
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete?.Invoke(new PurchaseInfo(
|
|
||||||
productName: args.info["product_name"],
|
|
||||||
productID: args.info["product_id"],
|
|
||||||
orderID: args.info["order_id"],
|
|
||||||
currency: args.info["currency"],
|
|
||||||
price: args.info["price"],
|
|
||||||
gameExtra: gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: code == 430,
|
|
||||||
purchaseResult: code == 0,
|
|
||||||
resultType: IAPResultType.PurchasingSuccess,
|
|
||||||
productType: args.info["product_type"]
|
|
||||||
));
|
|
||||||
LogVerifySuccessOrder(args, data.environment, gameExtraParam, code == 430);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 不需要重试的错误码
|
|
||||||
if (!NotRetryCode.Contains(code))
|
|
||||||
{
|
|
||||||
SaveVerifyFailOrderId(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 主动删除过期订单
|
|
||||||
if (!string.IsNullOrEmpty(data.illegal_msg) && args.info["product_type"].ToString().Equals("Subscription"))
|
|
||||||
{
|
|
||||||
if (data.illegal_msg.Contains("product expired"))
|
|
||||||
{
|
|
||||||
RemoveVerifySuccessOrder(args.info["product_id"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (code == -1)
|
|
||||||
{
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete?.Invoke(new PurchaseInfo(
|
|
||||||
productName: args.info["product_name"],
|
|
||||||
productID: args.info["product_id"],
|
|
||||||
orderID: args.info["order_id"],
|
|
||||||
currency: args.info["currency"],
|
|
||||||
price: args.info["price"],
|
|
||||||
gameExtra: gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: code == 430,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: args.info["product_type"]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete?.Invoke(new PurchaseInfo(
|
|
||||||
productName: args.info["product_name"],
|
|
||||||
productID: args.info["product_id"],
|
|
||||||
orderID: args.info["order_id"],
|
|
||||||
currency: args.info["currency"],
|
|
||||||
price: args.info["price"],
|
|
||||||
gameExtra: gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: code == 430,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: code == 430 ? IAPResultType.PurchasingSuccess : IAPResultType.ServerAuthenticationFailed,
|
|
||||||
productType: args.info["product_type"]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// msg 包含 illegal_order_0 说明是正常的缓存订单上报
|
|
||||||
// 卸载重装后,一次性商品
|
|
||||||
if (msg.Contains("illegal_order_0"))
|
|
||||||
{
|
|
||||||
LogVerifySuccessOrder(args, msg.Contains("sandbox") ? "sandbox" : "production", gameExtraParam, code == 430);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogVerifyFailOrder(args, gameExtraParam, $"Purchase service code : {code} msg : {msg} dataMsg:{data.illegal_msg} illegal_order:{data.illegal_order} environment:{(msg.Contains("sandbox") ? "sandbox" : "production")}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LogVerifySuccessOrder(IAPDataConfig _productInfo, string _enviroment, string _gameExtraParam, bool _orderAlreadyExists)
|
|
||||||
{
|
|
||||||
IAPEvent.LogPurchaseSuccess(new PurchaseInfo(
|
|
||||||
productName: _productInfo.info["product_name"],
|
|
||||||
productID: _productInfo.info["product_id"],
|
|
||||||
orderID: _productInfo.info["order_id"],
|
|
||||||
currency: _productInfo.info["currency"],
|
|
||||||
price: _productInfo.info["price"],
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: _orderAlreadyExists,
|
|
||||||
purchaseResult: !_orderAlreadyExists,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: _productInfo.info["product_type"]
|
|
||||||
), _enviroment);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LogVerifyFailOrder(IAPDataConfig _productInfo, string _gameExtraParam, string _errInfo)
|
|
||||||
{
|
|
||||||
|
|
||||||
IAPEvent.LogPurchaseFail(new PurchaseInfo(
|
|
||||||
productName: _productInfo.info["product_name"],
|
|
||||||
productID: _productInfo.info["product_id"],
|
|
||||||
orderID: _productInfo.info["order_id"],
|
|
||||||
currency: _productInfo.info["currency"],
|
|
||||||
price: _productInfo.info["price"],
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: _errInfo,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: _productInfo.info["product_type"]
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 重置订单状态
|
|
||||||
private void RefreshOrderStatue(IAPDataConfig _productInfo, IAPDataStateType state)
|
|
||||||
{
|
|
||||||
if (ES3.KeyExists("FailOrderCacheData"))
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> list = ES3.Load(_purchaseOrderMap) as List<IAPDataConfig>;
|
|
||||||
var value = _productInfo.info["order_id"];
|
|
||||||
var want = list.Find(e => e.info.ContainsValue(value));
|
|
||||||
if (want != null)
|
|
||||||
{
|
|
||||||
want.state = state;
|
|
||||||
ES3.Save(_purchaseOrderMap, list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 存储订单
|
|
||||||
public void SaveOrder(IAPDataConfig _productInfo)
|
|
||||||
{
|
|
||||||
if (ES3.KeyExists(_purchaseOrderMap))
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> list = ES3.Load(_purchaseOrderMap) as List<IAPDataConfig>;
|
|
||||||
var want = list.Find(e => e.info.ContainsValue(_productInfo.info["order_id"]));
|
|
||||||
if (want == null)
|
|
||||||
{
|
|
||||||
list.Add(_productInfo);
|
|
||||||
ES3.Save(_purchaseOrderMap, list);
|
|
||||||
IAPEvent.LogSaveOrderBySdk(new PurchaseInfo(
|
|
||||||
productName: _productInfo.info["product_name"],
|
|
||||||
productID: _productInfo.info["product_id"],
|
|
||||||
orderID: _productInfo.info["order_id"],
|
|
||||||
currency: _productInfo.info["currency"],
|
|
||||||
price: _productInfo.info["price"],
|
|
||||||
gameExtra: _productInfo.info["mGameExtraParam"],
|
|
||||||
productType: _productInfo.info["product_type"],
|
|
||||||
failReason: null,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL
|
|
||||||
));
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] IAP SaveOrder 已经有表了,添加订单,订单ID:" + _productInfo.info["order_id"] + " 未验证订单个数:" + list.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> tem = new List<IAPDataConfig>
|
|
||||||
{
|
|
||||||
_productInfo
|
|
||||||
};
|
|
||||||
ES3.Save(_purchaseOrderMap, tem);
|
|
||||||
IAPEvent.LogSaveOrderBySdk(new PurchaseInfo(
|
|
||||||
productName: _productInfo.info["product_name"],
|
|
||||||
productID: _productInfo.info["product_id"],
|
|
||||||
orderID: _productInfo.info["order_id"],
|
|
||||||
currency: _productInfo.info["currency"],
|
|
||||||
price: _productInfo.info["price"],
|
|
||||||
gameExtra: _productInfo.info["mGameExtraParam"],
|
|
||||||
productType: _productInfo.info["product_type"],
|
|
||||||
failReason: null,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL
|
|
||||||
));
|
|
||||||
LoggerUtils.Debug("[iap] IAP SaveOrder 第一次存储表 添加订单ID:" + _productInfo.info["order_id"] + " 商品类型:" + _productInfo.info["product_type"] + " 订单个数:" + tem.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 保存验证失败订单
|
|
||||||
private bool inDealFailOrder;
|
|
||||||
private void SaveVerifyFailOrderId(IAPDataConfig _productInfo)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] iap save verify fail order,orderId:" + _productInfo.info["order_id"] + " 商品类型:" + _productInfo.info["product_type"]);
|
|
||||||
if (ES3.KeyExists(_purchaseOrderMap))
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> list = ES3.Load(_purchaseOrderMap) as List<IAPDataConfig>;
|
|
||||||
|
|
||||||
var value = _productInfo.info["order_id"];
|
|
||||||
var want = list.Find(e => e.info.ContainsValue(value));
|
|
||||||
if (want == null)
|
|
||||||
{
|
|
||||||
list.Add(_productInfo);
|
|
||||||
ES3.Save(_purchaseOrderMap, list);
|
|
||||||
ReadFailOrderId();
|
|
||||||
LoggerUtils.Debug("[iap] IAP SaveVerifyFailOrderId 已经有表了,添加失败订单,订单ID:" + _productInfo.info["order_id"] + " 商品类型:" + _productInfo.info["product_type"]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!inDealFailOrder)
|
|
||||||
{
|
|
||||||
inDealFailOrder = true;
|
|
||||||
InvokeRepeating(nameof(ReadFailOrderId), 0, 30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> tem = new List<IAPDataConfig>
|
|
||||||
{
|
|
||||||
_productInfo
|
|
||||||
};
|
|
||||||
ES3.Save(_purchaseOrderMap, tem);
|
|
||||||
ReadFailOrderId();
|
|
||||||
LoggerUtils.Debug("[iap] IAP SaveVerifyFailOrderId 第一次存储表 添加失败订单 订单个数:" + tem.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 再次验证订单
|
|
||||||
public void ReadFailOrderId()
|
|
||||||
{
|
|
||||||
if (ES3.KeyExists(_purchaseOrderMap))
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> list = ES3.Load(_purchaseOrderMap) as List<IAPDataConfig>;
|
|
||||||
LoggerUtils.Debug("[iap] IAP ReadFailOrderId 读取失败订单列表,count:" + list.Count + " mRepeatCountDic" + mRepeatCountDic.Count);
|
|
||||||
if (list.Count > 0)
|
|
||||||
{
|
|
||||||
// 当前进程每条订单校验5次,如果失败则不再处理
|
|
||||||
// 重复校验时判断次数是否大于5,大于5则不再处理
|
|
||||||
IAPDataConfig tempData = null;
|
|
||||||
if (mRepeatCountDic.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var data in list)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] iap start verify fail order with repeat dic" + data.info["order_id"] + " count:" + mRepeatCountDic[data.info["order_id"]]);
|
|
||||||
if (mRepeatCountDic.ContainsKey(data.info["order_id"]) && mRepeatCountDic[data.info["order_id"]] <= 5)
|
|
||||||
{
|
|
||||||
tempData = data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 如果还有次数不超过5次的订单,则继续校验,否则就不再处理
|
|
||||||
if (tempData != null)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] iap start verify fail order with repeat temp dic" + tempData.info["order_id"] + " count:" + mRepeatCountDic[tempData.info["order_id"]]);
|
|
||||||
VerifyPurchase(tempData);
|
|
||||||
IAPEvent.LogStarVerifyOrderBySdk(new PurchaseInfo(
|
|
||||||
productName: tempData.info["product_name"],
|
|
||||||
productID: tempData.info["product_id"],
|
|
||||||
orderID: tempData.info["order_id"],
|
|
||||||
currency: tempData.info["currency"],
|
|
||||||
price: tempData.info["price"],
|
|
||||||
gameExtra: tempData.info["mGameExtraParam"],
|
|
||||||
productType: tempData.info["product_type"],
|
|
||||||
failReason: null,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] iap cancel verify fail order");
|
|
||||||
CancelInvoke(nameof(ReadFailOrderId));
|
|
||||||
inDealFailOrder = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CancelInvoke(nameof(ReadFailOrderId));
|
|
||||||
inDealFailOrder = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 移除订单
|
|
||||||
// 校验成功后移除订单
|
|
||||||
public void RemoveVerifySuccessOrder(string orderId)
|
|
||||||
{
|
|
||||||
if (ES3.KeyExists(_purchaseOrderMap))
|
|
||||||
{
|
|
||||||
List<IAPDataConfig> list = ES3.Load(_purchaseOrderMap) as List<IAPDataConfig>;
|
|
||||||
var want = list.Find(e => e.info.ContainsValue(orderId));
|
|
||||||
if (want != null)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] IAP RemoveVerifySuccessOrder 找到并移除订单,订单ID:" + orderId);
|
|
||||||
list.Remove(want);
|
|
||||||
IAPEvent.LogRemoveOrderBySdk(new PurchaseInfo(
|
|
||||||
productName: want.info["product_name"],
|
|
||||||
productID: want.info["product_id"],
|
|
||||||
orderID: want.info["order_id"],
|
|
||||||
currency: want.info["currency"],
|
|
||||||
price: want.info["price"],
|
|
||||||
gameExtra: want.info["mGameExtraParam"],
|
|
||||||
productType: want.info["product_type"],
|
|
||||||
failReason: null,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL));
|
|
||||||
ES3.Save(_purchaseOrderMap, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] IAP 订单还剩余:" + list.Count + " 条未校验");
|
|
||||||
if (list.Count > 0)
|
|
||||||
{
|
|
||||||
ReadFailOrderId();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inDealFailOrder = false;
|
|
||||||
CancelInvoke(nameof(ReadFailOrderId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
public class IAPDataConfig
|
|
||||||
{
|
|
||||||
public Dictionary<string, string> info;
|
|
||||||
public IAPDataStateType state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 8c0364ee309a94459af3113c481b3206
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,581 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using NUnit.Framework.Constraints;
|
|
||||||
using Unity.Services.Core;
|
|
||||||
using Unity.Services.Core.Environments;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Purchasing;
|
|
||||||
using UnityEngine.Purchasing.Extension;
|
|
||||||
using static WZ.IAPOrderManager;
|
|
||||||
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
public class IAPPurchaseManager : D_MonoSingleton<IAPPurchaseManager>, IDetailedStoreListener
|
|
||||||
{
|
|
||||||
#region API
|
|
||||||
public void BuyProductByID(string productId, string productName, string gameExtraParam)
|
|
||||||
{
|
|
||||||
#if !UNITY_EDITOR
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete(new PurchaseInfo(
|
|
||||||
productName: productName,
|
|
||||||
productID: productId,
|
|
||||||
orderID: "",
|
|
||||||
currency: "USD",
|
|
||||||
price: "",
|
|
||||||
gameExtra: gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: true,
|
|
||||||
resultType: IAPResultType.PurchasingSuccess,
|
|
||||||
productType: ""
|
|
||||||
));
|
|
||||||
#else
|
|
||||||
_productName = productName;
|
|
||||||
_gameExtraParam = gameExtraParam;
|
|
||||||
Product m_p = GetProductInfoByID(productId);
|
|
||||||
var currencyCode = "";
|
|
||||||
var localizedPrice = "";
|
|
||||||
if (m_p != null)
|
|
||||||
{
|
|
||||||
currencyCode = m_p.metadata.isoCurrencyCode;
|
|
||||||
localizedPrice = m_p.metadata.localizedPrice.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
IAPEvent.LogIAPButtonClick(new PurchaseInfo(
|
|
||||||
productName: _productName,
|
|
||||||
productID: productId,
|
|
||||||
orderID: "",
|
|
||||||
currency: currencyCode,
|
|
||||||
price: localizedPrice,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: ""));
|
|
||||||
|
|
||||||
if (IsInitialized())
|
|
||||||
{
|
|
||||||
if (_inPurchaseProgress)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] The payment is in progress, please do not initiate the payment repeatedly.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Product product = _storeController.products.WithID(productId);
|
|
||||||
if (product != null && product.availableToPurchase)
|
|
||||||
{
|
|
||||||
_inPurchaseProgress = true;
|
|
||||||
LoggerUtils.Debug(
|
|
||||||
string.Format("[iap] Purchasing product asychronously: '{0}'", product.definition.id));
|
|
||||||
|
|
||||||
if (_googlePlayConfiguration != null)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(productName))
|
|
||||||
{
|
|
||||||
_googlePlayConfiguration.SetObfuscatedAccountId(productName);
|
|
||||||
}
|
|
||||||
_googlePlayConfiguration.SetObfuscatedProfileId(gameExtraParam);
|
|
||||||
LoggerUtils.Debug($"[iap] [BuyProductByID] 设置成功 userId = {productName} profileId = {gameExtraParam}");
|
|
||||||
}
|
|
||||||
_storeController.InitiatePurchase(product);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IAPEvent.LogPurchaseFail(new PurchaseInfo(
|
|
||||||
productName: _productName,
|
|
||||||
productID: productId,
|
|
||||||
orderID: "",
|
|
||||||
currency: currencyCode,
|
|
||||||
price: localizedPrice,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "BuyProductID FAIL. Not purchasing product, either is not found or is not available for purchase",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: product.definition.type.ToString()));
|
|
||||||
LoggerUtils.Debug("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete(new PurchaseInfo(
|
|
||||||
productName: productName,
|
|
||||||
productID: productId,
|
|
||||||
orderID: "",
|
|
||||||
currency: "",
|
|
||||||
price: "",
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "BuyProductID FAIL. IAP Not initialized or Not add product.",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.PurchasingUnavailable,
|
|
||||||
productType: ""));
|
|
||||||
|
|
||||||
IAPEvent.LogPurchaseFail(new PurchaseInfo(
|
|
||||||
productName: _productName,
|
|
||||||
productID: productId,
|
|
||||||
orderID: "",
|
|
||||||
currency: currencyCode,
|
|
||||||
price: localizedPrice,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "BuyProductID FAIL. Not purchasing product, either is not found or is not available for purchase",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: IAPResultType.NULL,
|
|
||||||
productType: ""));
|
|
||||||
LoggerUtils.Debug("[iap] BuyProductID FAIL. IAP Not initialized or Not add product.");
|
|
||||||
LoggerUtils.Debug("[iap] OnPurchaseFailed -> productId : " + productId + " , transactionID : " + "" + " , localizedPrice : " + "" + " , isoCurrencyCode : " + "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public Product GetProductInfoByID(string pID)
|
|
||||||
{
|
|
||||||
if (_storeController == null && _storeExtensionProvider == null)
|
|
||||||
return null;
|
|
||||||
for (int i = 0; i < _storeController.products.all.Length; i++)
|
|
||||||
{
|
|
||||||
Product tItem = _storeController.products.all[i];
|
|
||||||
if (tItem.definition.id.Equals(pID))
|
|
||||||
{
|
|
||||||
return tItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddProducts(Dictionary<string, ProductType> products, Action<bool, string> onProductsResult = null)
|
|
||||||
{
|
|
||||||
_initProductDic = products;
|
|
||||||
|
|
||||||
FetchAdditionalProducts(products, onProductsResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region 购买成功
|
|
||||||
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs purchaseEvent)
|
|
||||||
{
|
|
||||||
_inPurchaseProgress = false;
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] Purchase OK: " + purchaseEvent.purchasedProduct.definition.id);
|
|
||||||
|
|
||||||
var wrapper = (Dictionary<string, object>)MiniJson.JsonDecode(purchaseEvent.purchasedProduct.receipt);
|
|
||||||
var payload = (string)wrapper["Payload"];
|
|
||||||
var profileId = _gameExtraParam;
|
|
||||||
var _productName = "";
|
|
||||||
var payloadObj = (Dictionary<string, object>)MiniJson.JsonDecode(payload);
|
|
||||||
var o = (string)payloadObj["json"];
|
|
||||||
var payloadData = (Dictionary<string, object>)MiniJson.JsonDecode(o);
|
|
||||||
|
|
||||||
if (payloadData.TryGetValue("obfuscatedAccountId", out var obfuscatedAccountIdValue))
|
|
||||||
{
|
|
||||||
var obfuscatedAccountId = (string)obfuscatedAccountIdValue;
|
|
||||||
if (!string.IsNullOrEmpty(obfuscatedAccountId))
|
|
||||||
{
|
|
||||||
_productName = obfuscatedAccountId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payloadData.TryGetValue("obfuscatedProfileId", out var value))
|
|
||||||
{
|
|
||||||
var obfuscatedProfileId = (string)value;
|
|
||||||
if (!string.IsNullOrEmpty(obfuscatedProfileId))
|
|
||||||
{
|
|
||||||
profileId = obfuscatedProfileId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoggerUtils.Debug("[iap] productName" + _productName + " profileId:" + profileId);
|
|
||||||
|
|
||||||
string token = "";
|
|
||||||
string orderId = "";
|
|
||||||
if (Application.platform == RuntimePlatform.Android)
|
|
||||||
{
|
|
||||||
var gpDetails = (Dictionary<string, object>)MiniJson.JsonDecode(payload);
|
|
||||||
var gpJson = (string)gpDetails["json"];
|
|
||||||
var tokenJson = (Dictionary<string, object>)MiniJson.JsonDecode(gpJson);
|
|
||||||
token = (string)tokenJson["purchaseToken"];
|
|
||||||
orderId = (string)tokenJson["orderId"];
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] ClientIAPSuccess productId : " + purchaseEvent.purchasedProduct.definition.id
|
|
||||||
+ " , transactionID : " + orderId
|
|
||||||
+ " , token : " + token
|
|
||||||
+ " , localizedPrice : " + purchaseEvent.purchasedProduct.metadata.localizedPriceString
|
|
||||||
+ " , isoCurrencyCode : " + purchaseEvent.purchasedProduct.metadata.isoCurrencyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
IAPDataConfig newData = new IAPDataConfig();
|
|
||||||
newData.info = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "price", purchaseEvent.purchasedProduct.metadata.localizedPrice.ToString() },
|
|
||||||
{ "product_id", purchaseEvent.purchasedProduct.definition.id },
|
|
||||||
{ "product_name", (string)_productName },
|
|
||||||
{ "purchase_token", token },
|
|
||||||
{ "order_id", orderId },
|
|
||||||
{ "currency", purchaseEvent.purchasedProduct.metadata.isoCurrencyCode },
|
|
||||||
{ "payment_method", "googleplay" },
|
|
||||||
{ "product_type", purchaseEvent.purchasedProduct.definition.type.ToString() },
|
|
||||||
{ "mGameExtraParam", (string)profileId }
|
|
||||||
};
|
|
||||||
newData.state = IAPDataStateType.def;
|
|
||||||
|
|
||||||
IAPEvent.LogClientComplete(new PurchaseInfo(
|
|
||||||
productName: (string)_productName,
|
|
||||||
productID: purchaseEvent.purchasedProduct.definition.id,
|
|
||||||
orderID: orderId,
|
|
||||||
currency: purchaseEvent.purchasedProduct.metadata.isoCurrencyCode,
|
|
||||||
price: purchaseEvent.purchasedProduct.metadata.localizedPrice.ToString(),
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: "",
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: true,
|
|
||||||
resultType: IAPResultType.PurchasingSuccess,
|
|
||||||
productType: purchaseEvent.purchasedProduct.definition.type.ToString()
|
|
||||||
));
|
|
||||||
|
|
||||||
IAPOrderManager.Instance.SaveOrder(newData);
|
|
||||||
IAPOrderManager.Instance.VerifyPurchase(newData);
|
|
||||||
return PurchaseProcessingResult.Complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 动态添加商品
|
|
||||||
private void FetchAdditionalProducts(Dictionary<string, ProductType> ProductDic,
|
|
||||||
Action<bool, string> onProductsResult = null)
|
|
||||||
{
|
|
||||||
if (!IsInitialized())
|
|
||||||
{
|
|
||||||
_addProductsDic = ProductDic;
|
|
||||||
LoggerUtils.Debug("[iap] IAP not init.Now InitUnityPurchase");
|
|
||||||
InitUnityPurchase();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isFetchingAdditionalProducts)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] Now fetching additional products,don't call repeatedly");
|
|
||||||
if (onProductsResult != null)
|
|
||||||
{
|
|
||||||
onProductsResult(false, "Now fetching additional products,don't call repeatedly");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isFetchingAdditionalProducts = true;
|
|
||||||
if (ProductDic != null)
|
|
||||||
{
|
|
||||||
var additional = new HashSet<ProductDefinition>();
|
|
||||||
foreach (string tID in ProductDic.Keys)
|
|
||||||
{
|
|
||||||
additional.Add(new ProductDefinition(tID, ProductDic[tID]));
|
|
||||||
}
|
|
||||||
|
|
||||||
Action onSuccess = () =>
|
|
||||||
{
|
|
||||||
_isFetchingAdditionalProducts = false;
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] Fetched successfully!");
|
|
||||||
RushSDKManager.Instance.OnGetProductsInfo?.Invoke(_storeController.products.all);
|
|
||||||
|
|
||||||
foreach (var product in _storeController.products.all)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap]" + product.metadata.localizedTitle
|
|
||||||
+ "|" + product.metadata.localizedPriceString
|
|
||||||
+ "|" + product.metadata.localizedDescription
|
|
||||||
+ "|" + product.metadata.isoCurrencyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onProductsResult != null)
|
|
||||||
{
|
|
||||||
onProductsResult(true, "Fetched successfully!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Action<InitializationFailureReason, string> onFailure = (InitializationFailureReason i, string msg) =>
|
|
||||||
{
|
|
||||||
_isFetchingAdditionalProducts = false;
|
|
||||||
if (onProductsResult != null)
|
|
||||||
{
|
|
||||||
onProductsResult(true, "Fetching failed for the specified reason: " + i + " msg: " + msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[iap] Fetching failed for the specified reason: " + i + " msg: " + msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
_storeController.FetchAdditionalProducts(additional, onSuccess, onFailure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 初始化
|
|
||||||
public void PreInitialize()
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] PreInitialize() mServiceInit: " + _serviceInit);
|
|
||||||
if (!_serviceInit)
|
|
||||||
{
|
|
||||||
InitializeUnityServices(OnSuccess, OnError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeUnityServices(Action onSuccess, Action<string> onError)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var options = new InitializationOptions().SetEnvironmentName("production");
|
|
||||||
|
|
||||||
UnityServices.InitializeAsync(options).ContinueWith(task => onSuccess());
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
onError(exception.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void OnSuccess()
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] Congratulations!\nUnity Gaming Services has been successfully initialized.");
|
|
||||||
_serviceInit = true;
|
|
||||||
IAPEvent.LogPurchaseInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnError(string message)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug($"[iap] Unity Gaming Services failed to initialize with error: {message}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化IAP
|
|
||||||
/// </summary>
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] IAP Initialize() _storeController.Debug:" + _storeController + " m_StoreExtensionProvider: " + _storeExtensionProvider);
|
|
||||||
if (_storeController == null && _storeExtensionProvider == null)
|
|
||||||
InitUnityPurchase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitUnityPurchase()
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] IAP InitUnityPurchase() IsInitialized: " + IsInitialized());
|
|
||||||
if (IsInitialized()) return;
|
|
||||||
|
|
||||||
_repeatCountDic = new Dictionary<string, int>();
|
|
||||||
|
|
||||||
_module ??= StandardPurchasingModule.Instance();
|
|
||||||
|
|
||||||
// 配置模式;
|
|
||||||
_builder ??= ConfigurationBuilder.Instance(_module);
|
|
||||||
|
|
||||||
int productsNum = 0;
|
|
||||||
|
|
||||||
if (_initProductDic != null && _initProductDic.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (string tID in _initProductDic.Keys)
|
|
||||||
{
|
|
||||||
productsNum++;
|
|
||||||
if (!string.IsNullOrEmpty(tID))
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug($"[iap] Add InitProductDic APProducts: {tID}");
|
|
||||||
_builder.AddProduct(tID, _initProductDic[tID]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_addProductsDic != null && _addProductsDic.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (string tID in _addProductsDic.Keys)
|
|
||||||
{
|
|
||||||
productsNum++;
|
|
||||||
if (!string.IsNullOrEmpty(tID))
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug($"[iap] Add AddProductsDic IAPProducts: {tID}");
|
|
||||||
_builder.AddProduct(tID, _addProductsDic[tID]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_googlePlayConfiguration = _builder.Configure<IGooglePlayConfiguration>();
|
|
||||||
if (productsNum > 0)
|
|
||||||
{
|
|
||||||
UnityPurchasing.Initialize(this, _builder);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug(
|
|
||||||
"[iap] UnityPurchasing will not initialize.Products is empty,please add product.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsInitialized()
|
|
||||||
{
|
|
||||||
return _storeController != null && _storeExtensionProvider != null;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 初始化成功
|
|
||||||
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] IAP initialize Succeed!");
|
|
||||||
|
|
||||||
_storeController = controller;
|
|
||||||
_storeExtensionProvider = extensions;
|
|
||||||
|
|
||||||
RushSDKManager.Instance.OnGetProductsInfo?.Invoke(_storeController.products.all);
|
|
||||||
foreach (var product in _storeController.products.all)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] " + product.metadata.localizedTitle
|
|
||||||
+ "|" + product.metadata.localizedPriceString
|
|
||||||
+ "|" + product.metadata.localizedDescription
|
|
||||||
+ "|" + product.metadata.isoCurrencyCode
|
|
||||||
+ "|" + product.definition.id
|
|
||||||
+ "|" + product.definition.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckSubscribeReceipt();
|
|
||||||
RushSDKManager.Instance.OnGetProductsInfo?.Invoke(_storeController.products.all);
|
|
||||||
RushSDKManager.Instance.OnPurchaseInitComplete?.Invoke(true, "");
|
|
||||||
IAPEvent.LogPurchaseInit(true);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 初始化失败
|
|
||||||
public void OnInitializeFailed(InitializationFailureReason error)
|
|
||||||
{
|
|
||||||
OnInitializeFailed(error, "");
|
|
||||||
RushSDKManager.Instance.OnPurchaseInitComplete?.Invoke(false, error.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnInitializeFailed(InitializationFailureReason error, string message)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] IAP OnInitializeFailed error:" + error.ToString() + " msg:" + message);
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
case InitializationFailureReason.AppNotKnown:
|
|
||||||
LoggerUtils.Debug("[iap] Is your App correctly uploaded on the relevant publisher console?");
|
|
||||||
break;
|
|
||||||
case InitializationFailureReason.PurchasingUnavailable:
|
|
||||||
LoggerUtils.Debug("[iap] Billing disabled! Ask the user if billing is disabled in device settings.");
|
|
||||||
break;
|
|
||||||
case InitializationFailureReason.NoProductsAvailable:
|
|
||||||
LoggerUtils.Debug("[iap] No products available for purchase! Developer configuration error; check product metadata!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
IAPEvent.LogPurchaseInit(false, error.ToString());
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 购买失败
|
|
||||||
public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug("[iap] OnPurchaseFailed productId : " + failureDescription.productId
|
|
||||||
+ " , transactionID : " + product.transactionID
|
|
||||||
+ " , localizedPrice : " + product.metadata.localizedPriceString
|
|
||||||
+ " , isoCurrencyCode : " + product.metadata.isoCurrencyCode
|
|
||||||
+ "failureDescription" + failureDescription.message);
|
|
||||||
|
|
||||||
|
|
||||||
// 失败打点
|
|
||||||
IAPEvent.LogPurchaseFail(new PurchaseInfo(
|
|
||||||
productName: product.metadata.localizedTitle,
|
|
||||||
productID: product.definition.id,
|
|
||||||
orderID: "",
|
|
||||||
currency: product.metadata.isoCurrencyCode,
|
|
||||||
price: product.metadata.localizedPriceString,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: failureDescription.message,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: (IAPResultType)failureDescription.reason,
|
|
||||||
productType: product.definition.type.ToString()
|
|
||||||
));
|
|
||||||
|
|
||||||
// 购买失败回调
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete(new PurchaseInfo(
|
|
||||||
productName: product.metadata.localizedTitle,
|
|
||||||
productID: product.definition.id,
|
|
||||||
orderID: "",
|
|
||||||
currency: product.metadata.isoCurrencyCode,
|
|
||||||
price: product.metadata.localizedPriceString,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: failureDescription.message,
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: (IAPResultType)failureDescription.reason,
|
|
||||||
productType: product.definition.type.ToString()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
|
|
||||||
{
|
|
||||||
// m_PurchaseInProgress = false;
|
|
||||||
LoggerUtils.Debug("[iap] OnPurchaseFailed productId -> : " + product.definition.id
|
|
||||||
+ " , transactionID : " + product.transactionID
|
|
||||||
+ " , localizedPrice : " + product.metadata.localizedPriceString
|
|
||||||
+ " , isoCurrencyCode : " + product.metadata.isoCurrencyCode
|
|
||||||
+ " , failureReason : " + failureReason.ToString());
|
|
||||||
|
|
||||||
|
|
||||||
// 失败打点
|
|
||||||
IAPEvent.LogPurchaseFail(new PurchaseInfo(
|
|
||||||
productName: product.metadata.localizedTitle,
|
|
||||||
productID: product.definition.id,
|
|
||||||
orderID: "",
|
|
||||||
currency: product.metadata.isoCurrencyCode,
|
|
||||||
price: product.metadata.localizedPriceString,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
productType: "",
|
|
||||||
failReason: failureReason.ToString(),
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: (IAPResultType)failureReason)
|
|
||||||
);
|
|
||||||
|
|
||||||
// 购买失败回调
|
|
||||||
RushSDKManager.Instance.OnPurchaseComplete(new PurchaseInfo(
|
|
||||||
productName: product.metadata.localizedTitle,
|
|
||||||
productID: product.definition.id,
|
|
||||||
orderID: "",
|
|
||||||
currency: product.metadata.isoCurrencyCode,
|
|
||||||
price: product.metadata.localizedPriceString,
|
|
||||||
gameExtra: _gameExtraParam,
|
|
||||||
failReason: failureReason.ToString(),
|
|
||||||
orderAlreadyExists: false,
|
|
||||||
purchaseResult: false,
|
|
||||||
resultType: (IAPResultType)failureReason,
|
|
||||||
productType: product.definition.type.ToString()
|
|
||||||
|
|
||||||
));
|
|
||||||
// ReadFailOrderId();
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
private StandardPurchasingModule _module;
|
|
||||||
private ConfigurationBuilder _builder;
|
|
||||||
private static IStoreController _storeController;
|
|
||||||
private static IExtensionProvider _storeExtensionProvider;
|
|
||||||
public string _gameExtraParam = "";
|
|
||||||
private static string _productName = "";
|
|
||||||
private bool _inPurchaseProgress = false;
|
|
||||||
public Dictionary<string, Dictionary<string, object>> _productArgs = new Dictionary<string, Dictionary<string, object>>();
|
|
||||||
private bool _serviceInit = false;
|
|
||||||
private Dictionary<string, ProductType> _addProductsDic;
|
|
||||||
private Dictionary<string, ProductType> _initProductDic;
|
|
||||||
private Dictionary<string, int> _repeatCountDic;
|
|
||||||
private IGooglePlayConfiguration _googlePlayConfiguration;
|
|
||||||
private bool _isFetchingAdditionalProducts = false;
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: ffce1a3398ade48a9907b1f3ebb82f8d
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
|
|
||||||
public struct SubscribeInfo
|
|
||||||
{
|
|
||||||
|
|
||||||
public int Illegal_order; // 0:代表合法订单,1:代表非法订单
|
|
||||||
public string Illegal_msg; // 非法订单信息
|
|
||||||
public string Environment; // production & sandbox
|
|
||||||
public string Purchase_time; //订阅时间,单位毫秒
|
|
||||||
public int Is_subscribed; //是否订阅过 0:未订阅过,1:订阅过
|
|
||||||
public int Is_expired; //是否过期 0未过期,1:已过期
|
|
||||||
public int Is_cancelled; // 0:未取消,1:已取消
|
|
||||||
public int Is_free_trial; // 0:不是免费试用,1:是免费试用
|
|
||||||
public int Is_auto_renewing; //是否自动续订 0:非自动,1:自动
|
|
||||||
public string Remaining_time; //订阅到期剩余时间,单位毫秒
|
|
||||||
public string Expiry_time; //过期时间,单位毫秒
|
|
||||||
public string Latest_order_id; //当前订阅的最新订单号
|
|
||||||
public string Product_id; //产品ID
|
|
||||||
|
|
||||||
public SubscribeInfo(int illegal_order, string illegal_msg, string environment, string purchase_time, int is_subscribed, int is_expired, int is_cancelled, int is_free_trial, int is_auto_renewing, string remaining_time, string expiry_time, string latest_order_id,string product_id)
|
|
||||||
{
|
|
||||||
Illegal_order = illegal_order;
|
|
||||||
Illegal_msg = illegal_msg;
|
|
||||||
Environment = environment;
|
|
||||||
Purchase_time = purchase_time;
|
|
||||||
Is_subscribed = is_subscribed;
|
|
||||||
Is_expired = is_expired;
|
|
||||||
Is_cancelled = is_cancelled;
|
|
||||||
Is_free_trial = is_free_trial;
|
|
||||||
Is_auto_renewing = is_auto_renewing;
|
|
||||||
Remaining_time = remaining_time;
|
|
||||||
Expiry_time = expiry_time;
|
|
||||||
Latest_order_id = latest_order_id;
|
|
||||||
Product_id = product_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 33709546096a84c849505413000f3a28
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 1edbb658f8a39411aa0d6508c05142b3
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
|
|
||||||
public class RequestHandler : MonoBehaviour
|
|
||||||
{
|
|
||||||
private static RequestHandler _instance;
|
|
||||||
|
|
||||||
public static RequestHandler Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance != null) return _instance;
|
|
||||||
_instance = FindObjectOfType<RequestHandler>();
|
|
||||||
if (_instance != null) return _instance;
|
|
||||||
var obj = new GameObject();
|
|
||||||
_instance = obj.AddComponent<RequestHandler>();
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = this;
|
|
||||||
}
|
|
||||||
else if (_instance != this)
|
|
||||||
{
|
|
||||||
Destroy(gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
DontDestroyOnLoad(gameObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendPostRequest(string url, string jsonRequestBody, Dictionary<string, string> headers = null, Action<int, string> callback = null)
|
|
||||||
{
|
|
||||||
StartCoroutine(PostRequestCoroutine(url, jsonRequestBody, headers, callback));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerator PostRequestCoroutine(string url, string jsonRequestBody, Dictionary<string, string> headers, Action<int, string> callback)
|
|
||||||
{
|
|
||||||
using var request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
|
|
||||||
request.timeout = 15;
|
|
||||||
request.downloadHandler = new DownloadHandlerBuffer();
|
|
||||||
request.SetRequestHeader("Content-Type", "application/json");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(jsonRequestBody))
|
|
||||||
{
|
|
||||||
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(jsonRequestBody));
|
|
||||||
request.uploadHandler.contentType = "application/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers != null)
|
|
||||||
{
|
|
||||||
foreach (var header in headers)
|
|
||||||
{
|
|
||||||
request.SetRequestHeader(header.Key, header.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
|
||||||
var startTime = Time.realtimeSinceStartup;
|
|
||||||
#endif
|
|
||||||
yield return request.SendWebRequest();
|
|
||||||
|
|
||||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
|
||||||
var endTime = Time.realtimeSinceStartup;
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine($"POST Request URL: {url}");
|
|
||||||
sb.AppendLine($"POST Request Headers: {GetHeadersAsString(headers)}");
|
|
||||||
sb.AppendLine($"POST Request Body: {jsonRequestBody}");
|
|
||||||
sb.AppendLine($"Response Code: {request.responseCode}");
|
|
||||||
sb.AppendLine($"Response Time: {endTime - startTime:F2} seconds");
|
|
||||||
sb.AppendLine($"Response Headers: \n {GetHeadersAsString(request.GetResponseHeaders())}");
|
|
||||||
var downloadHandlerText = request.downloadHandler != null ? request.downloadHandler.text : "";
|
|
||||||
sb.AppendLine($"Response: {downloadHandlerText}");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if (request.result == UnityWebRequest.Result.Success)
|
|
||||||
{
|
|
||||||
callback?.Invoke(0, request.downloadHandler?.text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
callback?.Invoke(-1, request.error ?? $"request fail, result = {request.result}");
|
|
||||||
}
|
|
||||||
|
|
||||||
request.disposeDownloadHandlerOnDispose = true;
|
|
||||||
request.disposeUploadHandlerOnDispose = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetHeadersAsString(Dictionary<string, string> headers)
|
|
||||||
{
|
|
||||||
if (headers == null || headers.Count == 0)
|
|
||||||
{
|
|
||||||
return "\tN/A";
|
|
||||||
}
|
|
||||||
|
|
||||||
return headers.Aggregate("", (current, header) => current + "\t" + header.Key + ": " + header.Value + "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: d0a1895b264d84fb888ce190870a1fc7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -1,272 +0,0 @@
|
||||||
#if UNITY_PURCHASE
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using Google.MiniJSON;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using ThinkingData.Analytics;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace WZ
|
|
||||||
{
|
|
||||||
public class ServerMgr : D_MonoSingleton<ServerMgr>
|
|
||||||
{
|
|
||||||
private const string XXTEA_KEY = "tkbff&(gBUjX#$s0710";
|
|
||||||
private const string secretKey = "tk~!@#$%^&*()_+0708";
|
|
||||||
|
|
||||||
public void CheckOrder(Dictionary<string, object> args, Action<int,string, SubscriptionInfo> callback)
|
|
||||||
{
|
|
||||||
Post(StaticValue.CheckOrderUrl, args,callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void VerifyPurchase(Dictionary<string, object> args, Action<int, string, DataInfo> callback)
|
|
||||||
{
|
|
||||||
float fPrice;
|
|
||||||
if (!float.TryParse(args["price"].ToString(), out fPrice))
|
|
||||||
{
|
|
||||||
fPrice = 0.0f;
|
|
||||||
}
|
|
||||||
var ssProperties = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "is_first", PlayerPrefsUtils.GetPlayerPrefsInt("First_Purchase", 0) == 0 },
|
|
||||||
{ "IAP", args["iap_name"].ToString() },
|
|
||||||
{ "product_id", args["product_id"].ToString() },
|
|
||||||
{ "payment_type", "GooglePlay" },
|
|
||||||
{ "Price", fPrice }
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (TDAnalytics.GetSuperProperties().Count > 0)
|
|
||||||
{
|
|
||||||
ssProperties = ssProperties.Concat(TDAnalytics.GetSuperProperties()).ToDictionary(postParK => postParK.Key, PostParV => PostParV.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TDAnalytics.GetPresetProperties().ToDictionary().Count > 0)
|
|
||||||
{
|
|
||||||
ssProperties = ssProperties.Concat(TDAnalytics.GetPresetProperties().ToDictionary()).ToDictionary(postParK => postParK.Key, PostParV => PostParV.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
args.Add("ss_super_properties", JsonConvert.SerializeObject(ssProperties));
|
|
||||||
Post(StaticValue.VerifyPurchaseUrl, args, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Post<T>(string url, Dictionary<string, object> args, Action<int, string, T> callback,
|
|
||||||
Dictionary<string, string> headers = null) where T : new()
|
|
||||||
{
|
|
||||||
args ??= new Dictionary<string, object>();
|
|
||||||
|
|
||||||
headers ??= new Dictionary<string, string>();
|
|
||||||
|
|
||||||
AddBaseParameters(args);
|
|
||||||
|
|
||||||
EncryptionParameters(args);
|
|
||||||
var requestBody = ConvertDictionaryToJson(args);
|
|
||||||
LoggerUtils.Debug("[server] url=> " + url +" requestBody=>"+requestBody);
|
|
||||||
var encryptBody = EncryptRequestBody(requestBody);
|
|
||||||
if (!string.IsNullOrEmpty(encryptBody))
|
|
||||||
{
|
|
||||||
headers["params"] = encryptBody;
|
|
||||||
headers["encrypt"] = true.ToString().ToLower();
|
|
||||||
requestBody = "";
|
|
||||||
}
|
|
||||||
headers.AddIfNotExists("Is-Dev", "0");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
headers.AddIfNotExists("unity-platform", Application.platform.ToString());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestHandler.Instance.SendPostRequest(url, requestBody, headers,
|
|
||||||
(code, res) =>
|
|
||||||
{
|
|
||||||
LoggerUtils.Debug($"[server] res ====> code : {code} res : {res}");
|
|
||||||
if (code == 0)
|
|
||||||
{
|
|
||||||
Response<T> resp = null;
|
|
||||||
var errorMsg = "";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
res = DecryptResponseBody(res);
|
|
||||||
resp = JsonUtility.FromJson<Response<T>>(res);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
errorMsg = $"[server] Data conversion exception。{e.Message} {res}";
|
|
||||||
LoggerUtils.Debug(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerUtils.Debug($"[server] resp ====> code : {resp.code} res : {resp.data}");
|
|
||||||
if (resp != null)
|
|
||||||
{
|
|
||||||
callback(resp.code, resp.msg, resp.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
callback.Invoke(-1, errorMsg, new T());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
callback.Invoke(code, res, new T());
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerUtils.Debug("[server]" + "[res] " + res);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string EncryptRequestBody(string requestBody)
|
|
||||||
{
|
|
||||||
var encryptRequestBodyBytes = XXTEA.Encrypt(Encoding.UTF8.GetBytes(requestBody), Encoding.UTF8.GetBytes(XXTEA_KEY));
|
|
||||||
var encryptRequestBody = EncryptionUtils.BytesToHexString(encryptRequestBodyBytes, false);
|
|
||||||
LoggerUtils.Debug($"[[server]] [EncryptRequestBody] requestBody = {requestBody} encryptRequestBody = {encryptRequestBody}");
|
|
||||||
return encryptRequestBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string DecryptResponseBody(string responseBody)
|
|
||||||
{
|
|
||||||
var decryptResponseBodyBytes = XXTEA.Decrypt(EncryptionUtils.HexStringToBytes(responseBody), Encoding.UTF8.GetBytes(XXTEA_KEY));
|
|
||||||
var decryptResponseBody = Encoding.UTF8.GetString(decryptResponseBodyBytes);
|
|
||||||
LoggerUtils.Debug($"[[server]] [DecryptResponseBody] decryptResponseBody = {decryptResponseBody}");
|
|
||||||
return decryptResponseBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetMD5Hash(string input)
|
|
||||||
{
|
|
||||||
using (var md5 = MD5.Create())
|
|
||||||
{
|
|
||||||
var inputBytes = Encoding.ASCII.GetBytes(input);
|
|
||||||
var hashBytes = md5.ComputeHash(inputBytes);
|
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
foreach (var t in hashBytes)
|
|
||||||
{
|
|
||||||
builder.Append(t.ToString("x2")); // Convert byte to hexadecimal string
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EncryptionParameters(Dictionary<string, object> args)
|
|
||||||
{
|
|
||||||
var signString =
|
|
||||||
$"{secretKey}platform={args["platform"]}packagename={args["package_name"]}channel={args["channel"]}appversion={args["app_version"]}appversioncode={args["app_version_code"]}language={args["language"]}ip={args["ip"]}ts={args["ts"]}";
|
|
||||||
var sign = GetMD5Hash(signString);
|
|
||||||
args["sign"] = sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddBaseParameters(IDictionary<string, object> args)
|
|
||||||
{
|
|
||||||
|
|
||||||
args.AddIfNotExists("unity_sdk_version", RushSDKManager.GetSDKVersion());
|
|
||||||
|
|
||||||
args.AddIfNotExists("package_name", Application.identifier);
|
|
||||||
args.AddIfNotExists("platform", "android");
|
|
||||||
args.AddIfNotExists("platform_os", "android");
|
|
||||||
args.AddIfNotExists("channel", "googleplay");
|
|
||||||
args.AddIfNotExists("device_type", "Android");
|
|
||||||
args.AddIfNotExists("platform_channel", "gp");
|
|
||||||
args.AddIfNotExists("app_version", Application.version);
|
|
||||||
args.AddIfNotExists("app_version_code", DataUtils.AndroidVersionCode());
|
|
||||||
args.AddIfNotExists("language", "ZH");
|
|
||||||
args.AddIfNotExists("ip", "");
|
|
||||||
args.AddIfNotExists("device_id", AdjustManager.Instance.GetGdid());
|
|
||||||
args.AddIfNotExists("adjust_adid", AdjustManager.Instance.GetAdid());
|
|
||||||
args.AddIfNotExists("app_u8id", "");
|
|
||||||
args.AddIfNotExists("app_name", Application.productName);
|
|
||||||
args.AddIfNotExists("model", "");
|
|
||||||
args.AddIfNotExists("screen_size", "");
|
|
||||||
args.AddIfNotExists("network_type", "");
|
|
||||||
args.AddIfNotExists("ua", "");
|
|
||||||
args.AddIfNotExists("idfa", "");
|
|
||||||
args.AddIfNotExists("idfv", "");
|
|
||||||
args.AddIfNotExists("gaid", AdjustManager.Instance.GetGdid());
|
|
||||||
args.AddIfNotExists("oaid", "");
|
|
||||||
args.AddIfNotExists("android_id", "");
|
|
||||||
args.AddIfNotExists("adid", AdjustManager.Instance.GetAdid());
|
|
||||||
args.AddIfNotExists("fire_adid", "");
|
|
||||||
args.AddIfNotExists("ad_network", AdjustManager.Instance.GetAdjustNetwork());
|
|
||||||
args.AddIfNotExists("campaign", AdjustManager.Instance.GetAdjustCampaign());
|
|
||||||
args.AddIfNotExists("adgroup", AdjustManager.Instance.GetAdjustAdgroup());
|
|
||||||
args.AddIfNotExists("creative", AdjustManager.Instance.GetAdjustCreative());
|
|
||||||
args.AddIfNotExists("clickLabel", AdjustManager.Instance.GetAdjustClickLabel());
|
|
||||||
args.AddIfNotExists("referrer", "");
|
|
||||||
args.AddIfNotExists("memory", "");
|
|
||||||
args.AddIfNotExists("memory_usage", "");
|
|
||||||
args.AddIfNotExists("country", "");
|
|
||||||
args.AddIfNotExists("user_id", "");
|
|
||||||
args.AddIfNotExists("user_type", "");
|
|
||||||
args.AddIfNotExists("ss_distinct_id", TDAnalytics.GetDistinctId() ?? "");
|
|
||||||
args.AddIfNotExists("ss_account_id", "");
|
|
||||||
args.AddIfNotExists("ts", "" + TimeUtils.CurrentTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static string ConvertDictionaryToJson(Dictionary<string, object> dictionary)
|
|
||||||
{
|
|
||||||
return Json.Serialize(dictionary);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class Response<T>
|
|
||||||
{
|
|
||||||
public int code = -1;
|
|
||||||
public string msg;
|
|
||||||
public T data;
|
|
||||||
public int ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class SensitiveDataInfo
|
|
||||||
{
|
|
||||||
public bool has_sensitive;
|
|
||||||
public string content;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class TranslateDataInfo
|
|
||||||
{
|
|
||||||
public string content;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class DataInfo
|
|
||||||
{
|
|
||||||
public string environment;
|
|
||||||
public int illegal_order = -1;
|
|
||||||
public string illegal_msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class SubscriptionInfo
|
|
||||||
{
|
|
||||||
public int illegal_order;
|
|
||||||
public string illegal_msg;
|
|
||||||
public string environment;
|
|
||||||
public string purchase_time;
|
|
||||||
public int is_subscribed;
|
|
||||||
public int is_expired;
|
|
||||||
public int is_cancelled;
|
|
||||||
public int is_free_trial;
|
|
||||||
public int is_auto_renewing;
|
|
||||||
public string remaining_time;
|
|
||||||
public string expiry_time;
|
|
||||||
public string latest_order_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: af510513690fd4631b3b57b1d427f4c7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
|
|
@ -67,14 +67,6 @@ public class RushSDKManager : D_MonoSingleton<RushSDKManager>
|
||||||
OnGetProductsInfo += _action;
|
OnGetProductsInfo += _action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 支付回调
|
|
||||||
/// </summary>
|
|
||||||
public Action<PurchaseInfo> OnPurchaseComplete;
|
|
||||||
public void RegisterPurchaseCompletionHandler(Action<PurchaseInfo> _action)
|
|
||||||
{
|
|
||||||
OnPurchaseComplete = _action;
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,19 +27,16 @@ public class Test : MonoBehaviour
|
||||||
|
|
||||||
public void OnShowAd()
|
public void OnShowAd()
|
||||||
{
|
{
|
||||||
// RushSDKManager.Instance.ShowBanner();
|
|
||||||
// RushSDKManager.Instance.InitializeSdk(null, true);
|
// RushSDKManager.Instance.InitializeSdk(null, true);
|
||||||
// KwaiAdsManager.Instance.ShowRewardAd();
|
// KwaiAdsManager.Instance.ShowRewardAd();
|
||||||
// AdsSDKManager.Instance.ShowRewardAd("getcoin",(state,revenue)=>
|
AdsSDKManager.Instance.ShowRewardAd("getcoin",(state,revenue)=>
|
||||||
// {
|
{
|
||||||
// LoggerUtils.Debug("[kwai] OnRewardedVideoAdShowed revenue:"+revenue+"+ state:"+state);
|
LoggerUtils.Debug("[kwai] OnRewardedVideoAdShowed revenue:"+revenue+"+ state:"+state);
|
||||||
// });
|
});
|
||||||
RushSDKManager.Instance.ShowBanner(BannerType.Standard,BannerAlignType.CenterTop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnShowInterstitial()
|
public void OnShowInterstitial()
|
||||||
{
|
{
|
||||||
RushSDKManager.Instance.ShowBanner(BannerType.Collapsible,BannerAlignType.CenterBottom);
|
|
||||||
// KwaiAdsManager.Instance.OnInterstitialCallback();
|
// KwaiAdsManager.Instance.OnInterstitialCallback();
|
||||||
// var small = gameObject.transform.Find("NativeAd-small").GetComponent<RectTransform>();
|
// var small = gameObject.transform.Find("NativeAd-small").GetComponent<RectTransform>();
|
||||||
// var medium = gameObject.transform.Find("NativeAd-medium").GetComponent<RectTransform>();
|
// var medium = gameObject.transform.Find("NativeAd-medium").GetComponent<RectTransform>();
|
||||||
|
|
@ -66,11 +63,11 @@ public class Test : MonoBehaviour
|
||||||
// {
|
// {
|
||||||
// Debug.LogWarning("luojian admob native ad start show fail,not ready.");
|
// Debug.LogWarning("luojian admob native ad start show fail,not ready.");
|
||||||
// }
|
// }
|
||||||
// AdsSDKManager.Instance.ShowInterstitialAd("endgame",IvType.IV1, (revenue) =>
|
AdsSDKManager.Instance.ShowInterstitialAd("endgame",IvType.IV1, (revenue) =>
|
||||||
// {
|
{
|
||||||
// LoggerUtils.Debug("oninter show call revenue:"+revenue);
|
LoggerUtils.Debug("oninter show call revenue:"+revenue);
|
||||||
|
|
||||||
// });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnInterShow()
|
public void OnInterShow()
|
||||||
|
|
@ -84,14 +81,12 @@ public class Test : MonoBehaviour
|
||||||
|
|
||||||
public void ToponDebug()
|
public void ToponDebug()
|
||||||
{
|
{
|
||||||
// ATSDKAPI.showDebuggerUI();
|
ATSDKAPI.showDebuggerUI();
|
||||||
RushSDKManager.Instance.HideBanner(BannerType.Standard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MaxDebug()
|
public void MaxDebug()
|
||||||
{
|
{
|
||||||
// MaxSdk.ShowMediationDebugger();
|
MaxSdk.ShowMediationDebugger();
|
||||||
RushSDKManager.Instance.HideBanner(BannerType.Collapsible);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Native1Show()
|
public void Native1Show()
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,6 @@ namespace WZ
|
||||||
public T[] items;
|
public T[] items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int AndroidVersionCode()
|
|
||||||
{
|
|
||||||
AndroidJavaClass contextCls = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
|
||||||
AndroidJavaObject context = contextCls.GetStatic<AndroidJavaObject>("currentActivity");
|
|
||||||
AndroidJavaObject packageMngr = context.Call<AndroidJavaObject>("getPackageManager");
|
|
||||||
string packageName = context.Call<string>("getPackageName");
|
|
||||||
AndroidJavaObject packageInfo =
|
|
||||||
packageMngr.Call<AndroidJavaObject>("getPackageInfo", packageName, 0);
|
|
||||||
return packageInfo.Get<int>("versionCode");
|
|
||||||
}
|
|
||||||
public static T[] FromJsonArray<T>(string json)
|
public static T[] FromJsonArray<T>(string json)
|
||||||
{
|
{
|
||||||
string wrappedJson = $"{{\"items\":{json}}}";
|
string wrappedJson = $"{{\"items\":{json}}}";
|
||||||
|
|
@ -43,12 +33,6 @@ namespace WZ
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddIfNotExists<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
|
|
||||||
{
|
|
||||||
if (!dictionary.ContainsKey(key))
|
|
||||||
dictionary.Add(key, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,86 +9,6 @@ namespace WZ
|
||||||
{
|
{
|
||||||
public static class EncryptionUtils
|
public static class EncryptionUtils
|
||||||
{
|
{
|
||||||
public static string BytesToHexString(byte[] bytes, bool isUpperCase)
|
|
||||||
{
|
|
||||||
if (bytes == null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
char[] hexDigits = isUpperCase ? HEX_DIGITS_UPPER : HEX_DIGITS_LOWER;
|
|
||||||
int len = bytes.Length;
|
|
||||||
if (len == 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
char[] ret = new char[len << 1];
|
|
||||||
for (int i = 0, j = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
|
|
||||||
ret[j++] = hexDigits[bytes[i] & 0x0f];
|
|
||||||
}
|
|
||||||
|
|
||||||
return new string(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] HexStringToBytes(string hexString)
|
|
||||||
{
|
|
||||||
if (IsSpace(hexString))
|
|
||||||
return new byte[0];
|
|
||||||
|
|
||||||
int len = hexString.Length;
|
|
||||||
if (len % 2 != 0)
|
|
||||||
{
|
|
||||||
hexString = "0" + hexString;
|
|
||||||
len = len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char[] hexBytes = hexString.ToUpper().ToCharArray();
|
|
||||||
byte[] ret = new byte[len >> 1];
|
|
||||||
for (int i = 0; i < len; i += 2)
|
|
||||||
{
|
|
||||||
ret[i >> 1] = (byte)(HexToDec(hexBytes[i]) << 4 | HexToDec(hexBytes[i + 1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsSpace(string s)
|
|
||||||
{
|
|
||||||
if (s == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
for (int i = 0, len = s.Length; i < len; ++i)
|
|
||||||
{
|
|
||||||
if (!char.IsWhiteSpace(s[i]))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int HexToDec(char hexChar)
|
|
||||||
{
|
|
||||||
if (hexChar >= '0' && hexChar <= '9')
|
|
||||||
{
|
|
||||||
return hexChar - '0';
|
|
||||||
}
|
|
||||||
else if (hexChar >= 'A' && hexChar <= 'F')
|
|
||||||
{
|
|
||||||
return hexChar - 'A' + 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly char[] HEX_DIGITS_UPPER =
|
|
||||||
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
|
||||||
|
|
||||||
private static readonly char[] HEX_DIGITS_LOWER =
|
|
||||||
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
|
||||||
|
|
||||||
private static string GetKey(string packageName)
|
private static string GetKey(string packageName)
|
||||||
{
|
{
|
||||||
var keyBytes = Encoding.UTF8.GetBytes(packageName);
|
var keyBytes = Encoding.UTF8.GetBytes(packageName);
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,7 @@ namespace WZ
|
||||||
public class TimeUtils
|
public class TimeUtils
|
||||||
{
|
{
|
||||||
#region 本地时间
|
#region 本地时间
|
||||||
public static long CurrentTimestamp()
|
|
||||||
{
|
|
||||||
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
||||||
}
|
|
||||||
// 获取当前本地时间的毫秒级时间戳
|
// 获取当前本地时间的毫秒级时间戳
|
||||||
public static long GetLocalTimestamp()
|
public static long GetLocalTimestamp()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue