2024-05-24 14:24:59 +08:00
|
|
|
|
using PhxhSDK;
|
2024-09-14 18:21:08 +08:00
|
|
|
|
using System;
|
2024-05-27 15:28:19 +08:00
|
|
|
|
using System.Collections.Generic;
|
2024-09-14 18:21:08 +08:00
|
|
|
|
using Unity.Services.Core;
|
2024-05-27 15:28:19 +08:00
|
|
|
|
using Unity.Services.Core.Environments;
|
2024-09-14 18:21:08 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.Purchasing;
|
2024-06-05 14:34:58 +08:00
|
|
|
|
using UnityEngine.Purchasing.Extension;
|
2024-09-14 18:21:08 +08:00
|
|
|
|
using UnityEngine.Purchasing.Security;
|
2024-05-24 14:24:59 +08:00
|
|
|
|
|
2024-06-05 14:34:58 +08:00
|
|
|
|
public class IAPHandle : IDetailedStoreListener
|
2024-05-24 14:24:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
private const string Environment = "production";
|
2024-06-11 15:58:47 +08:00
|
|
|
|
public Action<string, string> SendReceiptAction;
|
2024-05-24 14:24:59 +08:00
|
|
|
|
public Action<string> SetApplicationUseId;
|
|
|
|
|
|
public Action<string> OnBreakPurchase;
|
|
|
|
|
|
public bool ClientVerify;
|
|
|
|
|
|
public List<string> ConsumableGoods;
|
|
|
|
|
|
public List<string> NonConsumableGoods;
|
|
|
|
|
|
|
|
|
|
|
|
private Dictionary<string, Product> _pendingDic = new Dictionary<string, Product>();
|
2024-06-03 12:19:05 +08:00
|
|
|
|
|
2024-05-24 14:24:59 +08:00
|
|
|
|
private IStoreController _controller;
|
|
|
|
|
|
private IExtensionProvider _extensions;
|
|
|
|
|
|
private IAppleExtensions _appleExtensions;
|
|
|
|
|
|
private IGooglePlayStoreExtensions _googlePlayStoreExtensions;
|
|
|
|
|
|
private Action<string> _onPurchaseSuccess;
|
|
|
|
|
|
private Action _onPurchaseFail;
|
2024-05-27 15:28:19 +08:00
|
|
|
|
private Action<List<string>> _onRestore;
|
2024-05-24 14:24:59 +08:00
|
|
|
|
private bool _isInitialized;
|
|
|
|
|
|
|
2024-09-14 18:21:08 +08:00
|
|
|
|
|
2024-05-24 14:24:59 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当前购买商品
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private string _curProduct;
|
|
|
|
|
|
|
|
|
|
|
|
public IAPHandle()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
InitUnityService();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("异常:" + exception);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region 初始化
|
|
|
|
|
|
|
|
|
|
|
|
async void InitUnityService()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2024-06-04 19:36:48 +08:00
|
|
|
|
Debug.Log("初始化Unity服务器");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
var options = new InitializationOptions().SetEnvironmentName(Environment);
|
|
|
|
|
|
await UnityServices.InitializeAsync(options).ContinueWith(task => OnInitUnityServiceSuccess());
|
2024-06-04 19:36:48 +08:00
|
|
|
|
StandardPurchasingModule.Instance().useFakeStoreAlways = true;
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnInitUnityServiceError(exception.Message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnInitUnityServiceError(string message)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("unity server initialization failed, Error: " + message);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void OnInitUnityServiceSuccess()
|
|
|
|
|
|
{
|
2024-06-04 19:36:48 +08:00
|
|
|
|
Debug.Log("unity server initialization successful !!");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化商品
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void InitIap()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ConsumableGoods == null && NonConsumableGoods == null)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2024-06-04 19:36:48 +08:00
|
|
|
|
Debug.Log("初始化IAP商品及 UnityPurchasing");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
|
|
|
|
|
|
|
|
|
|
|
|
//Add Product
|
|
|
|
|
|
foreach (var consumableGoods in ConsumableGoods)
|
|
|
|
|
|
{
|
2024-06-03 12:19:05 +08:00
|
|
|
|
Debug.Log($"添加消耗商品:{consumableGoods}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
builder.AddProduct(consumableGoods, ProductType.Consumable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var nonConsumableGoods in NonConsumableGoods)
|
|
|
|
|
|
{
|
2024-06-03 12:19:05 +08:00
|
|
|
|
Debug.Log($"添加非消耗商品:{nonConsumableGoods}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
builder.AddProduct(nonConsumableGoods, ProductType.NonConsumable);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UnityPurchasing.Initialize(this, builder);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IStoreListener 初始化
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void IStoreListener.OnInitialized(IStoreController controller, IExtensionProvider extensions)
|
|
|
|
|
|
{
|
|
|
|
|
|
_controller = controller;
|
|
|
|
|
|
_extensions = extensions;
|
|
|
|
|
|
_appleExtensions = extensions.GetExtension<IAppleExtensions>();
|
|
|
|
|
|
_googlePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();
|
|
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(SDKManager.Instance.ApplicationUserName))
|
|
|
|
|
|
{
|
|
|
|
|
|
Guid uid = Guid.NewGuid();
|
|
|
|
|
|
SDKManager.Instance.ApplicationUserName = uid.ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_appleExtensions.SetApplicationUsername(SDKManager.Instance.ApplicationUserName);
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("IAP initialization successful");
|
|
|
|
|
|
Debug.Log("用户 UUID :" + SDKManager.Instance.ApplicationUserName);
|
2024-05-24 14:24:59 +08:00
|
|
|
|
_isInitialized = true;
|
2024-06-05 14:34:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
DebugUtil.LogError("购买 {0} 失败, 原因: {1} ", failureDescription.productId, failureDescription.message);
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IAP 初始化失败
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void IStoreListener.OnInitializeFailed(InitializationFailureReason error)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("Unity IAP遇到不可恢复的初始化错误调用,请检查配置或设备设置中是否禁用ipa");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IAP 初始化失败
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void IStoreListener.OnInitializeFailed(InitializationFailureReason error, string message)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("IAP OnInitializeFailed reason : " + message);
|
|
|
|
|
|
switch (error)
|
|
|
|
|
|
{
|
|
|
|
|
|
case InitializationFailureReason.AppNotKnown:
|
|
|
|
|
|
DebugUtil.LogError("IAP Is your App correctly uploaded on the relevant publisher console?");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case InitializationFailureReason.PurchasingUnavailable:
|
|
|
|
|
|
DebugUtil.LogError("IAP Billing disabled!");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case InitializationFailureReason.NoProductsAvailable:
|
|
|
|
|
|
DebugUtil.LogError("IAP No products available for purchase!");
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(error), error, message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
2024-05-27 15:28:19 +08:00
|
|
|
|
|
2024-05-24 14:24:59 +08:00
|
|
|
|
#region 购买
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IAP 购买商品
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void BuyGoods(string productId, string actorId, Action<string> onPurchaseSuccess, Action onPurchaseFail)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("购买商品: " + productId);
|
2024-06-17 15:25:04 +08:00
|
|
|
|
#if !UNITY_EDITOR
|
2024-09-12 14:16:10 +08:00
|
|
|
|
#if PLATFORM_ANDROID
|
|
|
|
|
|
AliPayTest(productId);
|
|
|
|
|
|
#else
|
|
|
|
|
|
if (!_isInitialized || Application.internetReachability == NetworkReachability.NotReachable)
|
|
|
|
|
|
return;
|
|
|
|
|
|
_onPurchaseSuccess = onPurchaseSuccess;
|
|
|
|
|
|
_onPurchaseFail = onPurchaseFail;
|
|
|
|
|
|
_controller.InitiatePurchase(productId, actorId);
|
|
|
|
|
|
#endif
|
2024-06-17 15:25:04 +08:00
|
|
|
|
#else
|
|
|
|
|
|
DebugUtil.Log("请在真实环境下测试");
|
|
|
|
|
|
#endif
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IAP 购买成功
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
|
|
|
|
|
|
{
|
2024-09-12 14:16:10 +08:00
|
|
|
|
#if UNITY_IOS || UNITY_ANDROID
|
2024-05-24 14:24:59 +08:00
|
|
|
|
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
|
|
|
|
|
|
AppleTangle.Data(), Application.identifier);
|
|
|
|
|
|
DebugUtil.Log("Google Play Public Key: " + GooglePlayTangle.Data());
|
|
|
|
|
|
DebugUtil.Log("Apple Public Key: " + AppleTangle.Data());
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = validator.Validate(e.purchasedProduct.receipt);
|
|
|
|
|
|
DebugUtil.Log("Receipt is valid. Contents:");
|
|
|
|
|
|
foreach (IPurchaseReceipt productReceipt in result)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
if (!IAPManager.Instance.ProductDic.TryGetValue(productReceipt.productID, out var productID))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
Debug.Log($"productID: {productReceipt.productID}");
|
|
|
|
|
|
Debug.Log($"purchaseDate: {productReceipt.purchaseDate}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
|
|
|
|
|
|
AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;
|
|
|
|
|
|
if (null != apple)
|
|
|
|
|
|
{
|
|
|
|
|
|
_curProduct = productReceipt.productID;
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("iOS Receipt: " + apple.originalTransactionIdentifier);
|
2024-05-24 14:24:59 +08:00
|
|
|
|
if (!ClientVerify)
|
|
|
|
|
|
{
|
2024-05-27 15:28:19 +08:00
|
|
|
|
if (!IAPManager.Instance.OwnedNonConsumableGood(_curProduct))
|
|
|
|
|
|
{
|
|
|
|
|
|
AddPendingOrder(apple.originalTransactionIdentifier, e.purchasedProduct);
|
2024-06-11 15:58:47 +08:00
|
|
|
|
SendReceipt(apple.originalTransactionIdentifier, _curProduct);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log($"非消耗品商品{_curProduct}已购买过");
|
2024-05-27 15:28:19 +08:00
|
|
|
|
}
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_onPurchaseSuccess?.Invoke(_curProduct);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GooglePlayReceipt google = productReceipt as GooglePlayReceipt;
|
|
|
|
|
|
if (null != google)
|
|
|
|
|
|
{
|
|
|
|
|
|
_curProduct = productReceipt.productID;
|
|
|
|
|
|
// 这是 Google 的订单 ID。
|
|
|
|
|
|
// 请注意,在沙盒中测试时此项为 null,因为 Google 的沙盒不提供订单 ID。
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log($"Google transactionID: {google.transactionID}");
|
|
|
|
|
|
Debug.Log($"Google purchaseState: {google.purchaseState}");
|
|
|
|
|
|
Debug.Log($"Google purchaseToken: {google.purchaseToken}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
|
|
|
|
|
|
//TODO 谷歌服务器验证 待测试 待确定验证哪个参数
|
|
|
|
|
|
if (!ClientVerify)
|
|
|
|
|
|
{
|
2024-05-27 15:28:19 +08:00
|
|
|
|
if (!IAPManager.Instance.OwnedNonConsumableGood(_curProduct))
|
|
|
|
|
|
{
|
|
|
|
|
|
AddPendingOrder(google.transactionID, e.purchasedProduct);
|
2024-06-11 15:58:47 +08:00
|
|
|
|
SendReceipt(google.transactionID, _curProduct);
|
2024-05-27 15:28:19 +08:00
|
|
|
|
}
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
_onPurchaseSuccess?.Invoke(_curProduct);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("ProcessPurchase Result Error: " + exception);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ClientVerify)
|
|
|
|
|
|
return PurchaseProcessingResult.Complete;
|
|
|
|
|
|
|
|
|
|
|
|
return PurchaseProcessingResult.Pending;
|
|
|
|
|
|
#else
|
|
|
|
|
|
return PurchaseProcessingResult.Complete;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
2024-06-03 12:19:05 +08:00
|
|
|
|
|
2024-05-24 14:24:59 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 收集待验证凭证
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void AddPendingOrder(string appleReceipt, Product product)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("添加待验证收据:{appleReceipt}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
_pendingDic.TryAdd(appleReceipt, product);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 向服务器发送收据验证
|
|
|
|
|
|
/// </summary>
|
2024-06-11 14:35:00 +08:00
|
|
|
|
private void SendReceipt(string receipt, string product)
|
2024-05-24 14:24:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (SendReceiptAction == null)
|
|
|
|
|
|
DebugUtil.LogError("SendReceiptAction 为空");
|
2024-06-11 14:35:00 +08:00
|
|
|
|
SendReceiptAction?.Invoke(receipt, product);
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 服务器验证完成移除待验证凭证
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RemovePendingOrder(string receipt)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_pendingDic.ContainsKey(receipt))
|
|
|
|
|
|
{
|
|
|
|
|
|
_controller.ConfirmPendingPurchase(_pendingDic[receipt]);
|
|
|
|
|
|
_pendingDic.Remove(receipt);
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log($"移除待验证收据:{receipt}, 待验证凭证还有: {_pendingDic.Count}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_pendingDic.Count == 0)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log($"订单 {receipt} 已完结, 购买的商品: {_curProduct}");
|
2024-05-24 14:24:59 +08:00
|
|
|
|
_onPurchaseSuccess?.Invoke(_curProduct);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-11 15:58:47 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Debug
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void ConfirmPending()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var goods in _pendingDic)
|
|
|
|
|
|
{
|
|
|
|
|
|
_controller.ConfirmPendingPurchase(goods.Value);
|
|
|
|
|
|
Debug.Log($" 完成订单:{goods.Key}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_pendingDic.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-24 14:24:59 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IAP 购买失败
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void IStoreListener.OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (failureReason == PurchaseFailureReason.PurchasingUnavailable)
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("可能在设备设置中禁用了 IAP");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_curProduct = null;
|
|
|
|
|
|
_onPurchaseFail?.Invoke();
|
|
|
|
|
|
DebugUtil.LogError("Purchase of [{0}] failed for this reason: {1}", product.definition.id, failureReason);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-12 14:16:10 +08:00
|
|
|
|
#endregion
|
2024-05-24 14:24:59 +08:00
|
|
|
|
|
|
|
|
|
|
//TODO 待完善 测试
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 恢复交易
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void RestorePurchase(Action<List<string>> onRestorePurchase)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isInitialized)
|
|
|
|
|
|
return;
|
2024-05-24 15:50:51 +08:00
|
|
|
|
|
2024-05-27 15:28:19 +08:00
|
|
|
|
_onRestore = onRestorePurchase;
|
|
|
|
|
|
var apple = _extensions.GetExtension<IAppleExtensions>();
|
|
|
|
|
|
apple.RestoreTransactions(HandleRestored);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void HandleRestored(bool result, string message)
|
|
|
|
|
|
{
|
|
|
|
|
|
var tempRestoreGoods = new List<string>();
|
|
|
|
|
|
if (result)
|
|
|
|
|
|
{
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("恢复购买成功");
|
2024-05-27 15:28:19 +08:00
|
|
|
|
foreach (var product in _controller.products.all)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (product.hasReceipt)
|
|
|
|
|
|
{
|
|
|
|
|
|
tempRestoreGoods.Add(product.definition.id);
|
2024-06-06 15:44:06 +08:00
|
|
|
|
Debug.Log("Products to be restored: " + product.definition.id);
|
2024-05-27 15:28:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_onRestore?.Invoke(tempRestoreGoods);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogWarning("购买恢复失败: {0}", message);
|
|
|
|
|
|
}
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string GetAppReceipt()
|
|
|
|
|
|
{
|
|
|
|
|
|
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
|
|
|
|
|
|
string receipt = builder.Configure<IAppleConfiguration>().appReceipt;
|
|
|
|
|
|
return receipt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CanMakePayments()
|
|
|
|
|
|
{
|
|
|
|
|
|
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
|
|
|
|
|
|
return builder.Configure<IAppleConfiguration>().canMakePayments;
|
|
|
|
|
|
}
|
2024-07-23 15:09:46 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据ID获取商品价格
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string GetGoodPrice(string productID)
|
|
|
|
|
|
{
|
|
|
|
|
|
var product = _controller.products.WithID(productID);
|
|
|
|
|
|
if (product != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
string price = product.metadata.localizedPriceString;
|
|
|
|
|
|
DebugUtil.Log("Product price: " + price);
|
|
|
|
|
|
return price;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DebugUtil.LogError("Product not found");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2024-09-12 14:16:10 +08:00
|
|
|
|
|
|
|
|
|
|
public void AliPayTest(string orderInfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2024-09-14 18:21:08 +08:00
|
|
|
|
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
|
|
|
|
|
|
if (unityPlayer == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("unityPlayer is null");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-12 14:16:10 +08:00
|
|
|
|
AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
|
2024-09-14 19:15:13 +08:00
|
|
|
|
AndroidJavaObject utils = new AndroidJavaObject("com.phxh.dev.nld.PayActivity");
|
|
|
|
|
|
utils.Call("AliPay", orderInfo, currentActivity, "AliPayListener", "AliPayCallback");
|
2024-09-12 14:16:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError(e);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-05-24 14:24:59 +08:00
|
|
|
|
}
|