# Unity IAP 초기화

> Unity IAP 패키지를 초기화하고, 필수 설정을 구성하고, 지원되는 플랫폼 인앱 구매 처리를 시작하기 위한 설정을 검증하는 방법을 알아봅니다.

Unity IAP(인앱 구매)를 사용하기 전에 [IAP 패키지를 초기화합니다.](#initialize-in-app-purchasing)

> **Important:**
>
> [D2C(Direct-to-Consumer) 결제 제공업체 통합](./payment-providers/workflow.md)을 원하는 경우 몇 가지 차이가 있으므로 [시작 시퀀스를 처리하기 위한 서비스 초기화](./payment-providers/initialize-services.md)를 참조하십시오.

프로젝트에서 [Unity 애널리틱스](/analytics.md) 또는 [Unity Authentication](/authentication.md)을 사용하려면 IAP를 초기화하기 전에 먼저 UGS(Unity Gaming Services)를 초기화해야 합니다. 사용 방법은 아래의 [Unity Gaming Services 초기화](#initialize-unity-gaming-services) 섹션을 참조하십시오.

## Unity Gaming Services 초기화##initialize-unity-gaming-services

모든 Unity Gaming Services를 초기화하려면 `UnityServices.InitializeAsync()`를 호출합니다. 이 메서드는 초기화 진행 상황을 트래킹하는 데 사용할 수 있는 `Task`를 반환합니다.

자세한 내용은 [초기화 예시](/services/services-core-api.md#initialization-example)를 참고하십시오. 완전히 작동하는 샘플을 보려면 **06 Initialize Gaming Services** 샘플을 임포트합니다(**패키지 관리자** > **인앱 구매** > **샘플**).

자세한 내용은 [Services Core API](/services/services-core-api.md)를 참고하십시오.

## 인앱 구매 초기화##initialize-in-app-purchasing

### 필수 조건##prerequisites

구매할 제품의 [에디터 카탈로그 만들기](./create-catalog-in-editor.md)의 단계를 완료합니다.

### 초기화 단계##initialization-steps

초기화는 다음 단계로 구성됩니다.

1. 앱 스토어에 대한 `StoreController` 얻기.
2. 이벤트 리스너를 `StoreController`에 연결합니다.
3. 앱 스토어 연결합니다.
4. 앱 스토어 상품을 가져오는 경우
5. 앱 스토어 구매를 가져옵니다.

```cs
using System.Collections.Generic;
using UnityEngine.Purchasing;

public class MyIAPManager
{
    private StoreController m_StoreController;
    public MyIAPManager()
    {
        // Define products
        var catalogProvider = new CatalogProvider();
        catalogProvider.AddProduct("100_gold_coins", ProductType.Consumable,
            new StoreSpecificIds()
            {
                {"100_gold_coins_google", GooglePlay.Name},
                {"100_gold_coins_mac", MacAppStore.Name}
            });

        // Get StoreController
        m_StoreController = UnityIAPServices.StoreController();

        // Add event listeners
        m_StoreController.OnStoreDisconnected += OnStoreDisconnected;

        m_StoreController.OnProductsFetched += OnProductsFetched;
        m_StoreController.OnProductsFetchFailed += OnProductsFetchFailed;

        m_StoreController.OnPurchasesFetched += OnPurchasesFetched;
        m_StoreController.OnPurchasesFetchFailed += OnPurchasesFetchFailed;

        // Connect to store
        m_StoreController.Connect().ContinueWith(_ =>
        {
            // Fetch products from store
            catalogProvider.FetchProducts(
                list => m_StoreController.FetchProducts(list)
                );
        });
    }

    /// <summary>
    /// Invoked when connection is lost to the current store, or on a Connect() failure.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnStoreDisconnected(StoreConnectionFailureDescription 실패)
    {
    }

    /// <summary>
    /// Invoked with products that are successfully fetched.
    /// </summary>
    /// <param name="products">Products successfully returned from the app store.</param>
    private void OnProductsFetched(제품 목록<Product>)
    {
        // Fetch purchases for successfully retrieved products
        m_StoreController.FetchPurchases();
    }

    /// <summary>
    /// Invoked when an attempt to fetch products has failed or when a subset of products failed to be fetched.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnProductsFetchFailed(ProductFetchFailed 실패)
    {
    }

    /// <summary>
    /// Invoked when previous purchases are fetched.
    /// </summary>
    /// <param name="orders">All active pending, completed, and deferred orders for previously fetched products.</param>
    private void OnPurchasesFetched(정렬 주문)
    {
    }

    /// <summary>
    /// Invoked when an attempt to fetch previous purchases has failed.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnPurchasesFetchFailed(PurchasesFetchFailureDescription 실패)
    {
    }

    /// <summary>
    /// Invoked when a purchase needs to be processed and fulfilled.
    /// </summary>
    /// <param name="order">The order awaiting fulfillment.</param>
    private void OnPurchasePending(PendingOrder 순서)
    {
    }
}
```

#### StoreController 가져오기##get-a-storecontroller

`StoreController`는 인앱 구매 기능과의 상호 작용을 위한 주요 인터페이스입니다. [UnityIAPServices.StoreController](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.UnityIAPServices.html#UnityEngine_Purchasing_UnityIAPServices_StoreController_System_String_)를 호출하여 `StoreController`의 인스턴스를 가져올 수 있습니다. 스토어 이름이 제공된 경우 기본 스토어 컨트롤러 또는 요청된 특정 스토어 컨트롤러를 반환합니다.

#### StoreController에 이벤트 핸들러 연결##attach-event-handlers-to-the-storecontroller

스토어가 올바르게 작동하려면 다음 이벤트에 핸들러를 연결합니다.

* [OnStoreDisconnected](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnStoreDisconnected)
* [OnProductsFetched](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnProductsFetched)
* [OnProductsFetchFailed](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnProductsFetchFailed)
* [OnPurchasesFetched](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasesFetched)
* [OnPurchasesFetchFailed](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasesFetchFailed)
* [OnPurchasePending](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasePending)

프로젝트에 인앱 구매를 연동할 때 추가 핸들러를 구현해야 할 수 있습니다. `StoreController`를 통해 제공되는 모든 이벤트 목록은 [이벤트](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#events)를 참조하십시오.

#### 앱 스토어 연결##connect-to-your-app-store

앱 스토어에 연결하려면 [StoreController.Connect](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_Connect)를 호출합니다. 연결이 완료되거나 실패하면 반환된 `Task`가 해결됩니다. 연결에 실패하면 `OnStoreDisconnected` 이벤트가 호출됩니다. IAP 기능을 사용하려면 스토어에 연결해야 합니다.

#### 상품 페치##fetch-products

> **Note:**
>
> 제품을 가져오기 전에 제품을 정의합니다. 지침은 [에디터에서 카탈로그 생성](/iap/create-catalog-in-editor.md)을 참조하십시오.

제품을 구매할 수 있는지 확인하려면 [StoreController.FetchProducts](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_FetchProducts_System_Collections_Generic_List_UnityEngine_Purchasing_ProductDefinition__UnityEngine_Purchasing_IRetryPolicy_)에 문의하십시오. 성공하면 성공적으로 반환된 제품 목록과 함께 `OnProductsFetched` 이벤트가 호출됩니다. 실패 시 `OnProductsFetchFailed`가 호출됩니다.

구매는 성공적으로 반환된 제품에 대해서만 가져오거나 시작할 수 있습니다. 런타임 중에 `FetchProducts`에 여러 번 호출할 수 있지만, 이전 요청이 완료될 때까지 기다린 후 다시 `FetchProducts`에 호출해야 합니다.

Apple 앱 스토어를 사용하는 경우 `FetchProducts`가 완료된 후 처리되지 않은 주문에 대해 `OnPurchasePending`를 호출할 수 있습니다.

##### GetProducts(제품)##getproducts

[`GetProducts`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_GetProducts)와 `FetchProducts`는 교환할 수 없습니다. 초기화 중에 `FetchProducts`를 호출해야 합니다. `FetchProducts`는 호출될 때마다 `GetProducts`가 반환한 목록에 결과물을 추가합니다.

#### 구매 페치##fetch-purchases

[`StoreController.FetchPurchases`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_FetchPurchases)을 호출하여 플레이어의 현재 활성 주문을 요청합니다. 활성 주문에는 `PendingOrders`, `ConfirmedOrders`(활성 구독 및 활성 비소모품), `DeferredOrders` 등이 포함됩니다. 자세한 내용은 [구매](/iap/purchases.md)를 참고하십시오.

`FetchPurchases` 호출은 두 개의 이벤트 핸들러 중 하나인 `OnPurchasesFetched`를 트리거합니다. 이 핸들러는 스토어 또는 `OnPurchasesFetchFailed`에서 반환된 모든 보류 중인 주문, 확인 및 디퍼드 주문이 포함된 `Orders` 객체와 함께 호출되며, 실패 시 호출됩니다.
Google Play를 사용하는 경우 처리되지 않은 구매에 대해 `OnPurchasePending` 이벤트가 호출됩니다.

인앱 구매 기능을 사용하려면 반드시 필요하지는 않습니다. 하지만 예기치 않은 동작이 발생할 수 있으므로 새 구매를 시작하기 전에 기존 구매를 가져와서 처리하는 것이 좋습니다.

런타임 중에 제품을 추가로 가져오면 구매를 다시 가져와야 합니다.

##### 오프라인 구매 페치##fetch-purchases-offline

Apple의 StoreKit 2와 같은 일부 플랫폼 라이브러리는 제품 데이터를 캐싱하지 않고도 오프라인 액세스 권한을 기기에 캐싱합니다. 이 접근 방식은 권장되지 않지만 `OnProductsFetchFailed` 콜백 후에도 `FetchPurchases`를 호출할 수 있습니다. 이 경우, `FetchPurchases`는 구매 정보를 반환하지만, 연결된 제품은 [`ProductType.Unknown`](https://docs.unity3d.com/Packages/com.unity.purchasing@5.2/api/UnityEngine.Purchasing.ProductType.html)의 `type`를 가집니다. 또한 `ProductDefinition.id` 및 `ProductDefinition.storeSpecificId` 모두 스토어별 식별자로 설정됩니다.

> **Note:**
>
> StoreKit 1에는 적용되지 않습니다. StoreKit 1은 디바이스에 영수증을 캐시하지만 패키지에는 가져온 제품 데이터가 필요하여 영수증 데이터를 파싱합니다. 제품 페치가 실패하면 `FetchPurchases`는 구매 정보를 반환하지 않습니다.

##### GetPurchases(구매)##getpurchases

[`GetPurchases`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_GetPurchases)와 `FetchPurchases`는 교환할 수 없습니다. 초기화 중에 `FetchPurchases`를 호출해야 합니다. `GetProducts` 및 `FetchProducts`와 달리, `FetchPurchases`는 `GetPurchases`가 반환한 목록을 채우지 않고 덮어씁니다. 그렇지 않으면 패키지는 이벤트의 주문 데이터를 기반으로 스토어와 최대한 동기화된 상태로 유지합니다.

### 코드리스 IAP 자동 초기화##automatically-initialize-codeless-iap

코드리스 IAP 설정 방법에 대한 지침은 [코드리스 IAP 설정](/iap/codeless-iap.md#set-up-codeless-iap)을 참조하십시오.

> **Note:**
>
> 스크립트에서 수동으로 초기화하는 경우에는 자동 초기화를 활성화해서는 안 됩니다. 이렇게 하면 오류가 발생할 수 있습니다.

### 코드리스 IAP를 위한 자동 Unity 게임 서비스 초기화##automatic-unity-game-services-initialization-for-codeless-iap

코드리스 IAP를 사용하는 경우 **IAP Catalog** 창 하단의 **Automatically initialize Unity Gaming Services** 체크박스를 선택하여 Unity Gaming Services 자동 초기화를 활성화합니다.
이렇게 하면 애플리케이션이 시작될 때 Unity Gaming Services가 즉시 초기화됩니다.

이 기능을 사용하려면 \*\*Automatically initialize UnityIAPServices (recommended)\*\*를 활성화해야 합니다. **IAP 카탈로그**에 이 체크박스가 표시되지 않으면 카탈로그 창에 제품을 아직 추가하지 않았기 때문일 수 있습니다.

그러면 기본 초기화 옵션으로 Unity Gaming Services가 초기화됩니다. 일부 서비스에는 특정 초기화 옵션이 필요하며 기본 구성에서는 작동하지 않을 수 있습니다. 커스텀 옵션이 필요한 경우 위에서 설명한 코딩된 API 사용하여 Unity Gaming Services를 초기화합니다.
