一、背景
-
技术难点:
-
用户卸载后重新安装,如何恢复订阅的功能
-
如何验证用户的订阅是否结束!
-
我们如何测试订阅
-
二、操作步骤
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 );
}
}
}