update: 支付插件初始化修改, orders 上报缓存, IAP 数据中台接口改造

deeplink
胡宇飞 2024-03-14 20:21:26 +08:00
parent 277bf0bfba
commit 0c9b2a77fe
16 changed files with 648 additions and 61 deletions

View File

@ -136,6 +136,11 @@ namespace Guru
{
CacheUserProperty(Analytics.PropertyIDFV, idfv);
}
public static void SetIDFA(string idfa)
{
CacheUserProperty(Analytics.PropertyIDFA, idfa);
}
/// <summary>

View File

@ -10,7 +10,7 @@ namespace Guru
public static class AdjustService
{
public const string Version = "1.6.0";
public const string Version = "1.6.1";
public static readonly string LOG_TAG = "Adjust";
public static readonly float DelayTime = 1f; // 延迟启动时间
@ -28,6 +28,8 @@ namespace Guru
}
}
public static string IDFA => Adjust.getIdfa();
private static string _adjustId = "";
public static string AdjustId
{
@ -111,6 +113,9 @@ namespace Guru
}
}
#endregion
#region 关键属性上报

View File

@ -106,6 +106,7 @@ namespace Guru
public static readonly string PropertyHp = "hp"; // 生命值/体力
public static readonly string PropertyAndroidID = "android_id"; // Android 平台 AndroidID
public static readonly string PropertyIDFV = "idfv"; // iOS 平台 IDFV
public static readonly string PropertyIDFA = "idfa"; // iOS 平台 IDFA
public static readonly string PropertyPicture = "picture"; // 玩家在主线的mapid
public static readonly string PropertyNoAds = "no_ads"; // 玩家是否去广告
public static readonly string PropertyATTStatus = "att_status"; // ATT 状态

View File

@ -14,6 +14,7 @@ namespace Guru
{
private static bool _hasGotFirebaseId; //已取得FirebaseId
private static bool _hasGotAdId; // 已取得AdId
private static bool _hasGotIDFA; // 已取得IDFA
private static bool _hasGotAdjustId; // 已取得AdjustId
private static bool _hasGotDeviceId; // 已取得DeviceId
private static bool _hasGotUid; // 已取得UID
@ -21,6 +22,7 @@ namespace Guru
private static double _reportSuccessInterval; // 上报频率
private const string VALUE_NOT_FOR_IOS = "not_support_for_ios";
private const string VALUE_ONLY_FOR_IOS = "idfa_only_for_ios";
public static bool IsDebug { get; set; } = false;
@ -148,6 +150,10 @@ namespace Guru
}
/// <summary>
/// 设置FirebaseId
/// </summary>
@ -200,6 +206,24 @@ namespace Guru
{
GuruAnalytics.SetIDFV(DeviceIDHelper.IDFV);
}
private static void SetIDFA()
{
if(_hasGotIDFA) return;
var idfa = AdjustService.IDFA;
if (!string.IsNullOrEmpty(idfa))
{
// Debug.Log($"---[ANA] ADID: {adId}");
IPMConfig.ADJUST_IDFA = idfa;
}
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_IDFA))
{
GuruAnalytics.SetIDFA(IPMConfig.ADJUST_IDFA);
_hasGotIDFA = true;
}
}
#endif
@ -231,6 +255,7 @@ namespace Guru
#if UNITY_IOS
SetATTStatus();
SetIDFV();
SetIDFA();
#endif
ReportEventSuccessRate();
}

View File

@ -211,7 +211,13 @@ namespace Guru
get => PlayerPrefs.GetString(nameof(ADJUST_ADID), "");
set => PlayerPrefs.SetString(nameof(ADJUST_ADID), value);
}
public static string ADJUST_IDFA
{
get => PlayerPrefs.GetString(nameof(ADJUST_IDFA), "");
set => PlayerPrefs.SetString(nameof(ADJUST_IDFA), value);
}
}
}

View File

