257 lines
11 KiB
C#
257 lines
11 KiB
C#
// ============================================================
|
||||
|
|
// IAPDemoUsage.cs
|
|||
|
|
// IAP 接入使用示例(MonoBehaviour)
|
|||
|
|
//
|
|||
|
|
// 将此脚本挂到场景中的任意 GameObject 即可运行示例。
|
|||
|
|
// 请将商品 ID 替换为你在 App Store Connect / Google Play Console 中配置的真实 ID。
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
using System.Collections;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.Purchasing;
|
|||
|
|
|
|||
|
|
namespace SDK_IAP
|
|||
|
|
{
|
|||
|
|
public class IAPDemoUsage : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 商品 ID 常量(请替换为真实 ID)
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
private const string PRODUCT_GOLD_100 = "mediumpack_01"; // 消耗品
|
|||
|
|
private const string PRODUCT_REMOVE_ADS = "non_ads"; // 非消耗品
|
|||
|
|
private const string PRODUCT_VIP_MONTH = "subcra"; // 订阅
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 生命周期
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
private void Awake()
|
|||
|
|
{
|
|||
|
|
// 订阅发货事件(持续监听,全局处理发货逻辑)
|
|||
|
|
IAPManager.OnDeliver += HandleDeliver;
|
|||
|
|
IAPManager.OnInitialized += HandleInitialized;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void Start()
|
|||
|
|
{
|
|||
|
|
InitIAP();
|
|||
|
|
//StartCoroutine(Test());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//private IEnumerator Test()
|
|||
|
|
//{
|
|||
|
|
// int index = 0;
|
|||
|
|
// while (true)
|
|||
|
|
// {
|
|||
|
|
// yield return new WaitForSeconds(1f);
|
|||
|
|
|
|||
|
|
// Analytics.OnTrackEvent?.Invoke($"test{index}", new Dictionary<string, string>());
|
|||
|
|
// index++;
|
|||
|
|
// }
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
private void OnDestroy()
|
|||
|
|
{
|
|||
|
|
IAPManager.OnDeliver -= HandleDeliver;
|
|||
|
|
IAPManager.OnInitialized -= HandleInitialized;
|
|||
|
|
IAPManager.Dispose();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 初始化
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
private void InitIAP()
|
|||
|
|
{
|
|||
|
|
var products = new List<ProductDefine>
|
|||
|
|
{
|
|||
|
|
// 消耗品 — 金币
|
|||
|
|
ProductDefine.Simple(PRODUCT_GOLD_100, ProductType.Consumable),
|
|||
|
|
|
|||
|
|
// 非消耗品 — 去广告(带平台特定 ID 示例)
|
|||
|
|
ProductDefine.Simple(
|
|||
|
|
PRODUCT_REMOVE_ADS,
|
|||
|
|
ProductType.NonConsumable),
|
|||
|
|
|
|||
|
|
// 订阅 — VIP 月卡
|
|||
|
|
ProductDefine.Simple(PRODUCT_VIP_MONTH, ProductType.Subscription),
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Debug.Log("[IAP Demo] 开始初始化...");
|
|||
|
|
IAPManager.Init(products, OnInitCallback);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Init 完成回调(与 OnInitialized 事件等价,二选一即可)
|
|||
|
|
private void OnInitCallback(bool success)
|
|||
|
|
{
|
|||
|
|
if (success)
|
|||
|
|
{
|
|||
|
|
Debug.Log("[IAP Demo] 初始化成功!");
|
|||
|
|
ShowProductPrices();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogError("[IAP Demo] 初始化失败,请检查网络或 App Store / Google Play 配置。");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 也可以通过静态事件监听(适合多个 Manager 分散处理)
|
|||
|
|
private void HandleInitialized(bool success)
|
|||
|
|
{
|
|||
|
|
// 此处可做更新 UI 等操作
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 显示商品价格(初始化成功后调用)
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
private void ShowProductPrices()
|
|||
|
|
{
|
|||
|
|
var products = IAPManager.GetProducts();
|
|||
|
|
foreach (var p in products)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[IAP Demo] 商品: {p.definition.id} | 价格: {p.metadata.localizedPriceString}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 购买示例
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/// <summary>购买 100 金币(消耗品)</summary>
|
|||
|
|
public void BuyGold100()
|
|||
|
|
{
|
|||
|
|
IAPManager.Buy(PRODUCT_GOLD_100, result =>
|
|||
|
|
{
|
|||
|
|
if (result.success)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[IAP Demo] 购买成功: {result.productId} | tid={result.transactionId}");
|
|||
|
|
// ⚠️ 消耗品奖励建议存服务器,防止本地数据丢失
|
|||
|
|
// GoldManager.Add(100);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[IAP Demo] 购买失败: {result.error}");
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>购买去广告(非消耗品)</summary>
|
|||
|
|
public void BuyRemoveAds()
|
|||
|
|
{
|
|||
|
|
IAPManager.Buy(PRODUCT_REMOVE_ADS, result =>
|
|||
|
|
{
|
|||
|
|
if (result.success)
|
|||
|
|
{
|
|||
|
|
Debug.Log("[IAP Demo] 去广告购买成功");
|
|||
|
|
// AdsManager.Disable();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[IAP Demo] 购买失败: {result.error}");
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>购买 VIP 月卡(订阅)</summary>
|
|||
|
|
public void BuyVipMonth()
|
|||
|
|
{
|
|||
|
|
IAPManager.Buy(PRODUCT_VIP_MONTH, result =>
|
|||
|
|
{
|
|||
|
|
if (result.success)
|
|||
|
|
{
|
|||
|
|
Debug.Log("[IAP Demo] VIP 订阅成功");
|
|||
|
|
ShowSubscriptionInfo();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
Debug.LogWarning($"[IAP Demo] 订阅失败: {result.error}");
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 恢复购买(iOS 界面上必须提供此按钮)
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
public void OnRestoreButtonClicked()
|
|||
|
|
{
|
|||
|
|
// UI 控制:仅在需要时显示此按钮
|
|||
|
|
if (!IAPManager.NeedShowRestoreButton()) return;
|
|||
|
|
|
|||
|
|
IAPManager.Restore(result =>
|
|||
|
|
{
|
|||
|
|
if (result.success)
|
|||
|
|
Debug.Log("[IAP Demo] 恢复购买流程完成(实际恢复内容通过 OnDeliver 发放)");
|
|||
|
|
else
|
|||
|
|
Debug.LogWarning($"[IAP Demo] 恢复购买失败: {result.error}");
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 权益检查
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
public void CheckRemoveAdsEntitlement()
|
|||
|
|
{
|
|||
|
|
IAPManager.CheckEntitlement(PRODUCT_REMOVE_ADS, status =>
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[IAP Demo] 去广告权益状态: {status}");
|
|||
|
|
// EntitlementStatus.FullyEntitled = 已购买且有效
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 订阅信息查询
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
public void ShowSubscriptionInfo()
|
|||
|
|
{
|
|||
|
|
var info = IAPManager.GetSubscriptionInfo(PRODUCT_VIP_MONTH);
|
|||
|
|
Debug.Log($"[IAP Demo] VIP 订阅状态:");
|
|||
|
|
Debug.Log($" isSubscribed = {info.isSubscribed}");
|
|||
|
|
Debug.Log($" isExpired = {info.isExpired}");
|
|||
|
|
Debug.Log($" expireDate = {info.expireDate:yyyy-MM-dd HH:mm:ss}");
|
|||
|
|
Debug.Log($" isAutoRenewing= {info.isAutoRenewing}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
// 全局发货处理(OnDeliver 事件接收)
|
|||
|
|
// ──────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 统一发货处理入口。
|
|||
|
|
/// 无论是新购买、补单、还是恢复购买,都会触发此方法。
|
|||
|
|
/// ⚠️ 幂等保护已由 DeliverGuardLite 处理,此处无需再判重。
|
|||
|
|
/// </summary>
|
|||
|
|
private void HandleDeliver(string productId)
|
|||
|
|
{
|
|||
|
|
Debug.Log($"[IAP Demo] 发货通知: {productId}");
|
|||
|
|
|
|||
|
|
switch (productId)
|
|||
|
|
{
|
|||
|
|
case PRODUCT_GOLD_100:
|
|||
|
|
Debug.Log("[IAP Demo] 发放 100 金币");
|
|||
|
|
// GoldManager.Add(100);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case PRODUCT_REMOVE_ADS:
|
|||
|
|
Debug.Log("[IAP Demo] 开启去广告");
|
|||
|
|
// AdsManager.Disable();
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case PRODUCT_VIP_MONTH:
|
|||
|
|
Debug.Log("[IAP Demo] 激活 VIP");
|
|||
|
|
// VipManager.Activate();
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
Debug.LogWarning($"[IAP Demo] 未知商品 ID: {productId}");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|