#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 { private static string _purchaseOrderMap = "PurchaseOrderMap"; private List NotRetryCode = new List { 0, 430, 900, 901, 902, 903, 904, 905 }; private Dictionary 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 list = ES3.Load(_purchaseOrderMap) as List; 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 list = ES3.Load(_purchaseOrderMap) as List; 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 tem = new List { _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 list = ES3.Load(_purchaseOrderMap) as List; 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 tem = new List { _productInfo }; ES3.Save(_purchaseOrderMap, tem); ReadFailOrderId(); LoggerUtils.Debug("[iap] IAP SaveVerifyFailOrderId 第一次存储表 添加失败订单 订单个数:" + tem.Count); } } #endregion #region 再次验证订单 public void ReadFailOrderId() { if (ES3.KeyExists(_purchaseOrderMap)) { List list = ES3.Load(_purchaseOrderMap) as List; 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 list = ES3.Load(_purchaseOrderMap) as List; 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 info; public IAPDataStateType state; } } } #endif