@ -1,30 +1,37 @@
using System;
using System.Collections.Generic;
namespace Guru
{
using System;
using System.Collections.Generic;
[Serializable]
public class AppleOrderData
{
public int orderType;
public string productId;
public string bundleId;
public string receipt;
public string country;
public int level;
public Dictionary<string, object> userInfo;
public EventConfig eventConfig;
public AppleOrderData(string receipt, int level)
public AppleOrderData(int orderType, string productId, string receipt, int level)
{
this.orderType = orderType;
this.productId = productId;
this.receipt = receipt;
this.level = level;
bundleId = GuruSettings.Instance.GameIdentifier;
country = IPMConfig.IPM_COUNTRY_CODE;
userInfo = new Dictionary<string, object>
{
["level"] = level
};
userInfo = new Dictionary<string, object> { ["level"] = level };
eventConfig = EventConfig.Build();
}
public override string ToString()
{
return $"{nameof(bundleId)}: {bundleId}, {nameof(receipt)}: {receipt}, {nameof(country)}: {country}";
return $"{nameof(orderType)}: {orderType}, {nameof(productId)}: {productId}, {nameof(bundleId)}: {bundleId}, {nameof(receipt)}: {receipt}, {nameof(country)}: {country}";
}
}
}

View File

@ -0,0 +1,28 @@
namespace Guru
{
using System;
[Serializable]
public class EventConfig
{
public string firebaseAppInstanceId; // firebase实例id用于标识一个用户
public string idfa; // adjust广告idios
public string adid; // adjust设备idios
public string gpsAdid; // adjust广告id
public static EventConfig Build()
{
var config = new EventConfig()
{
firebaseAppInstanceId = IPMConfig.FIREBASE_ID,
idfa = IPMConfig.ADJUST_IDFA,
adid = IPMConfig.ADJUST_ID,
gpsAdid = IPMConfig.ADJUST_ADID,
};
return config;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0b44b9252ff741f58c6489223c0d5dca
timeCreated: 1710411579

View File

@ -6,27 +6,56 @@ namespace Guru
[Serializable]
public class GoogleOrderData
{
public int orderType;
public string packageName;
public string productId;
public string token;
public Dictionary<string, object> userInfo;
public int orderType; // 订单类型可选值0:IAP订单 1: 订阅订单
public string packageName; //应用包名
public string productId = ""; // 商品ID 当orderType=0时传递该参数
public string subscriptionId = ""; // 订阅ID // 当orderType=1时传递该参数
public string token; // 应用商店里面的购买token
public int level;
public Dictionary<string, object> userInfo; // 当前用户信息。目前包含: level: 用户属性中的"b_level"的值
public string basePlanId; // 订阅商品的planId
public string offerId; // 订阅商品的offerId
public EventConfig eventConfig; // 事件打点所需信息
public GoogleOrderData(int orderType, string productId, string token, int level)
public GoogleOrderData(int orderType, string productId, string subscriptionId, string token, int level,
string offerId = "", string basePlanId = "")
{
this.orderType = orderType;
this.packageName = GuruSettings.Instance.GameIdentifier;
this.productId = productId;
this.subscriptionId = subscriptionId;
this.token = token;
userInfo = new Dictionary<string, object>
{
["level"] = level
};
this.offerId = offerId;
this.basePlanId = basePlanId;
this.level = level;
userInfo = new Dictionary<string, object> { ["level"] = level };
eventConfig = EventConfig.Build();
}
public GoogleOrderData(ProductInfo productInfo, string token, int level,
string offerId = "", string basePlanId = "")
{
this.orderType = productInfo.Type == "subscription" ? 1 : 0;
if (orderType == 1)
{
subscriptionId = productInfo.Id;
}
else
{
productId = productInfo.Id;
}
this.packageName = GuruSettings.Instance.GameIdentifier;
this.token = token;
this.offerId = offerId;
this.basePlanId = basePlanId;
userInfo = new Dictionary<string, object> { ["level"] = level };
eventConfig = EventConfig.Build();
}
public override string ToString()
{
return $"{nameof(orderType)}: {orderType}, {nameof(packageName)}: {packageName}, {nameof(productId)}: {productId}, {nameof(token)}: {token}";
return $"{nameof(orderType)}: {orderType}, {nameof(packageName)}: {packageName}, {nameof(productId)}: {productId}, {nameof(subscriptionId)}: {subscriptionId}, {nameof(token)}: {token}";
}
}
}

View File

@ -0,0 +1,74 @@
using UnityEngine;
namespace Guru
{
using System;
using System.Collections.Generic;
[Serializable]
public class IAPOrderData
{
public string platform; // 平台类型 android 或 ios
public int orderType = 0; // 订单类型可选值0:IAP订单 1: 订阅订单
public string productId = ""; // 商品ID 当orderType=0时传递该参数
public string subscriptionId = ""; // 订阅ID // 当orderType=1时传递该参数
public string receipt = ""; // 应用商店里面的购买token
public int level = 0; // 用户属性中的"b_level"的值
public string packageName = ""; // 应用包名
public string offerId = ""; // 订阅商品的offerId (Android)
public string basePlanId = ""; // 订阅商品的planId (Android)
public Dictionary<string, object> userInfo;
public EventConfig eventConfig;
/// <summary>
/// 构建订单数据
/// </summary>
/// <param name="platform"></param>
/// <param name="orderType"></param>
/// <param name="receipt"></param>
/// <param name="level"></param>
/// <param name="productId"></param>
/// <param name="subscriptionId"></param>
/// <param name="offerId"></param>
/// <param name="basePlanId"></param>
/// <returns></returns>
public static IAPOrderData Build(string platform, int orderType = 0, string receipt= "", int level = 0,
string productId = "", string subscriptionId = "",
string offerId = "", string basePlanId = "")
{
IAPOrderData orderData = new IAPOrderData
{
platform = platform,
orderType = orderType,
productId = productId,
subscriptionId = subscriptionId,
receipt = receipt,
level = level,
packageName = Application.identifier,
offerId = offerId,
basePlanId = basePlanId,
userInfo = new Dictionary<string, object>()
{
{"level", level}
},
eventConfig = new EventConfig()
{
firebaseAppInstanceId = IPMConfig.FIREBASE_ID,
idfa = IPMConfig.ADJUST_IDFA,
adid = IPMConfig.ADJUST_ID,
gpsAdid = IPMConfig.ADJUST_ADID,
}
};
return orderData;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9e4562ba60204b85bca8777b771c73e5
timeCreated: 1710410036

View File

@ -11,23 +11,34 @@ namespace Guru
public string productId;
public string receipt;
public int level;
public AppleOrderData orderData;
public AppleOrderRequest(){}
public AppleOrderRequest(int orderType, string productId, string receipt, int level)
public static AppleOrderRequest Build(int orderType, string productId, string receipt, int level)
{
this.orderType = orderType;
this.productId = productId;
this.receipt = receipt;
this.level = level;
var request = new AppleOrderRequest()
{
orderType = orderType,
productId = productId,
receipt = receipt,
level = level,
};
return request;
}
public static AppleOrderRequest Build(AppleOrderData orderData)
{
return Build(orderData.orderType, orderData.productId, orderData.receipt, orderData.level);
}
protected override string RequestURL => IPMConfig.IPM_URL + "order/api/v1/orders/ios";
protected override UnityWebRequest CreateRequest()
{
AppleOrderData appleOrderData = new AppleOrderData(receipt, level);
this.Log($"send orderData:{appleOrderData}");
this.Log($"send orderData:{orderData}");
var request = new UnityWebRequest(RequestURL, "POST");
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonMapper.ToJson(appleOrderData)));
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonMapper.ToJson(orderData)));
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader(IPMConfig.Header_Param_APPID, IPMConfig.IPM_X_APP_ID);
request.SetRequestHeader(IPMConfig.Header_Param_UID, IPMConfig.IPM_UID);
@ -41,11 +52,17 @@ namespace Guru
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
if (responseData != null && responseData.data != null)
{
// Analytics.Tch001IAPRev(responseData.data.usdPrice);
double usdPrice = responseData.data.usdPrice;
Analytics.Tch001IAPRev(usdPrice);
Analytics.Tch02IAPRev(usdPrice);
AdjustService.TrackIAPPurchase(usdPrice, productId);
if (orderType == 0)
{
AdjustService.TrackIAPPurchase(usdPrice, productId);
}
else if (orderType == 1)
{
AdjustService.TrackSubPurchase(usdPrice, productId);
}
Analytics.IAPPurchase(usdPrice, productId);
}
}

View File

@ -7,17 +7,20 @@ namespace Guru
{
public class GoogleOrderRequest : RequestBase
{
public int orderType;
public int orderType; // 订单类型可选值0:IAP订单 1: 订阅订单
public string productId;
public string subscriptionId;
public string token;
public string packageName;
public int level;
public string basePlanId;
public string offerId;
public GoogleOrderData orderData;
public GoogleOrderRequest(){}
public GoogleOrderRequest(int orderType, string productId, string subscriptionId,
string token, int level)
string token, int level, string offerId = "", string basePlanId = "")
{
this.orderType = orderType;
this.packageName = Application.identifier;
@ -25,12 +28,14 @@ namespace Guru
this.subscriptionId = subscriptionId;
this.token = token;
this.level = level;
}
orderData = new GoogleOrderData(orderType, productId, subscriptionId, token, level, offerId, basePlanId);
}
protected override string RequestURL => IPMConfig.IPM_URL + "order/api/v1/orders/android";
protected override UnityWebRequest CreateRequest()
{
GoogleOrderData googleOrderData = new GoogleOrderData(orderType, productId, token, level);
GoogleOrderData googleOrderData = orderData;
this.Log($"send orderData:{googleOrderData}");
var request = new UnityWebRequest(RequestURL, "POST");
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonMapper.ToJson(googleOrderData)));
@ -51,27 +56,59 @@ namespace Guru
double usdPrice = responseData.data.usdPrice;
Analytics.Tch001IAPRev(usdPrice);
Analytics.Tch02IAPRev(usdPrice);
AdjustService.TrackIAPPurchase(usdPrice, productId);
Analytics.IAPPurchase(usdPrice, productId);
string pid = "";
if (!string.IsNullOrEmpty(productId))
{
pid = productId;
AdjustService.TrackIAPPurchase(usdPrice, productId); // 上报 IAP 支付事件
}
if (!string.IsNullOrEmpty(subscriptionId))
{
pid = subscriptionId;
AdjustService.TrackSubPurchase(usdPrice, productId); // 上报 订阅 支付事件
}
Analytics.IAPPurchase(usdPrice, pid);
return;
}
if (!string.IsNullOrEmpty(response))
{
if (response.Contains("500") || response.Contains("Internal Server Error"))
{
Debug.LogError(
$"[IAP] GoogleOrderRequest failed: contact with guru backend server team. Make sure they'v connect order report to this project!");
}
else
{
Debug.LogError($"[IAP] GoogleOrderRequest failed: {response}");
}
}
else
{
Debug.LogError($"[IAP] GoogleOrderRequest failed: response is null or empty");
}
}
public static GoogleOrderRequest Build(int orderType, string productId, string subscriptionId,
string token, int level, string offerId = "", string basePlanId = "")
{
var request = new GoogleOrderRequest()
{
orderData = new GoogleOrderData(orderType, productId, subscriptionId, token, level, offerId, basePlanId),
orderType = orderType,
packageName = Application.identifier,
productId = productId,
subscriptionId = subscriptionId,
token = token,
level = level,
};
return request;
}
public static GoogleOrderRequest Build(GoogleOrderData data)
{
var request = new GoogleOrderRequest()
{
orderData = data,
orderType = data.orderType,
packageName = data.packageName,
productId = data.productId,
subscriptionId = data.subscriptionId,
token = data.token,
level = data.level,
};
return request;
}
}
}

