lib_unity_purchase/Runtime/Stores/Android/UDP/UDPBindings.cs

244 lines
9.5 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using UnityEngine.Purchasing.Extension;
using UnityEngine.Purchasing.MiniJSON;
namespace UnityEngine.Purchasing
{
internal class UDPBindings : INativeUDPStore
{
private readonly object m_Bridge;
private Action<bool, string> m_RetrieveProductsCallbackCache;
public UDPBindings()
{
var udpIapBridge = UdpIapBridgeInterface.GetClassType();
if (udpIapBridge != null)
{
m_Bridge = Activator.CreateInstance(udpIapBridge);
}
else
{
Debug.LogError("Failed to access UDP. Please make sure your UDP package is installed and up-to-date");
throw new NotImplementedException();
}
}
public void Initialize(Action<bool, string> callback)
{
if (m_Bridge != null)
{
var initMethod = UdpIapBridgeInterface.GetInitMethod();
initMethod.Invoke(m_Bridge, new object[] { callback });
}
else
{
Debug.LogError("Cannot Initialize UDP store module. Please make sure your UDP package is installed and up-to-date");
throw new NotImplementedException();
}
}
public void Purchase(string productId, Action<bool, string> callback, string developerPayload = null)
{
if (m_Bridge != null)
{
var purchaseMethod = UdpIapBridgeInterface.GetPurchaseMethod();
purchaseMethod.Invoke(m_Bridge, new object[] { productId, callback, developerPayload });
}
else
{
Debug.LogError("Cannot Purchase via UDP. Please make sure your UDP package is installed and up-to-date");
throw new NotImplementedException();
}
}
public void RetrieveProducts(ReadOnlyCollection<ProductDefinition> products, Action<bool, string> callback)
{
if (m_Bridge != null)
{
if (m_RetrieveProductsCallbackCache != null)
{
callback(false, /*lang=json,strict*/ "{ \"error\" : \"already retrieving products\" }");
return;
}
m_RetrieveProductsCallbackCache = callback;
Action<bool, object> retrieveCallback = OnInventoryQueried;
var retrieveProductsMethod = UdpIapBridgeInterface.GetRetrieveProductsMethod();
var ids = new List<String>();
foreach (var product in products)
{
ids.Add(product.storeSpecificId);
}
retrieveProductsMethod.Invoke(m_Bridge, new object[] { new ReadOnlyCollection<string>(ids), retrieveCallback });
}
else
{
Debug.LogError("Cannot Retrieve Products from UDP. Please make sure your UDP package is installed and up-to-date");
throw new NotImplementedException();
}
}
public void FinishTransaction(ProductDefinition productDefinition, string transactionID)
{
if (m_Bridge != null)
{
var finishTransactionMethod = UdpIapBridgeInterface.GetFinishTransactionMethod();
finishTransactionMethod.Invoke(m_Bridge, new object[] { transactionID });
}
else
{
Debug.LogError("Cannot Complete transaction for UDP. Please make sure your UDP package is installed and up-to-date");
throw new NotImplementedException();
}
}
private void OnInventoryQueried(bool success, object payload)
{
var actualSuccess = success;
string parsedPayload;
var inventoryType = InventoryInterface.GetClassType();
if (success)
{
if (inventoryType != null)
{
var inventory = payload;
if (inventory != null && inventory.GetType() == inventoryType)
{
var fetchedProducts = new HashSet<ProductDescription>();
var getProductList = InventoryInterface.GetProductListMethod();
var products = (IEnumerable)getProductList.Invoke(inventory, null);
var productList = products.Cast<object>().ToList();
foreach (var productInfo in productList)
{
var priceProp = ProductInfoInterface.GetPriceProp();
var titleProp = ProductInfoInterface.GetTitleProp();
var descProp = ProductInfoInterface.GetDescriptionProp();
var currencyProp = ProductInfoInterface.GetCurrencyProp();
var microsProp = ProductInfoInterface.GetPriceAmountMicrosProp();
var metadata = new ProductMetadata(
(string)priceProp.GetValue(productInfo, null),
(string)titleProp.GetValue(productInfo, null),
(string)descProp.GetValue(productInfo, null),
(string)currencyProp.GetValue(productInfo, null),
Convert.ToDecimal((long)microsProp.GetValue(productInfo, null)) / 1000000);
var idProp = ProductInfoInterface.GetProductIdProp();
var productId = (string)idProp.GetValue(productInfo, null);
var desc = new ProductDescription(productId, metadata);
var hasPurchase = InventoryInterface.HasPurchaseMethod();
if ((bool)hasPurchase.Invoke(inventory, new object[] { productId }))
{
var getPurchaseInfo = InventoryInterface.GetPurchaseInfoMethod();
var purchase = getPurchaseInfo.Invoke(inventory, new object[] { productId });
var dic = StringPropertyToDictionary(purchase);
var transactionId = dic["GameOrderId"];
var storeSpecificId = dic["ProductId"];
if (!string.IsNullOrEmpty(transactionId))
{
dic["transactionId"] = transactionId;
}
if (!string.IsNullOrEmpty(storeSpecificId))
{
dic["storeSpecificId"] = storeSpecificId;
}
desc = new ProductDescription(productId, metadata, dic.toJson(), transactionId);
}
fetchedProducts.Add(desc);
}
parsedPayload = JSONSerializer.SerializeProductDescs(fetchedProducts);
}
else
{
actualSuccess = false;
parsedPayload = /*lang=json,strict*/ "{ \"error\" : \"Cannot load inventory from UDP. Please make sure your UDP package is installed and up-to-date\" }";
}
}
else
{
actualSuccess = false;
parsedPayload = /*lang=json,strict*/ "{ \"error\" : \"Cannot parse inventory type for UDP. Please make sure your UDP package is installed and up-to-date\" }";
}
}
else
{
parsedPayload = (string)payload;
}
m_RetrieveProductsCallbackCache(actualSuccess, parsedPayload);
m_RetrieveProductsCallbackCache = null;
}
#region INativeStore - Unused
public void RetrieveProducts(string json)
{
throw new NotImplementedException();
}
public void Purchase(string productJSON, string developerPayload)
{
throw new NotImplementedException();
}
public void FinishTransaction(string productJSON, string transactionID)
{
throw new NotImplementedException();
}
#endregion
#region helper functions
/// <summary>
/// Put the string property of <see cref="info"/> into a dictionary if the property is not empty string.
/// </summary>
/// <param name="info">Model object, namely <see cref="PurchaseInfo"/> or <see cref="UserInfo"/></param>
/// <returns></returns>
internal static Dictionary<string, string> StringPropertyToDictionary(object info)
{
var dictionary = new Dictionary<string, string>();
if (info == null)
{
return dictionary;
}
var properties = info.GetType().GetProperties();
foreach (var property in properties)
{
if (property.PropertyType == typeof(string))
{
var value = (string)property.GetValue(info, null);
if (!string.IsNullOrEmpty(value))
{
dictionary[property.Name] = value;
}
}
}
return dictionary;
}
#endregion
}
}