拡張機能と設定
拡張機能
アプリケーションのレシートの読み取り
アプリケーションのレシート は、デバイスのローカルストレージに保存され、以下のようにして読み取ることができます。
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
string receipt = builder.Configure<IAppleConfiguration>().appReceipt;
支払い制限の確認
アプリ内課金がデバイスの設定で制限されている場合があります。これは、以下のようにして確認できます。
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
bool canMakePayments = builder.Configure<IAppleConfiguration>().canMakePayments;
トランザクションの復元
Apple のプラットフォームでは、ユーザーが以前のトランザクションを復元するにはパスワードを入力する必要があります。そのため、これを行うためのボタンをアプリケーションに用意する必要があります。復元プロセス中に、ユーザーがすでに所有しているアイテムに対して IStoreListener
の ProcessPurchase
メソッドが呼び出されます。
/// <summary>
/// OnInitialized の IStoreListener 実装
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
extensions.GetExtension<IAppleExtensions> ().RestoreTransactions (result => {
if (result) {
// これは、何かが復元されたということではなく、
// 単に復元プロセスが成功したことを示しています。
} else {
// 復元が失敗しました。
}
});
}
アプリケーションのレシートの更新
Apple はサーバーから新しいアプリケーションのレシートを取得するメカニズム (SKReceiptRefreshRequest) を提供しています。これは通常、ローカルストレージに現在レシートがキャッシュされていない場合に使用されます。
このメカニズムでは、ユーザーがパスワードの入力を求められることに注意してください。
Unity IAP ではこのメソッドを以下のように使用します。
/// <summary>
/// OnInitialized の IStoreListener 実装
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
extensions.GetExtension<IAppleExtensions> ().RefreshAppReceipt (receipt => {
// リクエストが成功した場合は、このハンドラーが呼び出されます。
// レシートは、最新のアプリケーションのレシートです。
Console.WriteLine(receipt);
},
() => {
// リクエストが失敗した場合は、このハンドラーが呼び出されます。
// 例えば、ネットワークが利用できない場合や、ユーザーが
// 入力したパスワードが間違っている場合があります。
});
}
承認と購入のリクエスト
iOS 8 には、承認と購入のリクエスト (Ask-to-Buy) という新しいペアレンタルコントロール機能が導入されています。
承認と購入のリクエストを使用した購入では、保護者の承認が必要です。このとき、Unity IAP からアプリケーションに以下の通知が送信されます。
/// Unity IAP の初期化が終了すると、以下が呼び出されます。
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
extensions.GetExtension<IAppleExtensions>().RegisterPurchaseDeferredListener(product => {
Console.WriteLine(product.definition.id);
});
}
App Store の Sandbox 環境で "承認と購入のリクエスト" シミュレーションを有効にする
以下のサンプルクラスは、App Store の Sandbox 環境で "承認と購入のリクエスト (Ask-to-Buy)" シミュレーションを有効にするために IAppleExtensions
にアクセスする方法を示しています。
using UnityEngine;
using UnityEngine.Purchasing;
public class AppleSimulateAskToBuy : MonoBehaviour {
public void SetSimulateAskToBuy(bool shouldSimulateAskToBuy) {
if (Application.platform == RuntimePlatform.IPhonePlayer) {
IAppleExtensions extensions = IAPButton.IAPButtonStoreManager.Instance.ExtensionProvider.GetExtension<IAppleExtensions>();
extensions.simulateAskToBuy = shouldSimulateAskToBuy;
}
}
}
購入が承認または却下されると、ストアの通常の ProcessPurchase
または OnPurchaseFailed
のリスナーメソッドが呼び出されます。
トランザクションレシート
アプリケーションのレシートに承認と購入のリクエスト (Ask-to-Buy) による消費型の購入が表示されない場合は、そのレシートを使用して購入を検証することができません。ただし、iOS には承認と購入のリクエストを含むすべての購入が含まれるトランザクションレシートが用意されています。 IAppleExtensions
を使用して、特定の Product
の最新のトランザクションレシートの文字列にアクセスできます。
ノート: トランザクションレシートは、Mac ビルドでは利用できません。Mac ビルドでトランザクションレシートをリクエストすると、空の文字列が返されます。
using System;
using UnityEngine;
using UnityEngine.Purchasing;
public class AskToBuy : MonoBehaviour, IStoreListener
{
// Unity IAP オブジェクト
private IStoreController m_Controller;
private IAppleExtensions m_AppleExtensions;
public AskToBuy ()
{
var builder = ConfigurationBuilder.Instance (StandardPurchasingModule.Instance ());
builder.AddProduct ("100_gold_coins", ProductType.Consumable, new IDs {
{ "100_gold_coins_google", GooglePlay.Name },
{ "100_gold_coins_mac", MacAppStore.Name }
});
UnityPurchasing.Initialize (this, builder);
}
/// <summary>
/// Unity IAP の初期化が終了すると以下が呼び出されます。
/// </summary>
public void OnInitialized (IStoreController controller, IExtensionProvider extensions)
{
m_Controller = controller;
m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();
// Apple のプラットフォームでは、Apple の承認と購入のリクエスト機能に起因する保留中の購入を処理する必要があります。
// Apple 以外のプラットフォームでは、この機能による影響はなく、OnDeferred が呼び出されることはありません。
m_AppleExtensions.RegisterPurchaseDeferredListener (OnDeferred);
}
/// <summary>
/// 購入が完了すると以下が呼び出されます
/// </summary>
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
{
if (Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.tvOS) {
string transactionReceipt = m_AppleExtensions.GetTransactionReceiptForProduct (e.purchasedProduct);
Console.WriteLine (transactionReceipt);
// 検証のために、トランザクションレシートをサーバーに送信します
}
return PurchaseProcessingResult.Complete;
}
/// <summary>
/// Unity IAP に解決できない初期化エラーが発生すると呼び出されます。
///
/// インターネットが利用できない場合、これは呼び出されません。Unity IAP は
/// インターネットが利用可能になるまで、初期化を試みます。
/// </summary>
public void OnInitializeFailed (InitializationFailureReason error)
{
}
/// <summary>
/// 購入が失敗すると呼び出されます
/// </summary>
public void OnPurchaseFailed (Product i, PurchaseFailureReason p)
{
}
/// <summary>
/// iOS 固有
/// これは Apple の "承認と購入のリクエスト" 機能の一環として
/// 未成年が購入をリクエストし、保護者の承認が必要な場合に、
/// 呼び出されます。
///
/// 購入が承認または却下されると、通常の購入イベントが
/// 行われます。
/// </summary>
/// <param name="item">Item.</param>
private void OnDeferred (Product item)
{
Debug.Log ("Purchase deferred: " + item.definition.id);
}
}
アプリケーションのレシートとは異なり、トランザクションレシートをローカルで検証することはできません。代わりに、検証のためにレシート文字列をリモートサーバーに送信する必要があります。すでにリモートサーバーを使用してアプリケーションのレシートを検証している場合は、トランザクションレシートを同じ Apple エンドポイントに送信して JSON 応答を受信します。
JSON 応答の例:
{
"receipt": {
"original_purchase_date_pst": "2017-11-15 15:25:20 America/Los_Angeles",
"purchase_date_ms": "1510788320209",
"unique_identifier": "0ea7808637555b2c633eb07aa1cb0894c821a6f9",
"original_transaction_id": "1000000352597239",
"bvrs": "0",
"transaction_id": "1000000352597239",
"quantity": "1",
"unique_vendor_identifier": "01B57C2E-9E91-42FF-9B0D-4983175D6694",
"item_id": "1141751870",
"original_purchase_date": "2017-11-15 23:25:20 Etc/GMT",
"product_id": "100.gold.coins",
"purchase_date": "2017-11-15 23:25:20 Etc/GMT",
"is_trial_period": "false",
"purchase_date_pst": "2017-11-15 15:25:20 America/Los_Angeles",
"bid": "com.unity3d.unityiap.demo",
"original_purchase_date_ms": "1510788320209"
},
"status": 0
}
Apple のプロモーション購入のインターセプト
Apple は、開発者がアプリケーションのプロダクトページを通じて ゲーム内課金 を宣伝することを許可しています。従来のアプリ内課金とは異なり、Apple のプロモーション対象アイテムの購入は、iOS および tvOS の App Store から直接開始されます。その後、App Store がアプリケーションを起動してトランザクションを完了させるか、アプリケーションがインストールされていない場合はユーザーにアプリケーションのダウンロードを促します。
IAppleConfiguration
の SetApplePromotionalPurchaseInterceptor
のコールバックメソッドは、プロモーション購入をインターセプトします。Apple に購入を送信する前に、このコールバックを使用して、ペアレンタルゲートの実装や分析イベントの送信などの機能を実行できます。このコールバックではユーザーが購入しようとした Product
を使用します。プロモーション購入を続行するには、 IAppleExtensions.ContinuePromotionalPurchases()
を呼び出す必要があります。これにより待機中の支払いが開始されます。
コールバックを設定しない場合、プロモーション購入は即座に処理され、ProcessPurchase
と結果が呼び出されます。
ノート: 他のプラットフォームでこれらの API を呼び出しても効果はありません。
private IAppleExtensions m_AppleExtensions;
public void Awake() {
var module = StandardPurchasingModule.Instance();
var builder = ConfigurationBuilder.Instance(module);
// iOS および tvOS で、App Store から直接実行されるプロモーション購入を
// インターセプトできます。
// これは他のプラットフォームでは効果はありません。OnPromotionalPurchase が呼び出されることは
// ありません。
builder.Configure<IAppleConfiguration>().
SetApplePromotionalPurchaseInterceptorCallback(OnPromotionalPurchase);
Debug.Log("Setting Apple promotional purchase interceptor callback");
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions) {
m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
foreach (var item in controller.products.all) {
if (item.availableToPurchase) {
// これらすべてのプロダクトがユーザーの App Store に表示されるように設定します。
m_AppleExtensions.SetStorePromotionVisibility(item, AppleStorePromotionVisibility.Show);
}
}
}
private void OnPromotionalPurchase(Product item) {
Debug.Log("Attempted promotional purchase: " + item.definition.id);
// プロモーション購入が検出されました。
// このイベントを次の方法で処理します (例: ペアレンタルゲートを実装する)。
// 今回はデモ目的のために、5 秒間待機してから
// 購入を続行します。
StartCoroutine(ContinuePromotionalPurchases());
}
private IEnumerator ContinuePromotionalPurchases() {
Debug.Log("Continuing promotional purchases in 5 seconds");
yield return new WaitForSeconds(5);
Debug.Log("Continuing promotional purchases now");
m_AppleExtensions.ContinuePromotionalPurchases (); // iOS および tvOS のみ
}