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 结构体内 新增一个字段 autoRenewing
  • 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 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 进入开发阶段

参数列表
参数
含义
updateSubscriptionHandler

此方法用来监听 订阅初始化完成后和订阅更新时的回调处理

返回一个subscriptionDict的订阅字典  包含{ 商品ID: 订阅状态 } 信息

此方法 监听时如果已经初始化 立即回调

如果没有初始化 等待初始化后 回调

subscriptionDict
可以在业务逻辑中 通过 SubscriptionController.Instance.subscriptionDict 来获取每个订阅的状态 

 源码

using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Security;
using UnityEngine;
using System;
using System.Collections.Generic;
using Google.Play.Billing;
using IGooglePlayStoreExtensions = UnityEngine.Purchasing.IGooglePlayStoreExtensions;

/// <summary>
/// 
/// 订阅
/// 
/// 
/// @anchor: ChenJC
/// @time: 2023/07/05
/// 
/// </summary>
public class SubscriptionController : SingleTon<SubscriptionController>
{
    private IStoreController m_Controller = null;
    private IExtensionProvider m_Extensions = null;

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

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

    /// <summary>
    /// 订阅状态字典
    /// key : 订阅产品 ( 仅包含有订阅过的产品id )
    /// value : 当前订阅状态 
    /// </summary>
    private Action<Dictionary<string, bool>> updateSubscriptionCallback;

    /// <summary>
    /// 订阅拉取并更新后回调处理
    /// </summary>
    public event Action<Dictionary<string, bool>> updateSubscriptionHandler
    {
        add
        {
            if ( inited )
            {
                value?.Invoke( subscriptionDict );
            }
            updateSubscriptionCallback += value;
        }

        remove
        {
            updateSubscriptionCallback -= value;
        }
    }

    public void OnInitialized( IStoreController storeController, IExtensionProvider extensions )
    {
        Debug.Log( "订阅Manager初始化开始..." );
        m_Controller = storeController;
        m_Extensions = extensions;
        UpdateSubscription( );
        inited = true;
        Debug.Log( "订阅Manager初始化结束..." );
    }

    public void UpdateSubscription( )
    {
        //        Dictionary<string, string> introductory_info_dict = null;
        //#if UNITY_ANDROID
        //        //var m_GooglePlayStoreExtensions = m_Extensions.GetExtension<IGooglePlayStoreExtensions>( );
        //#else
        //        var m_AppleExtensions = m_Extensions.GetExtension<IAppleExtensions>( );
        //        introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary( );
        //#endif
        foreach ( var item in m_Controller.products.all )
        {
            if ( item.availableToPurchase )
            {
                Debug.Log( string.Join( " - ",
                    new[]
                    {
                        item.metadata.localizedTitle,
                        item.metadata.localizedDescription,
                        item.metadata.isoCurrencyCode,
                        item.metadata.localizedPrice.ToString(),
                        item.metadata.localizedPriceString,
                        item.transactionID,
                        item.receipt
                    } ) );
                //#if !UNITY_ANDROID
                //                // Set all these products to be visible in the user's App Store according to Apple's Promotional IAP feature
                //                // https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/PromotingIn-AppPurchases/PromotingIn-AppPurchases.html
                //                m_AppleExtensions.SetStorePromotionVisibility(item, AppleStorePromotionVisibility.Show);
                //#endif
                // this is the usage of SubscriptionManager class
                if ( item.receipt != null )
                {
                    if ( item.definition.type == ProductType.Subscription )
                    {
                        try
                        {
                            SubscriptionManager p = new SubscriptionManager( item, null );
                            SubscriptionInfo info = p.getSubscriptionInfo( );

                            if ( info.isAutoRenewing( ) == Result.True || info.isSubscribed( ) == Result.True )
                            {
                                subscriptionDict[ info.getProductId( ) ] = true;
                            }
                            else
                            {
                                //非订阅状态判断是否到期
                                if ( info.isExpired( ) == Result.False )
                                {
                                    subscriptionDict[ info.getProductId( ) ] = true;
                                }
                                else
                                {
                                    subscriptionDict[ info.getProductId( ) ] = false;
                                }
                            }
                        }
                        catch ( Exception e1 ) //StoreSubscriptionInfoNotSupportedException es
                        {
                            //老版本数据解析失败 使用自己定义的方式来解析 通过autoRenewing来判读
                            Debug.Log( "This product is not available for SubscriptionManager class, only products that are purchase by 1.19+ SDK can use this class." );
                            try
                            {
                                GooglePurchaseData data = new GooglePurchaseData( item.receipt );
                                subscriptionDict[ data.json.productId ] = data.json.autoRenewing;
                            }
                            catch ( Exception e )
                            {
                                Debug.LogWarning( e );
                            }
                        }
                    }
                }
            }
        }
        updateSubscriptionCallback?.Invoke( subscriptionDict );
    }


    private bool checkIfProductIsAvailableForSubscriptionManager( string receipt )
    {
        var receipt_wrapper = ( Dictionary<string, object> ) MiniJson.JsonDecode( receipt );
        if ( !receipt_wrapper.ContainsKey( "Store" ) || !receipt_wrapper.ContainsKey( "Payload" ) )
        {
            Debug.Log( "The product receipt does not contain enough information" );
            return false;
        }
        var store = ( string ) receipt_wrapper[ "Store" ];
        var payload = ( string ) receipt_wrapper[ "Payload" ];

        if ( payload != null )
        {
            switch ( store )
            {
                case GooglePlay.Name:
                    {
                        var payload_wrapper = ( Dictionary<string, object> ) MiniJson.JsonDecode( payload );
                        if ( !payload_wrapper.ContainsKey( "json" ) )
                        {
                            Debug.Log( "The product receipt does not contain enough information, the 'json' field is missing" );
                            return false;
                        }
                        var original_json_payload_wrapper = ( Dictionary<string, object> ) MiniJson.JsonDecode( ( string ) payload_wrapper[ "json" ] );
                        if ( original_json_payload_wrapper == null || !original_json_payload_wrapper.ContainsKey( "developerPayload" ) )
                        {
                            Debug.Log( "The product receipt does not contain enough information, the 'developerPayload' field is missing" );
                            return false;
                        }
                        var developerPayloadJSON = ( string ) original_json_payload_wrapper[ "developerPayload" ];
                        var developerPayload_wrapper = ( Dictionary<string, object> ) MiniJson.JsonDecode( developerPayloadJSON );
                        if ( developerPayload_wrapper == null || !developerPayload_wrapper.ContainsKey( "is_free_trial" ) || !developerPayload_wrapper.ContainsKey( "has_introductory_price_trial" ) )
                        {
                            Debug.Log( "The product receipt does not contain enough information, the product is not purchased using 1.19 or later" );
                            return false;
                        }
                        return true;
                    }
                case AppleAppStore.Name:
                case AmazonApps.Name:
                case MacAppStore.Name:
                    {
                        return true;
                    }
                default:
                    {
                        return false;
                    }
            }
        }
        return false;
    }

}

使用方式 


在支付初始化成功后调用 

 

以及购买订阅后更新

 


订阅处理


subscriptionDict字典返回的是购买过的订阅商品名和订阅状态字典

True: 订阅 | 自动续费开启
False: 取消订阅 && 关闭订阅  && 订阅到期

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值