操作步骤
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: 取消订阅 && 关闭订阅 && 订阅到期