# Use ONE store IAP in Unity

### **Overview**  <a href="#useonestoreiapinunity-overview" id="useonestoreiapinunity-overview"></a>

The Unity development environment provides ONE store Unity Plugin for easy application of ONE store IAP.

This document describes how to use Unity plugin by setting up project and how to implement the billing function in the game.

This plugin has been developed with Unity 2019.3.15f1 version.

### **Set up ONE store Unity Plugin**  <a href="#useonestoreiapinunity-setuponestoreunityplugin" id="useonestoreiapinunity-setuponestoreunityplugin"></a>

1\. Download the ‘.unitypackage’ file from Developer Center for the billing plugin for Unity.

2\. Click on ‘Assets > Import Package > Custom Package‘ on the Unity menu bar.

![](https://2218522982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgStyyzRzNh9x2u93ZH03%2Fuploads%2FH5CcWY5MXKAtmH0emU66%2Fimage.png?alt=media\&token=d39ea132-ba65-43c3-b48a-5040bea0ca70)\


3\. Find the downloaded location and select the ‘. unitypackage’ file.

4\. With all the assets being ticked in the ‘Import Unity Package‘ dialogue box, click on the ‘Import’ button&#x20;

![](https://2218522982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgStyyzRzNh9x2u93ZH03%2Fuploads%2FvvMSvjMFIrwQmjivLUPm%2Fimage.png?alt=media\&token=f0a5c884-0e0f-4ca0-a1e1-00b6dc305003)\


5\. After the package is imported, the asset of the project will be added as seen below.\
![](https://2218522982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgStyyzRzNh9x2u93ZH03%2Fuploads%2Fj0FRL5yxVN13DaFQhSt1%2Fimage.png?alt=media\&token=0975f019-e9a9-4e63-ab58-5c21a07dc176)

### **Unity Plugin Configuration**  <a href="#useonestoreiapinunity-unitypluginconfiguration" id="useonestoreiapinunity-unitypluginconfiguration"></a>

#### **Assets > Plugins > Android** <a href="#useonestoreiapinunity-assets-greater-than-plugins-greater-than-android" id="useonestoreiapinunity-assets-greater-than-plugins-greater-than-android"></a>

| <p><br></p>             | <p><br></p>                                                                                                                                                                                                                                                                                                                                                                            |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AndroidManifest.xml     | <p><strong>Project Settings > Player > Publishing Settings > Build</strong></p><p>It is necessary for setting up Custom Main Manifest.</p><p><img src="https://2218522982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgStyyzRzNh9x2u93ZH03%2Fuploads%2FzWEy9FZQ9OYyxjOVE1qz%2Fimage.png?alt=media&#x26;token=26f20db2-f61f-480c-841f-86406a4ffc64" alt=""></p> |
| Iap\_adapter-v1.3.0.aar | It takes charge of the communication between Unity and ONE store IAP library.                                                                                                                                                                                                                                                                                                          |
| Iap\_sdk-v19.00.00.aar  | ONE store IAP library file                                                                                                                                                                                                                                                                                                                                                             |

#### **Assets > Scripts > Purchase**  <a href="#useonestoreiapinunity-assets-greater-than-scripts-greater-than-purchase" id="useonestoreiapinunity-assets-greater-than-scripts-greater-than-purchase"></a>

| <p><br></p>              | <p><br></p>                                                                                                            |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| AndroidNative.cs         | It is the utility file that pops up Android AlertDialog from Unity.                                                    |
| GaaIapCallbackManager.cs | It takes charge of calling up the response result sent from Android in Unity.                                          |
| GaaIapCallManager.cs     | It takes charge of calling up IAP SDK functions in Unity.                                                              |
| GaaIapResultListener.cs  | It receives the response result transmitted from GaaIapCallbackManager and processes the data to be easily used in UI. |
| GaaPurchaseResponse.cs   | It is the file that defines the value object used in IAP library.                                                      |

#### Assets > StreamingAssets <a href="#useonestoreiapinunity-assets-greater-than-streamingassets" id="useonestoreiapinunity-assets-greater-than-streamingassets"></a>

| <p><br></p>           | <p><br></p>                                                     |
| --------------------- | --------------------------------------------------------------- |
| global-appstores.json | It is the file necessary to find the payment module in IAP SDK. |

\


### **Apply ONE store In-App Purchase (IAP) Library to Game**  <a href="#useonestoreiapinunity-applyonestorein-apppurchase-iap-librarytogame" id="useonestoreiapinunity-applyonestorein-apppurchase-iap-librarytogame"></a>

#### **Initialize & connect ONE store IAP**  <a href="#useonestoreiapinunity-initialize-and-connectonestoreiap" id="useonestoreiapinunity-initialize-and-connectonestoreiap"></a>

To request IAP to ONE store, you first need to connect to ONE store Service (OSS) with the steps below.

If the connection is tried through GaaIapCallManager.StartConnection(), SDK initialization begins internally and the connection to the billing module is attempted. At this point, refer to the billing module information defined in global-appstores.json.

| `using Gaapublic` `class` `YourUiScript: MonoBehaviour{    ...    public` `void` `StartConnection()    {        if` `(GaaIapCallManager.IsServiceAvailable() == false)        {            GaaIapCallManager.StartConnection( /* your public key */` `);        }    }    ...}` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

You can receive the way to confirm the response made by the connection through GaaIapResultListener.PurchaseClientStateEvent().

The response result will be transmitted in the GaaPurchaseResponse.IapResult object format.

You can confirm the value of apResult.code through GaaPurchaseResponse.ResponseCode.

| `void` `PurchaseClientStateEvent(IapResult iapResult){    if` `(iapResult.IsSuccess())    {        ...    }    else` `if` `(iapResult.code == ResponseCode.RESULT_NEED_UPDATE)    {        ...    }    else` `if` `(iapResult.code == ResponseCode.RESULT_NEED_LOGIN)    {        ...    }}` |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

When the connection fails, you must respond according to the response code.

You must cut the connection with the billing module when ending the app.

| `void` `OnDestroy({    GaaIapCallManager.Destroy();}` |
| ----------------------------------------------------- |

#### Check in-app product details <a href="#useonestoreiapinunity-checkin-appproductdetails" id="useonestoreiapinunity-checkin-appproductdetails"></a>

In-app ID issued when registering an in-app will be used to search the in-app product details. Call up QueryProductDetails() to search the in-app product details. Specify the array value of the in-app ID (productid) and the corresponding in-app type.

There are two types of in-app: Managed product (ProductType.INAPP) and Monthly auto-renewal product (ProductType.AUTO). Enter ProductType.ALL to check both types of in-app.

To check the in-app product details, the app uses the in-app ID, which has been defined when the in-app is registered on ONE store Developer Center. For details, refer to Developer Center.

You can receive the response result value of checking the in-app product details through ProductDetailsSuccessEvent(), ProductDetailsErrorEvent() of GaaIapResultListener.

The communication between Android and Unity is string communication. There is a limit in the string length to be sent at once, and therefore the result value will be transmitted per in-app at a time.

Therefore, the value of ProductDetailsSuccessEvent(..., ..., int count, int totalCount) is important.

ex) If there is one in-app: count = 1, totalCount = 1 / if there are 10 in-apps: count = 1, totalCount = 10 ... count = 10, totalCount = 10

| `// Check in-app product detailsstring[] all_products = { inapp_p5000, inapp_p10000, inapp_p50000, auto_a100000 };GaaIapCallManager.QueryProductDetails(all_products, ProductType.ALL);` |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

| `List<ProductDetail> products = new` `List<ProductDetail>();void` `ProductDetailsSuccessEvent(ProductDetail productDetail, int` `count, int` `totalCount){    if` `(count == 1)    {        products.Clear();    }` `products.Add(productDetail);` `if` `(count == totalCount)    {        // send ProductDetail List to UI    }}`   `void` `ProductDetailsErrorEvent(IapResult iapResult){    if` `(iapResult.code == ResponseCode.RESULT_NEED_UPDATE)    {        ...    }    else` `if` `(iapResult.code == ResponseCode.RESULT_NEED_LOGIN)    {        ...    }}` |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

You must manage the list of in-app IDs in the app’s own security back-end server.

#### Request purchase <a href="#useonestoreiapinunity-requestpurchase" id="useonestoreiapinunity-requestpurchase"></a>

To purchase in-app, call up GaaIapCallManager.LaunchPurchaseFlow().

Generate and specify the GaaPurchaseResponse.PurchaseFlowParams object during calls.

The required values are the in-app ID (productid) and in-app type (Managed product: ProductType.INAPP, Monthly auto-renewal product: ProductType.AUTO).

Also input develperPayload(up to 200byte) randomly entered by the developer. This value can be used to check data consistency and additional data after the billing is made.

productName is used not to change the title of registered in-app ID, but to change the title of in-app to be shown at the time of billing.

ONE store is offering various benefit promotions for users, including discount coupons and cashback.

The developer can allow or limit the app user’s participation in the promotion by using the gameUserId, promotionApplicable parameters at the request of purchase.

If the developer sends the app’s unique user identification number and selects whether to participate in the promotion, ONE store will apply the user’s promotion benefits based on this value

The gameUserId, promotionApplicable parameters are optional values and must be used after a prior consultation on the promotion with the person in charge of ONE store business department. In general cases, the values shall not be sent.

In addition, if these values are sent after the prior consultation, gameUserId must be sent in a hashed unique value for protection of personal information.

The following example shows how to request the purchase of in-app.

| `PurchaseFlowParams param = new` `PurchaseFlowParams();param.productId = productId;param.productType = type;param.devPayload = "your Developer Payload";//param.productName = "";                     // optional` `//param.gameUserId = "";                      // promotion//param.promotionApplicable = false;          // promotion` `GaaIapCallManager.LaunchPurchaseFlow(param);` |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

If you call the LaunchPurchaseFlow() method, ONE store billing screen will be displayed.

Fig.1 shows ONE store in-app billing screen

![](https://2218522982-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgStyyzRzNh9x2u93ZH03%2Fuploads%2F8YQqpbCYqwRHoLCZqpg2%2Fimage.png?alt=media\&token=a560d083-8e0f-4911-a41e-37b8bd680b6f)

**Fig.1** ONE store in-app billing screen

The response to the billing will be sent through ProductDetailsSuccessEvent(), ProductDetailsErrorEvent() of GaaIapResultListener.

count, totalCount exist for the same reason as ‘Check in-app product details’.

| `private` `List<PurchaseData> purchases = new` `List<PurchaseData>();private` `List<string> signatures = new` `List<string>();`   `void` `PurchaseUpdatedSuccessEvent(PurchaseData purchaseData, string signature, int` `count, int` `totalCount){    if` `(purchaseData != null) {        if` `(count == 1)        {            purchases.Clear();            signatures.Clear();        }` `purchases.Add(purchaseData);        signatures.Add(signature);` `if` `(count == totalCount)        {            OnPurchaseUpdatedResponse(purchases, signatures);        }    }    else    {        // no PurchaseData    }}` `void` `PurchaseUpdatedErrorEvent(IapResult iapResult){    ...}` |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

\


If the billing is successful, a purchase token will be generated. The purchase token is a unique identifier showing the purchase ID bought by the user. In the app, the purchase token can be stored in the local or security back-end server and can be used to check the purchase.

The purchase token for Managed product is unique for every purchase ID, however the purchase token for Monthly auto-renewal product remains the same while the in-app is being renewed.

The user also receives a transaction receipt containing a receipt number via email. As for Managed product, he/she will receive the email whenever purchasing it. As for Monthly auto-renewal product, he/she will receive the email at the time of first purchase and every renewal afterwards.

#### Acknowledge purchase <a href="#useonestoreiapinunity-acknowledgepurchase" id="useonestoreiapinunity-acknowledgepurchase"></a>

If ONE store IAP library v6 (SDK V19) and above is used, purchase must be acknowledged within 3 days. Otherwise, it will be judged that the in-app has not been provided, and thereby the purchase amount will be refunded.

You can acknowledge the purchase by using one of the following methods.

* If the in-app is consumable, use GaaIapCallManager.Consume()&#x20;
* If the in-app is not consumable, use GaaIapCallManager.Acknowledge()

As for Monthly auto-renewal product, you need to acknowledge the purchase only for the first billing.

The PurchaseData object includes the isAcknowledged() method, which shows if the purchase is acknowledged. If you use this method before acknowledging the purchase, you can figure out if the purchase has already been acknowledged.

The following example shows how to acknowledge the purchase of Monthly auto-renewal product.

| `void` `PurchaseUpdatedSuccessEvent(PurchaseData purchaseData, string signature, int` `count, int` `totalCount){    ...    if` `(purchaseData != null) {        ...        if` `(purchaseData.IsAcknowledged() == false)        {            GaaIapCallManager.Acknowledge(purchaseData, "your developer payload");        }    }    ...}` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

#### Consume Managed product  <a href="#useonestoreiapinunity-consumemanagedproduct" id="useonestoreiapinunity-consumemanagedproduct"></a>

Managed product cannot be re-purchased until the purchased in-app is consumed.

As soon as Managed product is purchased, the purchase information on this in-app product shall be managed by ONE store. Once it is consumed, the user’s right to the purchased Managed product shall be immediately retrieved.

In other words, if Managed product is purchased but not consumed, then it can be used as non-consumable in-app. If Managed product is consumed immediately after the purchase, it can be used as consumable in-app. If it is consumed after a certain period, then it can be used as Monthly auto-renewal product.

To consume Managed product, call up GaaIapCallManager.Consume(). The response result will be sent to ConsumeSuccessEvent(), ConsumeErrorEvent() of GaaIapResultListener

The following example shows how to consume Managed product.

| `GaaIapCallManager.Consume(purchaseData, "your developer payload");`   `void` `ConsumeSuccessEvent(PurchaseData purchaseData){    // When consumption is successfully completed, the purchased product is paid to the user.}` `void` `ConsumeErrorEvent(IapResult iapResult){    ...}` |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### &#x20;Check purchase history  <a href="#useonestoreiapinunity-checkpurchasehistory" id="useonestoreiapinunity-checkpurchasehistory"></a>

Get the information on unconsumed Managed product and Monthly auto-renewal product in use by using the PurchaseClient.queryPurchasesAsync() method.

Perform signature verification within the SDK with the public key that has been specified while connecting to the billing module to check whether the purchase details data is forged or falsified. If the verification fails, the error code of IapResult (ResponseCode.ERROR\_SIGNATURE\_VERIFICATION) will be transmitted. If this error occurs, that indicates that the purchase result data is likely forged and falsified. In that case, you need to see if there have been any abusing attacks related to the purchase.

To allow the user to check the history of the purchase made in the app, call up queryPurchasesAsync() in PurchaseClient together with the in-app type as seen in the following example.

The response to checking the purchase history will be sent through QueryPurchasesSuccessEvent(), QueryPurchasesErrorEvent() of GaaIapResultListener.

| `GaaIapCallManager.QueryPurchases(ProductType.INAPP); // or ProductType.AUTO` |
| ----------------------------------------------------------------------------- |

ProductType.ALL, the in-app type, will not work when searching the purchase history. Either Managed product (INAPP) or Monthly auto-renewal product (AUTO) must be specified.&#x20;

There are various data in the PurchaseData object. You can check the in-app information including the purchase status and time. For details, refer to the PurchaseData object.

By calling up QueryPurchases(), you can figure out the history of all the purchases and uses that the user might have made in the app while the app is not running.

If you call upon QueryPurchaseAsync(), you can also figure out the user’s purchase history, which has been omitted from the app for some reasons even though the user purchased the in-app while the app was executing.

QueryPurchaseAsync() needs to be called upon for the following cases;

* Whenever the app starts, call upon queryPurchaseAsync() to restore the user’s history of all the purchases, which have been made since the app stopped for the last time.
* You must call up QueryPurchases() if the response result is a success after acknowledging the purchase(Acknowledge) or changing the Monthly auto-renewal product status (ManageRecurringProduct).

#### Change Monthly auto-renewal product status  <a href="#useonestoreiapinunity-changemonthlyauto-renewalproductstatus" id="useonestoreiapinunity-changemonthlyauto-renewalproductstatus"></a>

Monthly auto-renewal product is the in-app that will be renewed 30 days after its initial purchase.

By using GaaIapCallManager.ManageRecurringProduct(), you can change the Monthly auto-renewal product status even before the renewal.

Set the RecurringAction value according to the PurchaseData.recurringState value.

The response result will be sent to GaaIapResultListener.RecurringSuccessEvent(), RecurringErrorEvent().

You can check the status information through PurchaseData.getRecurringState() received from ‘Check purchase history’.

The following example shows how to change the Monthly auto-renewal product status.

| `// GaaPurchaseResponse.RecurringAction 참조PurchaseData purchaseData = ...string recurringAction;if` `(purchaseData.recurringState == RecurringState.RECURRING) {    recurringAction = RecurringAction.CANCEL;} else` `if` `(purchaseData.recurringState == RecurringState.CANCEL) {    recurringAction = RecurringAction.REACTIVATE;}GaaIapCallManager.ManageRecurringProduct(purchaseData, recurringAction);`  `void` `RecurringSuccessEvent(PurchaseData purchaseData, string action){    // Returns purchaseData sent to the request.    // The action value is the changed state value.    // If you have changed the status of the monthly payment product, you should get the correct value again through "GaaIapCallManager.QueryPurchases()".}`  `void` `RecurringErrorEvent(IapResult iapResult){    ...}` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

If the Monthly auto-renewal product status changes successfully, you MUST receive the purchase information of Monthly auto-renewal product again through QueryPurchases(ProductType.AUTO). Only after that you can confirm the changed PurchaseData.recurringState value.

#### Request ONE store login <a href="#useonestoreiapinunity-requestonestorelogin" id="useonestoreiapinunity-requestonestorelogin"></a>

ONE store IAP SDK works only during login.

If there is the previous login history, ONE store will automatically log in. However, if the login is needed, IapResult.getResponseCode() will be sent to RESULT\_NEED\_LOGIN upon API requests.

When RESULT\_NEED\_LOGIN is sent, you must call the GaaIapCallManager.LaunchLoginFlow() method.

You can check the response result through GaaIapResultListener.LoginFlowEvent().

The following example shows how to request ONE store login.

| `GaaIapCallManager.LaunchLoginFlow();`   `void` `LoginFlowEvent(IapResult iapResult){    if` `(iapResult.IsSuccess()) {        // You need to specify the scenario after successful login.    }}` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

#### Install ONE store Service (OSS)  <a href="#useonestoreiapinunity-installonestoreservice-oss" id="useonestoreiapinunity-installonestoreservice-oss"></a>

In-app purchase (IAP) is not available if ONE store service (OSS) version is low or none.

If ResponseCode.RESULT\_NEED\_UPDATE occurs as the response result when you try to connect through GaaIapCallManager.StartConnection(), you must call the GaaIapCallManager.LaunchUpdateOrInstallFlow() method.

You can check the response result through GaaIapResultListener.UpdateOfInstallFlowEvent()

The following example shows how to install OSS.

| `GaaiapCallManager.LaunchUpdateOrInstallFlow();`   `void` `UpdateOrInstallFlowEvent(IapResult iapResult){    if` `(iapResult.IsSuccess()) {        // If the installation is completed successfully,        // you should try to reconnect with the ONE store service.        GaaIapCallManager.StartConnection("your public key")    } else` `{        ...    }}` |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

#### Obtain market identification code  <a href="#useonestoreiapinunity-obtainmarketidentificationcode" id="useonestoreiapinunity-obtainmarketidentificationcode"></a>

For IAP library V6 and above, the market identification code is necessary to use Server API.

If you call up the GaaIapCallManager.GetStoreInfo() method, you can check the response through GaaIapResultListener.StoreInfoEvent().

The following example shows how to obtain the market identification code.

| `GaaIapCallManager.GetStoreInfo();`   `void` `StoreInfoEvent(string storeCode){    // Save storecode and use it in Server to Server API.}` |
| ------------------------------------------------------------------------------------------------------------------------------------------ |

\


\
