Unity SDK の統合
概要
Unity 開発者向けに Billing SDK のより優れた簡素化された統合を提供するため、Aptoide Billing SDK Unity が作成されました。これは Unity プロジェクトにインポートするパッケージで構成されており、Aptoide Billing SDK Native のミラーリングされたクラスとメソッドが含まれています。ネイティブ SDK の初期化、課金操作の管理、ネイティブ SDK からのコールバックの処理を行うメソッドを提供します。このパッケージは、Unity アプリケーションにおけるアプリ内購入や課金関連機能の統合を簡素化するように設計されています。
本ガイドは、この Aptoide Billing SDK Unity Package の統合を支援します。
Unity でのインポートと使用方法
Unity Package Manager を介したインポート
- 上部メニューバーを開きます: Window > Package Manager。
+記号をクリックし、Import via git URL を選択します。- 以下のリンクを貼り付けます:
https://github.com/Aptoide/aptoide-unity-billing-sdk.git
最新の更新情報を確認するには、こちらで利用可能なリリースをご確認ください。
インポートされるファイル
Runtime/Plugins/Android
このフォルダー内のファイルは、プロジェクトの Assets/Plugins/Android フォルダーに手動でインポートする必要があります。
重要
Assets/Plugins/Android フォルダーにコピーした後、プラグインの競合を避けるため、インポートしたパッケージから Runtime/Plugins/Android フォルダーを削除してください。
baseProjectTemplate.gradle
このファイルは、依存関係のリポジトリとソースを識別する目的で使用されます。
プロジェクトに build.gradle ファイルがまだない場合は、テンプレート baseProjectTemplate.gradle を使用できます。
gradleTemplate.properties
このファイルには、Aptoide Billing Native SDK を使用するために必要なオプションが含まれています。
プロジェクトに gradle.properties ファイルがまだない場合は、テンプレート gradleTemplate.properties を使用できます。
settingsTemplate.properties
このファイルは、依存関係のリポジトリとソースを識別する目的で使用されます。
プロジェクトに settings.gradle ファイルがまだない場合は、テンプレート settingsTemplate.gradle を使用できます。
mainTemplate.gradle
このファイルには、Unity Billing SDK を使用するために必要な依存関係が含まれています。
プロジェクトに main.gradle ファイルがまだない場合は、テンプレート mainTemplate.gradle を使用できます。
依存関係管理用のファイルがすでにある場合は、Unity Billing SDK が使用する 2 つの依存関係を追加するだけです。
dependencies {
implementation("com.aptoide:android-aptoide-billing:1.5.0") // Check the version in the mainTemplate.gradle to avoid any failures with the Native Billing SDK versioning
implementation("org.json:json:20210307")
}
AptoideBillingSDKUnityBridge.java
このファイルは、Unity Billing SDK と Android Native Billing SDK の間のメインブリッジとして機能します。
AptoideBillingClient クラスのメソッドを呼び出すことで、Unity をネイティブ SDK に接続します。
Runtime/SDK
AptoideBillingSDKManager.cs
このクラスは、プロジェクトから Unity Billing SDK への呼び出しを行うために使用されます。Native Billing SDK のミラーリングされたメソッドを備えています。
Unity Billing SDK の機能
初期化
- 必要なパラメーターで Aptoide Billing SDK を初期化します。
- ネイティブ課金サービスへの接続を確立します。
課金操作
- 商品の詳細を非同期でクエリします。
- アプリ内購入のための課金フローを起動します。
- 購入したアイテムを消費します。
- 消費不可の購入を承認します (消費せずに確定します)。
- ユーザーが行った購入をクエリします。
- 特定の機能が SDK でサポートされているかを確認します。
アカウント管理
- ユーザーを Aptoide アカウントにサインイン (およびサインアウト) させます。
- 再インストールやデバイス間で、保留中の購入および消費不可の購入を復元します。
- サインイン / サインアウトの状態変化を通知します。
アプリ更新管理
- アプリの更新が利用可能かどうかを確認します。
- 更新のためにダイアログを起動するか、ユーザーをストアへリダイレクトします。
コールバック処理
- 課金セットアップ、購入の更新、商品の詳細、消費レスポンス、承認レスポンス、アカウントのサインイン結果、アカウントの状態変化について、ネイティブ SDK からのコールバックを処理します。
統合に関する注意事項
AptoideBillingSDKManager を使用するには、そのメソッドを呼び出し、必要なゲームロジックを適用するための別のクラスを作成する必要があります。
課金フローの例
InitializePluginを使用して SDK を初期化します。QueryPurchasesAsyncを使用して完了済みだが未消費の購入をクエリし、それらを消費します。QueryProductDetailsAsyncを使用して利用可能な商品をクエリし、正しい価格をユーザーに表示します。LaunchBillingFlowを使用して選択した商品の課金フローを起動し、QueryProductDetailsAsyncで取得した商品の結果を使ってBillingFlowParamsを作成します。IPurchasesUpdatedListenerのOnPurchasesUpdatedメソッドで受け取った購入結果を処理します。- サーバー側で購入を検証します。
- アイテムをユーザーに提供します。
ConsumeAsyncを使用して購入を消費し、購入と提供のプロセスが自分側で正常に完了したことを通知します。
実装ガイド
1. サービス接続と初期化
Unity パッケージが完全に統合されたら、AptoideBillingSDKManager を初期化する必要があります。
そのためには、まず AptoideBillingSDKManager で使用するリスナーを実装する必要があります。これは、リスナーを変数で実装するか、次のようにゲームロジッククラスで直接実装することで行えます:
public class Logic : MonoBehaviour,
IAptoideBillingClientStateListener,
IConsumeResponseListener,
IPurchasesUpdatedListener,
IPurchasesResponseListener,
IProductDetailsResponseListener,
IAcknowledgeResponseListener,
IAptoideSignInResponseListener,
IAptoideAccountStateListener
{
...
void Start() {
AptoideBillingSDKManager.InitializePlugin(
this, // IAptoideBillingClientStateListener
this, // IConsumeResponseListener
this, // IPurchasesUpdatedListener
this, // IPurchasesResponseListener
this, // IProductDetailsResponseListener
this, // IAcknowledgeResponseListener
this, // IAptoideSignInResponseListener
this, // IAptoideAccountStateListener
"YOUR_PUBLIC_KEY", // Set here the public Key associated to your Billing Integration
gameObject.name
);
}
...
}
公開鍵を取得するには、このドキュメントに従ってください。
初期化を行うと、OnBillingSetupFinished および OnBillingServiceDisconnected メソッドで課金サービスへの接続状態を受け取ります。
接続が成功すると、responseCode が 0 の状態で OnBillingSetupFinished の呼び出しを受け取り、必要なメソッドを呼び出します:
public void OnBillingSetupFinished(BillingResult billingResult)
{
if (billingResult.ResponseCode == 0)
{
// Check pending purchases of Consumables
CheckPendingConsumables();
// Check for pending and active Subscriptions
CheckSubscriptions();
// Query in-app Product details
QueryInapps()
// Query subscriptions Product details
QuerySubs()
}
else
{
Debug.LogError($"Billing setup failed with response code: {billingResult.ResponseCode}");
}
}
2. 未消費の購入とアクティブなサブスクリプションのクエリ
セットアップが正常に完了したら、消費型の保留中の購入と、アクティブまたは保留中のサブスクリプションをただちに確認する必要があります。保留中の購入がある場合は、その正当性を検証し、アイテムをユーザーに提供して消費する必要があります。消費についてはステップ 5 で説明します。
消費型商品 (Consumables)
以下の例は、消費型の保留中の購入を確認する方法を示しています:
public void CheckPendingConsumables()
{
QueryPurchasesParams queryPurchasesParams =
QueryPurchasesParams.NewBuilder()
.SetProductType("inapp")
.Build();
// Query Purchases asynchronously for inapp products
AptoideBillingSDKManager.QueryPurchasesAsync(queryPurchasesParams);
}
public void OnQueryPurchasesResponse(BillingResult billingResult, Purchase[] purchases)
{
if (billingResult.ResponseCode == 0) // Assuming 0 indicates success
{
// Validate the Purchase in a server-to-server request
// follow this page /docs/iap-validators-server-to-server-check-client
// After validating, deliver the product to the User
// Lastly AptoideBillingSDKManager.ConsumeAsync should be called to notify
// Aptoide Services of the Successfull delivery and allow the User to Purchase once again the Item
}
else
{
Debug.LogError($"Failed to update purchases. Response code: {billingResult.ResponseCode}");
}
}
サブスクリプション (Subscriptions)
アクティブ/保留中のサブスクリプションを検証するには、QueryPurchasesAsync メソッドを使用します。結果は、保留中のサブスクリプション (消費対象) とアクティブなものから構成されます。期限切れになったサブスクリプションをユーザーから正しく削除するには、受け取った結果に含まれていないもので、現在ユーザーが利用可能なものを照合する必要があります。
以下の例は、サブスクリプションを確認する方法を示しています:
public void CheckSubscriptions()
{
QueryPurchasesParams queryPurchasesParams =
QueryPurchasesParams.NewBuilder()
.SetProductType("subs")
.Build();
// Query Purchases asynchronously for subscription products
AptoideBillingSDKManager.QueryPurchasesAsync(queryPurchasesParams);
}
public void OnQueryPurchasesResponse(BillingResult billingResult, Purchase[] purchases)
{
if (billingResult.ResponseCode == 0) // Assuming 0 indicates success
{
// Validate the Purchase in a server-to-server request
// follow this page /docs/iap-validators-server-to-server-check-client
// After validating, deliver the product to the User
// Lastly AptoideBillingSDKManager.ConsumeAsync should be called to notify
// Aptoide Services of the Successfull delivery and allow the User to Purchase once again the Item
// Remove Subscriptions from the User when not present in this list
}
else
{
Debug.LogError($"Failed to update purchases. Response code: {billingResult.ResponseCode}");
}
}
サブスクリプションのステータスに関するリアルタイム情報をユーザーに提供するには、RTDN を使用してください。
3. 商品のクエリ
接続を開始した後、Aptoide Connect からの正しい価格でユーザーに表示するため、購入可能な商品をクエリする必要があります。このクエリには、商品のタイトルだけでなく、説明、価格などが含まれます。
商品をクエリするには、AptoideBillingSDKManager.QueryProductDetailsAsync を使用できます。これにより、Aptoide Connect のレスポンスを処理する結果が得られます。
リスナーを作成した後、以下のようにパラメーターとともに QueryProductDetailsAsync に渡すことができます:
private static List<QueryProductDetailsParams.Product> inappProducts =
new List<QueryProductDetailsParams.Product>() {
QueryProductDetailsParams.Product.NewBuilder()
.SetProductId("my_inapp_sku")
.SetProductType("inapp")
.Build()
};
private static List<QueryProductDetailsParams.Product> subsProducts =
new List<QueryProductDetailsParams.Product>() {
QueryProductDetailsParams.Product.NewBuilder()
.SetProductId("my_sub_sku")
.SetProductType("subs")
.Build()
};
public void QueryInapps()
{
// inappProducts is a list of in-app QueryProductDetailsParams
QueryProductDetailsParams queryProductDetails =
QueryProductDetailsParams.NewBuilder()
.SetProductList(inappProducts)
.Build();
AptoideBillingSDKManager.QueryProductDetailsAsync(queryProductDetails);
}
public void QuerySubs()
{
// Check if subscriptions are supported
if (AptoideBillingSDKManager.IsFeatureSupported(0).ResponseCode == 0)
{
Debug.Log("Subscriptions are supported.");
// subsProducts is a list of subscription QueryProductDetailsParams
QueryProductDetailsParams queryProductDetails =
QueryProductDetailsParams.NewBuilder()
.SetProductList(subsProducts)
.Build();
AptoideBillingSDKManager.QueryProductDetailsAsync(queryProductDetails);
}
else
{
Debug.LogWarning("Subscriptions are not supported by the Billing Service.");
}
}
public void OnProductDetailsResponse(BillingResult billingResult, QueryProductDetailsResult productDetailsResult)
{
if (billingResult.ResponseCode == 0)
{
foreach (var productDetails in productDetailsResult.ProductDetailsList)
{
// Apply the Product details to the UI or perform any action
// based on the Product type (inapp or subs)
}
foreach(var unfetchedProduct in productDetailsResult.UnfetchedProductList)
{
// Apply the logic for the unfetched Products here
}
}
else
{
Debug.LogError($"Failed to receive SKU details. Response code: {responseCode}");
}
}
4. 課金フローの起動
購入フローを開始するには、AptoideBillingSDKManager.LaunchBillingFlow 関数を使用します。これは、QueryProductDetailsAsync で取得した商品を含む BillingFlowParams と、開発者が使用するデータを受け取ります。以下のスニペットは、「購入」ボタンに関連付ける可能性のある関数を示しています:
public void StartPurchase(ProductDetails productDetails, string obfuscatedAccountId)
{
if (AptoideBillingSDKManager.IsReady())
{
// Verify if the purchase of Subscription type you are making is a Free Trial or not
bool isFreeTrial = IsFreeTrialSubscription(productDetails, obfuscatedAccountId);
List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
new List<BillingFlowParams.ProductDetailsParams> ()
{
BillingFlowParams.ProductDetailsParams.NewBuilder()
// Use the ProductDetails obtained via QueryProductDetailsAsync() method
.SetProductDetails(productDetails)
.Build()
};
BillingFlowParams billingFlowParams =
BillingFlowParams.NewBuilder()
.SetProductDetailsParamsList(productDetailsParamsList)
.SetObfuscatedAccountId(obfuscatedAccountId)
.SetFreeTrial(isFreeTrial)
.Build();
BillingResult billingResult =
AptoideBillingSDKManager.LaunchBillingFlow(billingFlowParams);
}
}
obfuscatedAccountId パラメーターを使用すると、課金システムの不正利用や悪用の防止に役立ちます。この識別子により、課金アクティビティをアプリケーションの特定のユーザーと正確に関連付けることができ、セキュリティと信頼性が向上します。ユーザーアカウントロジックがない場合、このパラメーターは null にできます。
無料トライアルの起動
ユーザーに無料トライアルを有効にするには、LaunchBillingFlow メソッドで freeTrial パラメーターを true に設定します。これにより、指定された obfuscatedAccountId に基づいて無料トライアルの支払いが開始されます。
注: 無料トライアルの支払いを起動する際、
obfuscatedAccountIdは必須です。
ユーザーがそのサブスクリプションの無料トライアルをすでに消費している場合、以降のサブスクリプションの試行は自動的に通常の支払いフローにフォールバックします。これにより、スムーズな支払い体験が保証され、エラーを発生させることなく、デフォルトで freeTrial を安全に true に設定できます。
public bool IsFreeTrialSubscription(
ProductDetails productDetails,
string obfuscatedAccountId
)
{
// First verify if the features Free Trial and Obfucasted Account Id are available
if (AptoideBillingSDKManager.IsFeatureSupported(2).ResponseCode != 0)
{
return false;
}
if (AptoideBillingSDKManager.IsFeatureSupported(1).ResponseCode != 0)
{
return false;
}
// Verify if the Sku Type is a Subscription
if (!productDetails.getProductType() != "subs")
{
return false;
}
// Apply your internal App Logic to verify if the User should receive a Free Trial or not
/* Example:
return obfuscatedAccountId == "123" && productDetails.getProductId() == "trial_dice";
*/
return false;
}
5. 購入の処理とユーザーへのアイテム提供
public void OnPurchasesUpdated(BillingResult billingResult, Purchase[] purchases)
{
if (billingResult.ResponseCode == 0)
{
foreach (var purchase in purchases)
{
string purchaseToken = purchase.PurchaseToken;
// Validate the Purchase in a server-to-server request
// follow this page /docs/iap-validators-server-to-server-check-client
// After validating, deliver the product to the User
// Lastly ConsumeAsync should be called to allow the user to purchase the
// item again and change the purchase's state.
// Also consume subscriptions to make them active, there will be no issue in consuming more than once
ConsumeParams consumeParams = ConsumeParams.NewBuilder()
.SetPurchaseToken(purchaseToken)
.Build();
AptoideBillingSDKManager.ConsumeAsync(consumeParams);
}
}
else
{
// Handle the error
Debug.Log("Error: " + billingResult.ResponseCode);
}
}
購入の検証
購入の正当性を保証し、不正を防止するために、アプリケーションは常にサーバー間リクエストで購入を検証する必要があります。この検証を行うには、アプリ内購入検証ページのガイドラインに従ってください。購入の検証が成功した後にのみ、商品をユーザーに提供するよう進めてください。
購入の消費
購入が完了した後、それを消費する必要があります。購入を消費するには、AptoideBillingSDKManager.ConsumeAsync 関数を使用します。消費の結果は OnConsumeResponse メソッドで取得されます。
なお、48 時間以内に購入を消費しない場合、自動的に返金されます。
以下に OnConsumeResponse の実装例を示します:
public void OnConsumeResponse(BillingResult billingResult, string purchaseToken)
{
if (billingResult.ResponseCode == 0)
{
Debug.Log($"Purchase with token {purchaseToken} consumed successfully.");
}
else
{
Debug.LogError($"Failed to consume purchase with token {purchaseToken}. Response code: {billingResult.ResponseCode}");
}
}
6. 消費不可の購入の承認
消費不可の商品は一度購入すると永続的に所有されます (例: 広告削除や恒久的な装飾アイテム)。これらは消費してはいけません — 購入を消費すると QueryPurchasesAsync から削除され、再度購入可能になってしまいます。代わりに、商品を検証して提供した後、AptoideBillingSDKManager.AcknowledgeAsync で購入を承認します。
承認は支払いを確定 (48 時間後に自動返金されないように) しつつ、購入を所有された状態に保ちます。そのため、QueryPurchasesAsync で返され続け、同じユーザーが再度購入することはできません。
承認機能はリモートで切り替えられ、デフォルトでは無効です。これに依存する前に、AptoideBillingSDKManager.IsFeatureSupported(4).ResponseCode == 0 で利用可能かどうかを確認してください (レスポンスコード 0 は有効であることを意味します)。
AcknowledgeAsync メソッドは ConsumeAsync をミラーリングしています。購入トークンを含む AcknowledgeParams を受け取り、結果は IAcknowledgeResponseListener の OnAcknowledgeResponse メソッドに配信されます。消費不可の商品に対しては、ConsumeAsync の代わりに、OnPurchasesUpdated から、および保留中の購入を確認する際に、このメソッドを呼び出してください:
public void Acknowledge(string purchaseToken)
{
AcknowledgeParams acknowledgeParams = AcknowledgeParams.NewBuilder()
.SetPurchaseToken(purchaseToken)
.Build();
AptoideBillingSDKManager.AcknowledgeAsync(acknowledgeParams);
}
public void OnAcknowledgeResponse(BillingResult billingResult, string purchaseToken)
{
if (billingResult.ResponseCode == 0)
{
Debug.Log($"Purchase with token {purchaseToken} acknowledged successfully.");
}
else
{
Debug.LogError($"Failed to acknowledge purchase with token {purchaseToken}. Response code: {billingResult.ResponseCode}");
}
}
承認された消費不可の商品は所有された状態を維持するため、ユーザーは Aptoide アカウントにサインインすることで、新しいデバイスや再インストール後にそれらを復元できます。詳細については、Aptoide サービスへのサインインドキュメントページをご覧ください。
トラブルシューティング
よくある問題
-
課金が初期化されない:
- インターネット接続を確認します
-
購入が完了しない:
- 公開鍵が正しいことを確認します
-
検証エラー:
- サーバーエンドポイントを確認します
- 購入トークンの有効性を確認します
ベストプラクティス
- 購入は常にサーバー側で検証します
- 適切なエラー処理を実装します
- サンドボックス環境で十分にテストします
FAQ
推奨される Unity バージョンは何ですか?
弊社の Unity ラッパーは JDK-11 をサポートしているため、2022.2 より上の任意の Unity バージョンが適しています。
Unity 統合の参考にできる例はありますか?
はい、Unity Billing SDK を統合している Aptoide Unity Diceroll があります。既存の疑問点を解消するためにご利用ください。
Native Billing SDK に基づく統合プロセスについて、より詳しい情報を得るにはどうすればよいですか?
Native Billing SDK のフローとプロセスについて詳しい情報を得るには、Native Billing SDK 統合ガイドをご確認ください。統合を成功させるために必要なすべての情報が含まれています。それに従うことで、AptoideBillingSDKManager.cs クラスのミラーリングされたメソッドを呼び出し、同じ結果を得ることができます。
まだ AppCoins Unity Billing SDK のレガシーバージョンを使用しています。レガシードキュメントはどこにありますか?
まだレガシーの AppCoins Unity Billing SDK を使用している場合は、機能とセキュリティパッチの面で最新の状態を保つため、新しい Aptoide Unity Billing SDK への移行を強くお勧めします。とはいえ、レガシードキュメントはこちらで引き続き利用できます。