アプリストアのレシート はデバイスのローカルストレージに保管されており、以下のようにして読むことができます。
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 はサーバーから App Store の新しいレシートを取得する方法 SKReceiptRefreshRequest を提供しています。これは通常、ローカルストレージに現在レシートがキャッシュされていない場合に使用されます。
この方法にはパスワードが必要だということに気を付けてください。
Unity IAP では以下のようにこのメソッドを使用します。
/// <summary>
/// OnInitialized の IStoreListener 実装 
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions> ().RefreshAppReceipt (receipt => {
        // リクエストが成功したら、このハンドラーが呼び出されます
        // レシートは最新の App Store レシート
        Console.WriteLine(receipt);
    },
    () => {
        // リクエストが失敗したら、このハンドラーが呼び出されます。
        // 例えば、ネットワークが使用不可であったり、
        // ユーザーが誤ったパスワードを入力した場合など。
    });
}
iOS 8 からペアレンタルコントロールに Ask to Buy (承認と購入のリクエスト) と呼ばれる新しい機能が追加されました。
Ask to Buy を使った購入では、保護者の承認を待機します。このとき、Unity IAP は以下のようにアプリケーションに通知を送信します。
/// Unity IAP の初期化が終了すると、以下が呼び出されます。
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    extensions.GetExtension<IAppleExtensions>().RegisterPurchaseDeferredListener(product => {
        Console.WriteLine(product.definition.id);
    });
}
下のサンプルは Sandbox の App Store で 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は、Ask to Buy を含むすべての購入のトランザクションレシートを提供します。IAppleExtensions を使用して、Product(プロダクト) の最新のトランザクションレシートの文字列にアクセスします。 
注意: トランザクションレシートは Mac ビルドには使用できません。Mac ビルドでトランザクションレシートを要求すると、空の文字列が返されます。
# if UNITY_PURCHASING
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 の Ask to Buy 機能を使った待機後の購入を処理するに対応する必要があります
        // 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 の Ask to Buy 機能の一部として
    /// 呼び出されます
    ///
    ///購入が承認か拒否をされると、
    /// 通常のイベントが発生します
    /// </summary>
    /// <param name="item">item</param>
    private void OnDeferred (Product item)
    {
        Debug.Log ("Purchase deferred: " + item.definition.id);
    }
}
# endif // UNITY_PURCHASING
アプリストアのレシートとは異なり、トランザクションレシートをローカルで検証することはできません。代わりに、検証のためにレシートの文字列をリモートサーバーに送信する必要があります。 すでにリモートサーバーを使用してアプリストアのレシートを検証している場合は、トランザクションレシートを同じ 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 のプロモーション購入は iOS および tvOS の App Store から直接開始されます。その後、App Store はアプリケーションを起動してトランザクションを完了するか、アプリケーションがインストールされていない場合はそれをダウンロードするようにユーザーに促します。
IAppleConfiguration と SetApplePromotionalPurchaseInterceptorCallback メソッドは、Apple のプロモーション購入を遮ります。購入を 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 から直接行われるプロモーション購入を
        // 遮ることができます。
        // Apple 以外のプラットフォームでは、 何も効力がありません。
        // 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 のみ
}
Apple ストアでテストをするには ITunes Connect でテストアカウントを作成し、そのテストアカウントで iTunes に接続しなければいけません。
iOS デバイスやラップトップで App Store からサインアウトしてアプリを起動すると、課金やリストアを行うときにログインするよう求められます。
NoProductsAvailable が原因で初期化に失敗した時は、以下の項目を確認してください。
Unity の Build Settings > Player Settings で Mac の Mac App Store Validation にチェックを入れておく必要があります。
アプリケーションをビルドしたら、バンドル ID とバージョン文字列で info.plist ファイルを更新します。.app ファイル上で右クリックし、show package contents を選択し、info.plist ファイルを探し、CFBundleIdentifier 文字列をアプリケーションのバンドル ID に更新します。
その後、アプリケーションに署名をし、パッケージ化し、インストールします。そのための操作は Mac OSX 上のターミナルで行います。
codesign -f --deep -s "3rd Party Mac Developer Application: " your.app/Contents/Plugins/unitypurchasing.bundle
codesign -f --deep -s "3rd Party Mac Developer Application: " your.app
productbuild --component your.app /Applications --sign "3rd Party Mac Developer Installer: " your.pkg
バンドルに署名するには、Contents.meta ファイルが存在する場合、まずこれを削除する必要があります。your.app/Contents/Plugins/unitypurchasing.bundle/Contents.meta
正しくパッケージをインストールするには、新しく作成したパッケージを実行する前にパッケージ化していない .app ファイルを削除しておく必要があります。
そして、アプリケーションフォルダーからアプリを起動します。初回は iTunes アカウントの詳細を入力するよう求められるので、iTunes Connect のテストアカウントでログインします。これでサンドボックス環境でテスト購入を行うことができます。