View File

@ -0,0 +1,159 @@
using System.Collections.Generic;
using UnityEngine;
namespace Guru
{
using System;
using Newtonsoft.Json;
public class IAPModel
{
public static readonly float SaveInterval = 3;
public static readonly string PlatformAndroid = "android";
public static readonly string PlatformIOS = "ios";
public int buyCount = 0;
public List<string> androidTokens;
public List<string> iosReceipts;
public List<GoogleOrderData> googleOrders;
public List<AppleOrderData> appleOrders;
/// <summary>
/// 是否还有未上报的 Google Order
/// </summary>
public bool HasUnreportedGoogleOrder => (googleOrders?.Count ?? 0) > 0;
/// <summary>
/// 是否还有未上报的 Apple Order
/// </summary>
public bool HasUnreportedAppleOrder => (appleOrders?.Count ?? 0) > 0;
public IAPModel()
{
androidTokens = new List<string>(20);
iosReceipts = new List<string>(20);
googleOrders = new List<GoogleOrderData>(20);
appleOrders = new List<AppleOrderData>(20);
}
public static IAPModel Load()
{
IAPModel model = null;
var json = LoadModelData();
if (!string.IsNullOrEmpty(json))
{
model = JsonConvert.DeserializeObject<IAPModel>(json);
}
if(null != model) return model;
return new IAPModel();
}
public void Save()
{
SaveModelData(this);
}
private static string LoadModelData()
{
return PlayerPrefs.GetString(nameof(IAPModel), "");
}
private static void SaveModelData(IAPModel model)
{
var json = JsonConvert.SerializeObject(model);
PlayerPrefs.SetString(nameof(IAPModel), json);
}
#region Receipt
public void AddToken(string token)
{
if (androidTokens == null) androidTokens = new List<string>(20);
if(string.IsNullOrEmpty(token)) return;
androidTokens.Add(token);
Save();
}
/// <summary>
/// 添加收据
/// </summary>
/// <param name="receipt"></param>
/// <param name="platform"></param>
public void AddReceipt(string receipt)
{
if (iosReceipts == null) iosReceipts = new List<string>(20);
if(string.IsNullOrEmpty(receipt)) return;
iosReceipts.Add(receipt);
Save();
}
public bool IsTokenExists(string token)
{
if (androidTokens == null) return false;
return androidTokens.Contains(token);
}
public bool IsReceiptExist(string receipt)
{
if (iosReceipts == null) return false;
return iosReceipts.Contains(receipt);
}
#endregion
#region Orders
public void AddGoogleOrder(GoogleOrderData order)
{
googleOrders.Add(order);
Save();
}
public void RemoveGoogleOrder(GoogleOrderData order)
{
googleOrders.Remove(order);
Save();
}
public void ClearGoogleOrders()
{
googleOrders.Clear();
Save();
}
public void AddAppleOrder(AppleOrderData order)
{
appleOrders.Add(order);
Save();
}
public void RemoveAppleOrder(AppleOrderData order)
{
appleOrders.Remove(order);
Save();
}
public void ClearAppleOrders()
{
appleOrders.Clear();
Save();
}
#endregion
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 52e82348c38f470c8d9f247451ca5ce5
timeCreated: 1710408457

View File

@ -12,6 +12,9 @@ namespace Guru
public abstract class IAPServiceBase<T>: IStoreListener where T: IAPServiceBase<T> , new()
{
public static readonly int OrderRequestTimeout = 10;
public static readonly int OrderRequestRetryTimes = 3;
#region 属性定义
private const string Tag = "[IAP]";
@ -33,7 +36,8 @@ namespace Guru
public bool IsInitialized => _storeController != null && _storeExtensionProvider != null;
private Product _curPurchasingProduct = null;
private IAPModel _model;
/// <summary>
/// 是否是首次购买
/// </summary>
@ -129,6 +133,7 @@ namespace Guru
{
_googlePublicKey = googlePublicKey;
_appleRootCert = appleRootCert;
InitModel();
Initialize(showLog);
}
@ -681,7 +686,7 @@ namespace Guru
#endregion
#region 支付上报逻辑
/// <summary>
/// 支付结果上报
/// </summary>
@ -716,15 +721,13 @@ namespace Guru
string subscriptionID = orderType == 1 ? args.purchasedProduct.definition.id : "";
LogI($"{Tag} --- Report Android IAP Order -> orderType:{orderType} productID:{productID} blevel:{blevel}");
Debug.Log($"############ --- result.Count: {result.Length}");
foreach (var productReceipt in result)
{
if (productReceipt is GooglePlayReceipt google)
{
Debug.Log($"{Tag} --- Report Android IAP Order -> orderType:{orderType} productID:{productID} blevel:{blevel}");
new GoogleOrderRequest(orderType, productID, subscriptionID, google.purchaseToken, blevel).SetTimeOut(5).Send();
// new GoogleOrderRequest(orderType, productID, subscriptionID, google.purchaseToken, blevel).SetTimeOut(5).Send();
ReportGoogleOrder(orderType, productID, subscriptionID, google.purchaseToken, blevel);
}
}
#elif UNITY_IOS
@ -737,7 +740,8 @@ namespace Guru
return;
}
AddReceipt(receipt);
new AppleOrderRequest(orderType, args.purchasedProduct.definition.id, receipt,blevel).Send();
// new AppleOrderRequest(orderType, args.purchasedProduct.definition.id, receipt,blevel).Send();
ReportAppleOrder(orderType, args.purchasedProduct.definition.id, receipt,blevel);
Debug.Log($"{Tag} --- Report iOS IAP Order -> orderType:{orderType} productID:{args.purchasedProduct.definition.id} blevel:{blevel}");
#endif
}
@ -821,6 +825,187 @@ namespace Guru
#endregion
#region 数据初始化
private void InitModel()
{
_model = IAPModel.Load(); // 初始化 Model
// 启动时查询
if(_orderRequests == null)
_orderRequests = new Queue<RequestBase>(20);
#if UNITY_ANDROID
if (_model.HasUnreportedGoogleOrder)
{
foreach (var o in _model.googleOrders)
{
ReportGoogleOrder(o);
}
_model.ClearGoogleOrders();
}
#elif UNITY_IOS
if (_model.HasUnreportedAppleOrder)
{
foreach (var o in _model.appleOrders)
{
ReportAppleOrder(o);
}
_model.ClearAppleOrders();
}
#endif
}
#endregion
#region 订单上报队列
private bool isOrderSending = false;
private Queue<RequestBase> _orderRequests = new Queue<RequestBase>(20);
/// <summary>
/// 上报 Google Order Request
/// </summary>
/// <param name="orderType"></param>
/// <param name="productId"></param>
/// <param name="subscriptionId"></param>
/// <param name="token"></param>
/// <param name="level"></param>
/// <param name="offerId"></param>
/// <param name="basePlanId"></param>
private void ReportGoogleOrder(int orderType, string productId, string subscriptionId, string token, int level,
string offerId = "", string basePlanId = "")
{
var request = GoogleOrderRequest.Build(orderType, productId, subscriptionId, token, level, offerId, basePlanId);
ReportNextOrder(request);
}
private void ReportGoogleOrder(GoogleOrderData data)
{
var request = GoogleOrderRequest.Build(data);
ReportNextOrder(request);
}
private void ReportAppleOrder(int orderType, string productId, string receipt, int level)
{
var request = AppleOrderRequest.Build(orderType, productId, receipt, level);
ReportNextOrder(request);
}
private void ReportAppleOrder(AppleOrderData data)
{
var request = AppleOrderRequest.Build(data);
ReportNextOrder(request);
}
private void ReportNextOrder(RequestBase request)
{
_orderRequests.Enqueue(request);
if(isOrderSending) return;
isOrderSending = true;
OnSendNextOrder();
}
/// <summary>
/// 上报下一个 Google 订单
/// </summary>
private void OnSendNextOrder()
{
if (_orderRequests != null && _orderRequests.Count > 0)
{
isOrderSending = true;
var request = _orderRequests.Dequeue();
GoogleOrderRequest go = request as GoogleOrderRequest;
AppleOrderRequest ao = request as AppleOrderRequest;
if (go != null && _model.IsTokenExists(go.token))
{
OnSendNextOrder();
return;
}
if( ao != null && _model.IsReceiptExist(ao.receipt))
{
OnSendNextOrder();
return;
}
request.SetTimeOut(OrderRequestTimeout)
.SetRetryTimes(OrderRequestRetryTimes)
.SetSuccessCallBack(() =>
{
if (go != null)
{
_model.AddToken(go.token);
}
else if (ao != null)
{
_model.AddReceipt(ao.receipt);
}
OnSendNextOrder();
})
.SetFailCallBack(() =>
{
if (go != null)
{
_model.AddGoogleOrder(go.orderData);
ReportGoogleOrderLost(go.orderData);
}
else if (ao != null)
{
_model.AddAppleOrder(ao.orderData);
ReportAppleOrderLost(ao.orderData);
}
OnSendNextOrder();
})
.Send();
}
else
{
isOrderSending = false;
}
}
private void ReportGoogleOrderLost(GoogleOrderData data)
{
Analytics.LogEvent("google_order_lost", new Dictionary<string, dynamic>()
{
["data"] = data.ToString(),
}, new Analytics.EventSetting()
{
EnableFirebaseAnalytics = true,
EnableFacebookAnalytics = true,
});
}
private void ReportAppleOrderLost(AppleOrderData data)
{
Analytics.LogEvent("apple_order_lost", new Dictionary<string, dynamic>()
{
["data"] = data.ToString(),
}, new Analytics.EventSetting()
{
EnableFirebaseAnalytics = true,
EnableFacebookAnalytics = true,
});
}
#endregion
}
}