SDK_UnityMoney/Assets/Script/SDKManager/Purchase/IAPOrderManager.cs

396 lines
19 KiB
C#
Raw Normal View History

2025-09-18 10:30:57 +00:00
#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