# IAP バージョン 4 からバージョン 5 へのアップグレード

> このガイドに従って、Unityアプリ内課金バージョン4からバージョン5に移行します。

アプリ内課金(IAP)バージョン5(v5)では、接続と購入フローの各ステップをより適切にコントロールできるように、アーキテクチャが大幅に改善されました。移行には既存の IAP 実装を大幅に更新する必要がありますが、このガイドでは遷移に役立つステップバイステップの手順とコードサンプルを提供します。

> **Note:**
>
> SDK v5.4から、Unity Iapは開発者データを[開発者データ フレームワーク](/cloud/developer-data.md.md)の一部として処理します。そのため、[UnityConsent](https://docs.unity3d.com/ScriptReference/UnityConsent.ConsentState.html)モジュールを使用して[ユーザー同意を管理](/cloud/developer-data/user-consent.md.md)する必要があります。

> **Note:**
>
> IAPバージョン5.3.0から、IAP AIスキルにアクセスして、プロジェクトをバージョン4からバージョン5に移行するヘルプを提供できるようになりました。
>
> **Project Settings** > **Services** > **アプリ内課金** の下部で、以下のオプションのいずれかを選択します。
>
> * **スキル フォルダーを開く**:スキル ファイルを含むフォルダーを開きます。このオプションを使用して、IAP AIスキルを任意のAIツールにコピーまたはインストールします。
> * **Cloud コードにインストール**：クロード コードに直接スキルを追加します。これにより、`in-app-purchases` という名前のスキルがインストールされます。
>
> スキルをインストールしたら、AIツールから`in-app-purchases`を実行し、プロジェクトをバージョン4からバージョン5に移行するようプロンプトを表示します。

## 変更点の概要##overview-of-changes

以下の表は、IAP v5の変更点と、実装の更新が必要な点をまとめたものです。アップグレードのメリットの詳細については、Unityアプリ内課金(IAP)v5.xにアップグレードする[理由](https://support.unity.com/hc/articles/47757890052372-Why-you-should-upgrade-to-Unity-In-App-Purchasing-IAP-v5-x)に関するサポート記事を参照してください。

| 変更                                                                                                        | 必要な更新                                                                                                                         |
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| 初期化は、ストア接続、プロダクトフェッチ、購入フェッチの別々の非同期呼び出しに分割されます。                                                            | [Replace UnityPurchasing.Initialize()](./upgrade-to-iap-v5.md#replace-unitypurchasing.initialize\(\))                         |
| `ConfigurationBuilder`は削除されます。製品は、`CatalogProvider`または`ProductDefinitions`のリストによって定義されるようになりました。          | [Replace ConfigurationBuilder](./upgrade-to-iap-v5.md#replace-configurationbuilder)                                           |
| ストア拡張はストア拡張サービスに置き換えられます。                                                                                 | [Replace ConfigurationBuilder](./upgrade-to-iap-v5.md#replace-configurationbuilder)                                           |
| `IDetailedStoreListener` と `IStoreListener` は、`StoreController` と個々のストアサービスの任意のイベントハンドラに置き換えられます。         | [Replace IDetailedStoreListener and IStoreListener](./upgrade-to-iap-v5.md#replace-idetailedstorelistener-and-istorelistener) |
| `IStoreController`は`StoreController`に置き換えられ、`UnityIAPServices.StoreController()`経由でいつでもフェッチできます。          | [Replace IStoreController](./upgrade-to-iap-v5.md#replace-istorecontroller)                                                   |
| `ProcessPurchase` コールバックは、新規購入の場合は `OnPurchasePending`、復元された購入の場合は `OnPurchasesFetched` に置き換えられます。        | [購入フローの置き換え](./upgrade-to-iap-v5.md#replace-purchase-flow)                                                                    |
| `RestoreTransactions` は Store Extensions から `StoreController` and `PurchaseService` に移行しました。              | [復元トランザクション](./upgrade-to-iap-v5.md#restore-transactions)                                                                     |
| エンタイトルメントチェックは、`FetchPurchases`または`CheckEntitlement`を使用したイベントベースになりました。                                   | [エンタイトルメントチェックの置き換え](./upgrade-to-iap-v5.md#replace-entitlement-checks)                                                       |
| Apple App Store レシート検証は非推奨です。google playレシート検証で`Order.Info.Receipt`が使用されるようになりました。                        | [更新レシート検証](./upgrade-to-iap-v5.md#receipt-validation)                                                                         |
| `CodelessIAPStoreListener.initializationComplete` は `CodelessIAPStoreListener.IsInitialized()` に置き換えられます。 | [Codeless IAP 更新](./upgrade-to-iap-v5.md#codeless-iap-specifics)                                                              |

## Replace UnityPurchasing.Initialize()##replace-unitypurchasing.initialize()

IAP v5 では、Unity Iap パッケージをより柔軟に初期化できます。ストアへの接続、製品のフェッチ、購入のハンドルは、個別に非同期で行うことができます。このアプローチは、初期化の成功を妨げる可能性のある問題を特定して解決するのにヘルプます。

> **Note:**
>
> バージョン 4 以前では、Unity Iap パッケージはストアに接続し、プロダクトをフェッチし、パッケージの初期化時に購入を同期してフェッチします。パッケージは、これらのすべての手順が完了した後にのみ、初期化の成功を報告します。

`UnityPurchasing.Initialize()` の動作を置き換える手順は、次のとおりです。

1. 呼び出しと待機の`StoreController.Connect()`:
   * この呼び出しが完了すると、IAP が現在のアプリストアに接続されます。
2. 以下を呼び出します。
   * `CatalogProvider` のインスタンスに製品を追加できます。これは、`ConfigurationBuilder` に製品を追加するのと似ています。`ProductDefinitions`のリストを `ProductService.FetchProducts()` または `StoreController.FetchProducts()` に渡すこともできます。詳細については、新しい初期化[プロセスのコード](./upgrade-to-iap-v5.md#code-sample-of-new-initialization-process-using-storecontroller)サンプル を参照してください。
   * `OnProductsFetched` イベントハンドラーは、リクエストが正常に完了したときに呼び出されます。指定したプロダクトを取得できなかった場合は、`OnProductsFetchFailed`が呼び出されます。
3. プロダクトが正常にフェッチされた後に`FetchPurchases()`を呼び出します。
   * `OnPurchasesFetched` イベントハンドラーは、リクエストが正常に完了したときに呼び出されます。`Orders` オブジェクトには、アプリストアから返されたすべてのディファード、保留中、および完了済みオーダーのフィルタ可能なコレクションが含まれます。失敗すると、`OnPurchasesFetchFailed` が実行されます。

> **Note:**
>
> デフォルトでは、`FetchPurchases` を呼び出すと、セッションでまだ処理されていない保留中の購入の`OnPurchasePending`が呼び出されます。この動作は`StoreController.ProcessPendingOrdersOnPurchasesFetched(false)`で無効にできます。

### StoreController を使用した新しい初期化プロセスのコードサンプル##code-sample-of-new-initialization-process-using-storecontroller

以下の例は、IAP v5 の初期化方法を示しています。

```cs
StoreController m_StoreController;  
  
async void InitializeIAP()  
{  
    m_StoreController = UnityIAPServices.StoreController();  
  
    m_StoreController.OnPurchasePending += OnPurchasePending;  
  
    await m_StoreController.Connect();  
  
    m_StoreController.OnProductsFetched += OnProductsFetched;
    m_StoreController.OnPurchasesFetched += OnPurchasesFetched;  
  
    var initialProductsToFetch = new List<ProductDefinition>  
    {  
        new(goldProductId, ProductType.Consumable), 
        new(diamondProductId, ProductType.Consumable)  
    };  
  
    m_StoreController.FetchProducts(initialProductsToFetch);  
}
void OnProductsFetched(List<Product> products)  
{  
    // Handle fetched products  
    m_StoreController.FetchPurchases();  
}  
void OnPurchasesFetched(Orders orders) {  
   // Process purchases, for example, check for entitlements from completed orders  
}
```

## IDetailedStoreListener と IStoreListener を置き換える##replace-idetailedstorelistener-and-istorelistener

IAP v5では、購入または初期化の処理に`IDetailedStoreListener`または`IStoreListener`の実装が不要になりました。イベントハンドラーを`StoreController`、または個々の`ProductService`、`PurchaseService`、`StoreService` サービスにアタッチすることで、`IDetailedStoreListener` によって処理されていた機能を置き換えます。

イベントハンドラを `StoreController` に追加する例については、新しい初期化[プロセスのコード](./upgrade-to-iap-v5.md#code-sample-of-new-initialization-process-using-storecontroller)サンプル を参照してください。

> **Note:**
>
> イベントハンドラはいつでも追加または削除できますが、特定のメソッドを呼び出す前に特定のイベントハンドラを使用することをお勧めします。推奨されるイベントハンドラーがアタッチされる前に機能を呼び出しと、Unity Iap は警告を表示します。

移行するには、各`IDetailedStoreListener`機能を以下に置き換えます。

| 関数                                                                             | IAP v5への置き換え                                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OnPurchaseFailed(Product, PurchaseFailureDescription)`                        | `StoreController.OnPurchaseFailed(FailedOrder)`または`PurchaseService.OnPurchaseFailed(FailedOrder)`へのイベントハンドラーの追加                                                                                                                                                                   |
| `OnInitialized(IStoreController controller, IExtensionProvider extensions)`    | `StoreController.Connect()`または`StoreService.Connect()`が完了した後に実行を継続します。                                                                                                                                                                                                            |
| `OnInitializeFailed(InitializationFailureReason error)`                        | `StoreService.OnStoreDisconnected(StoreConnectionFailureDescription)`、`ProductService.OnProductsFetchFailed(ProductFetchFailed)`、および `PurchaseService.OnPurchasesFetchFailed(PurchasesFetchFailureDescription)` にイベントハンドラを追加します。これらのイベントハンドラは、`StoreController` を使用して追加することもできます。 |
| `OnInitializeFailed(InitializationFailureReason error, string message = null)` | `StoreController.OnStoreDisconnected(StoreConnectionFailureDescription)`または`StoreService.OnStoreDisconnected(StoreConnectionFailureDescription)`へのイベントハンドラーの追加                                                                                                                    |
| `PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)`             | `StoreController.OnPurchasePending(PendingOrder)`または`PurchaseService.OnPurchasePending(PendingOrder)`へのイベントハンドラーの追加                                                                                                                                                               |

## ConfigurationBuilder を置き換える##replace-configurationbuilder

以下の`ConfigurationBuilder`関数を以下の動作に置き換えます。

| 関数                                                | IAP v5への置き換え                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ConfigurationBuilder.AddProduct()`               | `ConfigurationBuilder.AddProduct()` を呼び出す代わりに、`CatalogProvider.AddProduct()` または `CatalogProvider.AddProducts()` を使用して`CatalogProvider` のインスタンスに製品を追加できます。プロダクトを取得するには、`CatalogProvider.FetchProducts` を呼び出し、`UnityIAPServices.DefaultProduct().FetchProductsWithNoRetries` などのコールバックを渡します。製品と`CatalogProvider`の詳細については、[エディターでのカタログ](./create-catalog-in-editor.md)の作成 を参照してください。`ProductDefinitions` を作成し、`StoreController` または `ProductService` の `FetchProducts()` 呼び出しに直接渡すこともできます。 |
| `IAppleConfiguration` および `IGoogleConfiguration`。 | `IAppleConfiguration` と `IGoogleConfiguration` の機能は、`AppleStoreExtendedService` などの Extended Store Services にあります。                                                                                                                                                                                                                                                                                                                                                                       |

> **Note:**
>
> サポートされていないプラットフォームでストア拡張サービスを取得する場合 (例えば、エディターや Android での`AppleStoreExtendedService`の取得)、サービスは null になります。イベントハンドラーの追加や設定の変更を行う前に、サービスが null でないことを必ず確認してください。

## IStoreController を置き換える##replace-istorecontroller

`IStoreController` を `StoreController` に置き換えます。 `StoreController` は `IStoreListener` に類似した IAP 機能を提供しますが、いつでも `UnityIAPServices.StoreController()` を呼び出して`StoreController`をフェッチできます。

これらの `IStoreController` のメソッドを `StoreController` の以下のメソッドに置き換えます。

| IStoreController          | StoreController                  | ノート                                                                          |
| ------------------------- | -------------------------------- | ---------------------------------------------------------------------------- |
| `products`                | `GetProducts`                    | `GetProducts` は製品のリストを返します。                                                  |
| `InitiatePurchase`        | `Purchase` または `PurchaseProduct` | `Purchase` 関数に `payload` 引数はありません。開発者ペイロードのサポートは、Google Billing v3 で廃止されました。 |
| `FetchAdditionalProducts` | `FetchProducts`                  | `FetchProducts` は初期プロダクトの取得にも使用されます。                                         |
| `ConfirmPendingPurchase`  | `ConfirmPurchase`                | `ConfirmPurchase`には`PendingOrder`が必要です。                                      |

## 購入フローの置き換え##replace-purchase-flow

購入を開始するには、`Purchase()`または`StoreController`または`PurchaseService``PurchaseProduct()`で呼び出します。保留中の購入を確認するには、確認したい`PendingOrder`で`StoreController.ConfirmPurchase(PendingOrder)`または`PurchaseService.ConfirmPurchase(PendingOrder)`を呼び出します。購入フローの詳細については、[購入](./purchases.md) を参照してください。

IAP v4 以前では、`ProcessPurchase` メソッドは自動的にすべての購入イベントを処理していました。IAP v5では、購入処理に以下のコールバックが使用されます。

* `OnPurchasePending`: 新規購入のために呼び出されます。
* `OnPurchasesFetched`: 復元された購入のために呼び出されます。

これらの新しいコールバック内で既存の`ProcessPurchase`ロジックを使用します。

## 復元トランザクション##restore-transactions

`RestoreTransactions` は Store Extensions から `StoreController` and `PurchaseService` に移行しました。

確定した購入は、`FetchPurchases()` を呼び出すか、`CheckEntitlement()` を呼び出すと自動的に復元されます。

## エンタイトルメントチェックの置き換え##replace-entitlement-checks

製品に対するユーザーのエンタイトルメントを確認するには、IAP はイベントに依存します。`FetchPurchases` を呼び出して `OnPurchasesFetched` イベントを処理することで、フェッチされたすべての製品のエンタイトルメントを確認できます。1 つの製品のエンタイトルメントを確認するには、`CheckEntitlement` を呼び出し、`OnCheckEntitlement` イベントをハンドルします。

## 追加プロダクトの取得##fetch-additional-products

`StoreController`または`ProductService`のいずれかで、追加製品のリストを使用して`FetchProducts`を呼び出し、`OnPurchasesFetched`イベントハンドラーをトリガーします。または、`CatalogProvider` インスタンスで `FetchProducts` を呼び出すこともできます。`ProductService` 経由で製品を取得する例については、新しい初期化[プロセスのコード](./upgrade-to-iap-v5.md#code-sample-of-new-initialization-process-using-storecontroller)サンプルを参照してください。`CatalogProvider` で`FetchProducts`を呼び出す例については、[エディターでのカタログ](./create-catalog-in-editor.md)の作成 を参照してください。

## レシート検証##receipt-validation

Apple App Store レシートのレシート検証は非推奨になりました。レシート検証は Google Play ストアでのみサポートされます。レシートをフェッチするには、`Order`ではなく`Product.Receipt`から`Order.Info.Receipt`を使用します。

> **Note:**
>
> StoreKit 1 のレシートからできるだけ早く [StoreKit 2 の jwsRepresentation](https://developer.apple.com/documentation/storekit/verificationresult/jwsrepresentation-21vgo) に移行することで、信頼性、セキュリティ、パフォーマンスが向上し、最終的にはユーザー体験が向上します。

> **Note:**
>
> サーバー側の検証に [OrderInfo.Apple.jwsRepresentation](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.IAppleOrderInfo.html#UnityEngine_Purchasing_IAppleOrderInfo_jwsRepresentation) を使用します。

## Codeless IAP の詳細##codeless-iap-specifics

以下の `CodelessIAPStoreListener` 機能を以下に置き換えます。

| `function`CodelessIAPStoreListener\`              | IAP v5への置き換え                               |
| ------------------------------------------------- | ------------------------------------------ |
| `CodelessIAPStoreListener.initializationComplete` | `CodelessIAPStoreListener.IsInitialized()` |
