Android アプリ内課金 (IAP) ストアにおける、ストア間を横断してプロダクトをインストールする場合の問題
ユニバーサル Windows プラットフォーム

iOS & Mac App Store

Extended functionality

アプリ レシートを読む

アプリ レシートはデバイスのローカルに保管され、以下のようにして読むことができます。

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 のプラットフォーム上では、前回のトランザクションを取得するには、リストアするかどうかのボタンを表示して、ユーザーからパスワードを入力してもらわなくてはなりません。トランザクションの復元中、IStoreListenerProcessPurchase は、ユーザーがすでに所有しているアイテムすべてに実行されます。

/// <summary>
/// OnInitialized の IStoreListener の実装
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    extensions.GetExtension<IAppleExtensions> ().RestoreTransactions (result => {
        if (result) {
            // 何かが復元されたというわけではありません
            // 単に復元のプロセスが成功したというだけです
        } else {
            // 復元が失敗しました

アプリ レシートのリフレッシュ

Apple provides a mechanism to fetch a new App Receipt from their servers, typically used when no receipt is currently cached in local storage; SKReceiptRefreshRequest.


このメソッドは、Unity IAP によって以下のように利用できます。

/// <summary>
/// Your IStoreListener implementation of OnInitialized.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    extensions.GetExtension<IAppleExtensions> ().RefreshAppReceipt (receipt => {
        // This handler is invoked if the request is successful.
        // Receipt will be the latest app receipt.
    () => {
        // This handler will be invoked if the request fails,
        // such as if the network is unavailable or the user
        // enters the wrong password.

Ask to Buy

iOS 8 introduced a new parental control feature called Ask to Buy.

Ask to Buy purchases defer for parent approval. When this occurs, Unity IAP sends your app a notification as follows:

/// This is called when Unity IAP has finished initialising.
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    extensions.GetExtension<IAppleExtensions>().RegisterPurchaseDeferredListener(product => {

When the purchase is approved or rejected, your store’s normal ProcessPurchase or OnPurchaseFailed listener methods are invoked.

Transaction Receipts

Sometimes consumable Ask to Buy purchases don’t show up in the App Receipt, in which case you cannot validate them using that receipt. However, iOS provides a Transaction Receipt that contains all purchases, including Ask to Buy. Access the most recent Transaction Receipt string for a given Product using IAppleExtensions.

Note: Transaction Receipts are not available for Mac builds. Requesting a Transaction Receipt on a Mac build results in an empty string.


using System;
using UnityEngine;
using UnityEngine.Purchasing;

public class AskToBuy : MonoBehaviour, IStoreListener
    // Unity IAP objects
    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>
    /// This will be called when Unity IAP has finished initialising.
    /// </summary>
    public void OnInitialized (IStoreController controller, IExtensionProvider extensions)
        m_Controller = controller;
        m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();

        // On Apple platforms we need to handle deferred purchases caused by Apple's Ask to Buy feature.
        // On non-Apple platforms this will have no effect; OnDeferred will never be called.
        m_AppleExtensions.RegisterPurchaseDeferredListener (OnDeferred);

    /// <summary>
    /// This will be called when a purchase completes.
    /// </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);
            // Send transaction receipt to server for validation
        return PurchaseProcessingResult.Complete;

    /// <summary>
    /// Called when Unity IAP encounters an unrecoverable initialization error.
    /// Note that this will not be called if Internet is unavailable; Unity IAP
    /// will attempt initialization until it becomes available.
    /// </summary>
    public void OnInitializeFailed (InitializationFailureReason error)

    /// <summary>
    /// Called when a purchase fails.
    /// </summary>
    public void OnPurchaseFailed (Product i, PurchaseFailureReason p)

    /// <summary>
    /// iOS Specific.
    /// This is called as part of Apple's 'Ask to buy' functionality,
    /// when a purchase is requested by a minor and referred to a parent
    /// for approval.
    /// When the purchase is approved or rejected, the normal purchase events
    /// will fire.
    /// </summary>
    /// <param name="item">Item.</param>
    private void OnDeferred (Product item)
        Debug.Log ("Purchase deferred: " +;


Unlike App Receipts, you cannot validate Transaction Receipts locally. Instead, you must send the receipt string to a remote server for validation. If you already use a remote server to validate App Receipts, send Transaction Receipts to the same Apple endpoint, to receive a JSON response.

Example JSON response:

    "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": "",
        "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

Intercepting Apple promotional purchases

Apple allows you to promote in-game purchases through your app’s product page. Unlike conventional in-app purchases, Apple promotional purchases initiate directly from the App Store on iOS and tvOS. The App Store then launches your app to complete the transaction, or prompts the user to download the app if it isn’t installed.

The IAppleConfiguration SetApplePromotionalPurchaseInterceptor callback method intercepts Apple promotional purchases. Use this callback to present parental gates, send analytics events, or perform other functions before sending the purchase to Apple. The callback uses the Product that the user attempted to purchase. You must call IAppleExtensions.ContinuePromotionalPurchases() to continue with the promotional purchase. This will initiate any queued-up payments.

If you do not set the callback, promotional purchases go through immediately and call ProcessPurchase with the result.

Note: Calling these APIs on other platforms has no effect.

private IAppleExtensions m_AppleExtensions;

public void Awake() {
    var module = StandardPurchasingModule.Instance();
    var builder = ConfigurationBuilder.Instance(module);
        // On iOS and tvOS we can intercept promotional purchases that come directly from
        // the App Store.
        // On other platforms this will have no effect; OnPromotionalPurchase will never be
        // called.
    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) {                
            // Set all these products to be visible in the user's App Store
            m_AppleExtensions.SetStorePromotionVisibility(item, AppleStorePromotionVisibility.Show);

private void OnPromotionalPurchase(Product item) {
    Debug.Log("Attempted promotional purchase: " +;
    // Promotional purchase has been detected. 
    // Handle this event by, e.g. presenting a parental gate.
    // Here, for demonstration purposes only, we will wait five seconds before continuing 
    // the purchase.

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 and tvOS only


Apple ストアでテストをするには ITunes Connect でテストアカウントを作成し、そのテストアカウントで iTunes に接続しなければいけません。

Sign out of the App Store on the iOS device or laptop, launch your application and you will be prompted to log in when you attempt either a purchase or to restore transactions.

NoProductsAvailable が原因で初期化に失敗したときは以下の内容を確認してください。

  • iTunes Connect で作成したプロダクト ID が Unity IAP のプロダクト ID と一致しているかどうか。
  • アプリ内課金の設定が iTunes Connect で有効になっているかどうか。
  • プロダクトが iTunes Connect で販売可能な状態になっているかどうか。
  • iTunes Connect で作成したプロダクトが購入可能になるまで数時間かかることがあります。
  • iTunes Connect の最新のデベロッパー契約に同意して、有効な振込先の情報を記入しているかどうか。

Mac App Store

Unity のビルド設定で Mac のスタンドアロン用に Mac App Store validation にチェックを入れておく必要があります。

アプリをビルドしたら、info.plist のバンドル ID とバージョン設定を更新する必要があります。.app ファイル上で右クリックして パッケージの内容を表示 を選択し、info.plist ファイルの CFBundleIdentifier の値をアプリのバンドル ID へと変更します。

そして署名をした後に、パッケージとアプリをインストールします。そのための操作は Mac OSX 上のターミナルで行います。

codesign -f --deep -s "3rd Party Mac Developer Application: "
codesign -f --deep -s "3rd Party Mac Developer Application: "
productbuild --component /Applications --sign "3rd Party Mac Developer Installer: " your.pkgstaller: " your.pkg`

To sign the bundle, you may first need to remove the Contents.meta file if it exists:

正しくパッケージをインストールするには、パッケージ化していない .app ファイルを削除しておく必要があります。

そして、アプリケーション フォルダーからアプリを起動します。初回は iTunes アカウントの詳細を入力するよう求められるので、iTunes Connect で作成したテストアカウントでログインします。これでテストアカウントがサンドボックス環境で課金を行うことができます。

  • 2018–25–01 編集レビュー を行ってパブリッシュされたページ
  • Ask to Buy, Transaction Receipts, and Intercepting Receipts added in 2017.3 NewIn20173
Android アプリ内課金 (IAP) ストアにおける、ストア間を横断してプロダクトをインストールする場合の問題
ユニバーサル Windows プラットフォーム