Unity IAP GooglePlay 订阅功能

一、背景
  • 技术难点:
    • 用户卸载后重新安装,如何恢复订阅的功能
    • 如何验证用户的订阅是否结束!
    • 我们如何测试订阅

二、操作步骤

1.1 初始化订阅和购买订阅

 购买订阅和正常购买没有区别 按照正常流程购买就行
ConfigurationBuilder builder = ConfigurationBuilder.Instance( Google.Play.Billing.GooglePlayStoreModule.Instance() );
foreach ( var itemId in itemIds )
{
      builder.AddProduct( itemId, ProductType.Subscription ); //订阅
      Debug.Log( "注册商品:" + itemId );
}
UnityPurchasing.Initialize( this, builder );

准备工作

  • GooglePurchaseJson 结构体内 新增三个字段
  • using UnityEngine;
    
    public struct GoogleToken
    {
        public string packageName;
        public string productId;
        public string token;
        public string projectId;
    }
    
    public class ProductData
    {
        public string productId;
        public int checkStatus;
        public string timestamp;
        public string sign;
    }
    
    public class GooglePurchaseData
    {
        // INAPP_PURCHASE_DATA
        public string inAppPurchaseData;
        // INAPP_DATA_SIGNATURE
        public string inAppDataSignature;
    
        public GooglePurchaseJson json;
    
        [System.Serializable]
        private struct GooglePurchaseReceipt
        {
            public string Payload;
        }
    
        [System.Serializable]
        private struct GooglePurchasePayload
        {
            public string json;
            public string signature;
        }
    
        [System.Serializable]
        public struct GooglePurchaseJson
        {
            public string packageName;
            public string productId;
            public string purchaseTime;
            public string purchaseState;
            public string purchaseToken;
    
            public string autoRenewing;
            public string orderId;
            public string developerPayload;
        }
        public GooglePurchaseData( string receipt )
        {
            try
            {
                var purchaseReceipt = JsonUtility.FromJson<GooglePurchaseReceipt>( receipt );
                var purchasePayload = JsonUtility.FromJson<GooglePurchasePayload>( purchaseReceipt.Payload );
                var inAppJsonData = JsonUtility.FromJson<GooglePurchaseJson>( purchasePayload.json );
    
                inAppPurchaseData = purchasePayload.json;
                inAppDataSignature = purchasePayload.signature;
                json = inAppJsonData;
            }
            catch
            {
                Debug.Log( "Could not parse receipt: " + receipt );
                inAppPurchaseData = "";
                inAppDataSignature = "";
            }
        }
    }
    

1.2 进入开发阶段

参数列表
参数
含义
inited
可以在 业务逻辑代码中 通过 SubscriptionController.Instance.inited 来判断 订阅是否初始化完成
补充: 订阅初始化是在内购初始化完成后调用的 也可以用来判定内购是否初始化完成了
用法: 你可以在游戏内使用协程来询问订阅是否初始化完成
subscriptionDict
可以在业务逻辑中 通过 SubscriptionController.Instance.subscriptionDict 来获取每个订阅的状态 当然他也包含非订阅产品

 源码

using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;
using UnityEngine;
using System;
using System.Collections.Generic;

/// <summary>
/// 
/// 订阅
/// 
/// 
/// </summary>
public class SubscriptionController : SingleTon<SubscriptionController>
{
    private IStoreController m_StoreController = null;

    /// <summary>
    /// 是否初始化完成
    /// </summary>
    public bool inited { private set; get; } = false;

    /// <summary>
    /// 订阅字典
    /// </summary>
    public Dictionary<string, bool> subscriptionDict { private set; get; } = new Dictionary<string, bool>();

    public void Initia( IStoreController storeController = null )
    {

        m_StoreController = storeController;
        //每次进入游戏调用检查订阅方法
#if UNITY_ANDROID
        CheckSubscribeReceiptAndorid();
#elif UNITY_IOS || UNITY_STANDALONE_OSX
        CheckSubscribeReceipt();
#endif

        inited = true;
    }

    public void CheckOk( string productId )
    {
        //如果检查处于订阅状态,可以在这里做客户端逻辑处理
        subscriptionDict[ productId ] = true;
    }
    public void CheckWrong( string productId )
    {
        //如果检查处于非订阅状态,可以在这里做客户端逻辑处理
        subscriptionDict[ productId ] = false;
    }

    //检查谷歌订阅状态的方法,该方法需要同时导入另外一个脚本GooglePurchaseData 解析谷歌支付的receipt
    public void CheckSubscribeReceiptAndorid()
    {
        foreach ( Product p in m_StoreController.products.all )
        {
            if ( p.hasReceipt )
            {
                Debug.Log( "recepit all:" + p.receipt );
                GooglePurchaseData data = new GooglePurchaseData( p.receipt );
                Debug.Log( "recepit autoRenewing:" + data.json.autoRenewing );
                /*
                Debug.Log("recepit orderId:" + data.json.orderId);
                Debug.Log("recepit packageName:" + data.json.packageName);
                Debug.Log("recepit productId:" + data.json.productId);
                Debug.Log("recepit purchaseTime:" + data.json.purchaseTime);
                Debug.Log("recepit purchaseState:" + data.json.purchaseState);
                Debug.Log("recepit purchaseToken:" + data.json.purchaseToken);
               */
                if ( bool.Parse( data.json.autoRenewing ) )
                {
                    CheckOk( data.json.productId );
                }
                else
                {
                    CheckWrong( data.json.productId );
                }

            }
        }

    }

    //检查IOS订阅状态的方法, 这里是通过receipt里面的expiredate和当前时间对比来判断当前的订阅商品是否过期。
    public void CheckSubscribeReceipt()
    {
        try
        {
            var builder = ConfigurationBuilder.Instance( StandardPurchasingModule.Instance() );
            // Get a reference to IAppleConfiguration during IAP initialization.
            var appleConfig = builder.Configure<IAppleConfiguration>();
            if ( appleConfig == null || string.IsNullOrEmpty( appleConfig.appReceipt ) )
            {
                return;
            }
            //Debug.LogError("appReceipt:" + appleConfig.appReceipt);
            var receiptData = System.Convert.FromBase64String( appleConfig.appReceipt );
            if ( receiptData == null )
            {
                return;
            }
            AppleReceipt receipt = new AppleReceiptParser().Parse( receiptData );
            if ( receipt == null )
            {
                return;
            }
            foreach ( AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts )
            {

                if ( productReceipt.productType == 3 )
                {
                    Debug.Log( "sub productid = " + productReceipt.productID );
                    DateTime expirationDate = productReceipt.subscriptionExpirationDate;
                    Debug.Log( "sub ExpirationDate = " + expirationDate.ToString() );

                    DateTime now = DateTime.Now.ToUniversalTime();
                    //DateTime cancellationDate = apple.cancellationDate;

                    if ( DateTime.Compare( now, expirationDate ) < 0 )
                    {
                        CheckOk( productReceipt.productID );
                    }
                    else
                    {
                        CheckWrong( productReceipt.productID );
                    }
                }
            }
        }
        catch ( Exception exp )
        {
            Debug.Log( exp );
        }
    }


}

猜你喜欢

转载自blog.csdn.net/qq_39162566/article/details/130079818
IAP