Using ONE store IAP (SDK V21) from Unity
Last updated
Last updated
The ONE store purchase plugin extends assets to the Unity environment to provide the latest features of the ONE store purchase library in games. This guide explains how to set up the project to use the plugin and how to implement features of the ONE store purchase library.
Unity
2020.3.48f1
Java SDK (Java 11)
Purchase: v21.01.00
App License Checker: v2.1.0
Download latest version of the ONE store In-app purchase plugin for Unity from the release page on GitHub.
In the Unity menu bar, click Assets > Import Package > Custom Package.
Navigate to the location of download and select the .unitypackage file.
In the Import Unity Package dialog, keep all assets selected and click Import.
After importing the package, a folder will be added. This folder contains the ONE store purchase library.
Assets/OneStoreCorpPlugins
/Common
/Authentication
/Purchase
/AppLicenseChecker
EDM4U (External Dependency Manager for Unity) is distributed alongside it.
If you are already using it, you can uncheck ExternalDependencyManager
during the Import Package
step and apply it.
To include repositories and dependencies in your project, follow these steps:
Project Settings > Player > Publishing Settings > Build
Check the following two options:
Custom Main Manifest
Custom Main Gradle Template
Select Assets > External Dependency Manager > Android Resolver > Force Resolve
.
You can see the following applied in the mainTemplete.gradle
file:
In-app Purchase dependencies are listed here: Assets/OneStoreCorpPlugins/Purchase/Editor/PurchaseDependencies.xml
App License Checker dependencies are listed here: Assets/OneStoreCorpPlugins/AppLicenseChecker/Editor/AppLicenseCheckerDependencies.xml
You must set the <queries>
in your AndroidManifest.xml
file.
For details, refer to the notice.
If you don’t set the <queries> tag, the SDK won’t be able to find the ONE store service.
This option forces the SDK to integrate with the global store. This feature has been implemented from SDK v21.01.00.
In the distribution build version, this option must be removed.
During development, you can set the log level to expose the flow of data in the SDK in more detail. It operates based on values defined in android.util.Log.
Constants Value | Value |
---|---|
VERBOSE | 2 |
DEBUG | 3 |
INFO (default) | 4 |
WARN | 5 |
ERROR | 6 |
For the distribution build version, remove this option as it may be vulnerable.
To request in-app purchases, initialize the PurchaseClientImpl
object using the license key provided by the ONE store developer center.
Call the Initialize()
function to complete basic setup. This is a prerequisite for connecting to the ONE store service.
After initializing the PurchaseClientImpl
object, request product information through QueryProductDetails()
and receive a response at PurchaseCallback.OnProductDetailsSucceeded()
.
ProductType
is as follows:
Product | Enum |
---|---|
Managed Product |
|
Subscription Product |
|
Monthly Subscription Product |
|
To search for all types of data at once, set ProductType.ALL
.
ProductType.ALL
can only be used for searching detailed product information, not for initiating purchase requests or retrieving purchase history.
The list of in-app product IDs should be managed by the developer's secure backend server.
To make a purchase request in the app, call the Purchase()
function on the main thread.
Create a PurchaseFlowParams object based on the values of the ProductDetail
object obtained by calling the QueryProductDetails()
API.
Use the PurchaseFlowParams.Builder
class to create a PurchaseFlowParams
object.
SetDeveloperPayload()
is an optional field with a maximum of 200 bytes, set by the developer. It can be used after payment to verify data integrity, and for additional data.
SetProductName()
is used to change and display the product name at the time of payment.
SetQuantity()
applies only to managed in-app products and is used when purchasing multiple units of a product.
ONE store offers various reward promotions to users such as discount coupons, cashback, etc.
Developers can restrict or allow user participation in promotions using gameUserId
and promotionApplicable
parameters during a purchase request.
Developers pass their app's unique user identification number and the choice of promotion participation, and ONE store applies the user's promotional benefits based on these values.
gameUserId
and promotionApplicable
parameters are optional and should only be used after prior consultation with the ONE store business department. In general cases, these values are not sent.
Even when sending values after consultation, the gameUserId should be sent as a hashed unique value for privacy reasons.
A successful call to Purchase()
displays the following screen: [Figure 1] represents the managed product purchase screen.
When a purchase is successful, the result is sent to the IPurchaseCallback.OnPurchaseSucceeded()
function.
In case of failure, the IPurchaseCallback.OnPurchaseFailed()
function is called.
When a purchase is successful, a purchase token, a unique identifier indicating the user and product ID, is also generated. While the purchase token can be stored within the app, it is safer to pass it to a backend server that can authenticate the purchase and protect against fraud.
The purchase token for managed and subscription products is issued each time a payment occurs. For monthly subscription products, the purchase token remains the same while the automatic payment is renewed.)
Additionally, users receive a transaction receipt via email that includes the receipt number. For managed products, an email is received each time a purchase is made, and for monthly subscription and subscription products, an email is received when first purchased and thereafter when renewed.
Subscriptions renew automatically until canceled. Subscriptions can have the following statuses:
Active: User is in good standing and can access their subscription.
Schedule Pause: Users can select when to pause subscriptions during use.
Weekly Subscription: Can be paused at week 1 to 3.
Monthly Subscription: Can be paused at month 1 to 3.
Annual Subscription: Does not support pauses.
Scheduled Cancellation: Users can select when to cancel their subscription during use. Payment will not be made on the next payment date.
Grace & Hold: If the user encounters payment issues, the payment will not be made on the next payment date. Immediate "Subscription Cancellation" is possible without scheduling a cancellation.
To upgrade or downgrade subscriptions, you can set a proration mode at time of purchase or set how changes affect subscription users.
The following table shows the available proration mode (OnestoreProrationMode
).
Proration Mode | Description |
IMMEDIATE_WITH_TIME_PRORATION | Subscription replacement occurs immediately, and remaining time is adjusted based on the price difference, either credited or charged. (This is default behavior.) |
IMMEDIATE_AND_CHARGE_PRORATED_PRICE | Subscription replacement occurs immediately, and billing cycle remains the same. The price for the remaining period is charged. (This option is only available for upgrades.) |
IMMEDIATE_WITHOUT_PRORATION | Subscription replacement occurs immediately, and a new price is charged on the next payment date. The billing cycle remains the same. |
DEFERRED | Replacement applies when existing plan expires, and the new fee is charged simultaneously. |
Subscription can offer users upgrades or downgrades using the same API as when initiating purchase request. However, to apply an upgrade or downgrade to a subscription, the existing subscription purchase token and prorated mode value are required. As in the following example, you must provide information about the current subscription, future (upgrade or downgrade) subscription, and proration mode.
In cases of upgrades or downgrades, the response is received in the same way as initiating purchase request logic.
Responses can also be received from retrieving purchase history. Even when subscription is purchased in proration mode, post-purchase processing is needed using PurchaseClient.acknowledgeAsync()
just like any other regular purchases.
Once a user completes a purchase, the app needs to process it. In most cases, the app receives purchase notifications through OnPurchaseSucceeded()
. Or as described in retrieving purchase history, the app may process it by calling the PurchaseClientImpl.QueryPurchases()
function.
A managed product cannot be repurchased until consumed.
To consume a product, call ConsumePurchase().
The result of the consumption operation is then handled through the IPurchaseCallback.OnConsumeSucceeded()
call.
If a managed product is not consumed it can be used as a permanent product type, and if consumed immediately after purchase it can be used as a consumable product. Additionally, if consumed after a certain period, it can be used as a limited-time product.
Since consumption requests can sometimes fail, it is necessary to check with a secure backend server to ensure that each purchase token has not been used. This prevents the app from granting multiple entitlements for the same purchase. Alternatively, you can wait until a successful consumption response is received before granting entitlements.
If a purchase is not acknowledged or consumed within 3 days, it will be determined that the user hasn't received the product and an automatic refund will be issued.
To authenticate non-consumable products, use the PurchaseClientImpl.AcknowledgePurchase()
function. This can be used for managed products, monthly subscription products, and subscription products.
Use the PurchaseData.Acknowledged()
function to determine if the product has been authenticated. Additionally, if the authentication operation is successful, the IPurchaseCallback.OnAcknowledgeSucceeded()
function is called.
Processing a purchase does not guarantee that the app has handled all purchases. There are several scenarios where the app might fail to recognize or track a purchase:
Network Issues: If the network connection is lost before device receives the purchase notification after a user successfully makes a purchase and is confirmed by ONE store.
Multiple Devices: Users expect an item purchased on one device to be available when they switch to another device.
To handle these situations, call PurchaseClientImpl.QueryPurchases()
in the app's Start()
or OnApplicationPause()
to verify that all purchases have been successfully processed, as described in post-purchase processing.
A monthly subscription product renews every 30 days after the initial purchase. The status of a monthly subscription product can be checked through PurchaseData.RecurringState()
.
To change the status of a monthly subscription product, use PurchaseClientImpl.ManageRecurringProduct()
.
Enter the purchase data and the desired RecurringAction
value.
You can display a screen to manage the status of subscription products.
Inserting PurchaseData
as a parameter checks the purchase data and executes the management screen for that subscription product. However, inserting null
will launch the user's subscription list screen.
The following is an example of how to display the subscription management screen.
From SDK v19 onward, a market distinction code is needed to use the S2S API.
When initializing the PurchaseClientImpl
object, the SDK attempts to connect to the payment module.
Upon successful connection, the storeCode
is automatically obtained and assigned to the PurchaseClientImpl.storeCode
variable.
In-app payments cannot be used if the version of ONE store service is outdated or is not installed. The first API call initially attempts to connect to the ONE store service. If RESULT_NEED_UPDATE
occurs, you must call the LaunchUpdateOrInstallFlow()
method.
The ONE store in-app SDK requires the user to be logged into ONE store. Internally, it first attempts to log in using the login token. If it fails or in cases like the initial login where a user's information is not available, a foreground login screen is displayed to prompt the user to log in.