Implementation of In-App Purchase

IAP can be implemented in two ways; the first way is to directly implement interface of the IAP service provided by ONE store, and the second way is to use the IAP SDK which is wrapping the IAP service interface implementation. IAP can be implemented by using one of the two ways above. Each developer can select a method appropriate for its applications. However, for a more convenient implementation, the implementation by using the IAP SDK is recommended rather than the direct implementation of the service.

Directly Implement In-App Purchase Service Interface

  • You are required to follow a development method optimized for the environment when developing plug-in forms of the various types of development platforms (including Unity and Unreal 3D), and therefore in some cases you may need to directly implement the IAP service interface. (Unity and the Unreal 3D ONE store IAP SDK will be provided) Interface of ONE store's IAP service is provided as the ‘IInAppPurchseService.aidl’ file which is the AIDL(Android Interface Definition Language) type. The method to directly implement interface by using the AIDL file without the IAP SDK is as follows:

    • Bind AIDL

      • To use IAP by allowing a developer's apps and ONE store (service) apps to communicate, you are required to bind IAP to the ONE store IAP service by using the IInAppPurchseService.aidl. file. To this end, create a ServiceConnection object.

      • And then, if you bind the created Connection object by calling the bindService method according to the life cycle of application in the app, you can request IAP by using the mService object.

      • When an activity or a process that uses payment is terminated, you must release the bound IAP service connection in the onDestroy method.

    • Unbind AIDL

      • If the bound service is not released, the created connection will be maintained and that could cause a problem in the function of application.

    • Check Support - isBillingSupported()

      • Check whether support is provided for IAP before using the ONE store IAP API in a developer's app. If you use other API without processing a failure code, the same failure code might be passed to you. You can find detailed response codes in the Table 1 in In-App Purchase Reference.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • Check In-App Product Information - getProductDetails()

      • Call the getProductDetails method with the in-app product type and in-app ID list information that you want to check by using the API which is for getting in-app product information registered on the ONE store Developer Center. The in-app ID is a Custom in-app ID which is designated when developers register an in-app product on the Developer Center. You can find detailed response codes and specifications in In-App Purchase Reference.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • Request Purchase

      • The ONE store service (OSS) provides two types of API - the getPurchaseIntent and the getPurchaseIntentExtraParam - to request purchase. You can find difference between each API in In-App Purchase Reference.

    • getPurchaseIntent()

      • Upon payment request, proceed with getting the purchase intent screen by using the getPurchaseIntent. The method is called by entering in-app ID, in-app product name, in-app product type and the developerPayload(up to 100bytes) randomly put by developers, and this value is used to confirm data consistency or additional data after the payment is made. The code that executes the payment process by using the results gained from calling the getPurchaseIntent and methods is as follows:

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • getPurchaseIntentExtraParam()

      • This is much the same as the getPurchaseIntent specification used by developers for purchase and delivers bundle data to the last parameter. You can find the contents defined in the Bundle data in In-App Purchase Reference. The code that executes the payment process by using the results gained from calling the getPurchaseIntentExtraParam and methods is as follows:

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

        The gameUserId, protectionApplicable parameters are optional and must be used only in advance for the promotion with ONE store department manager. In general, the value should not be sent. In addition, the gameUserId should be sent to a hashed unique value so that there is no privacy information protection issue when sending values in advance.

      • You can find the detailed response codes and specifications of purchase request in In-App Purchase Reference. Upon the completion of payment process, the result value is passed to the onActivityResult method of the Activity that implemented IAP. At this moment, the Activity.RESULT_OK value or the Activity.RESULT_CANCELED value is passed to the resultCode, and you will receive the payment result code value and purchase information data as Bundle in the Intent data.

    • Check Purchase History - getPurchases()

      • The API for checking purchase history can get the information of managed products(inapp) which are not consumed yet and the list of subscription(auto) products which are in use. On the first call, the continuationKey value is sent as a blank(""). When there are more than 100 in-app product information items, you can receive the information items below the 100th rank by putting the continuationKey which was downloaded from the server in the first response into the second call parameter. The response result is the list of purchase history IDs, the list of purchase history information and the list of signatures used for signature verification. Developers are required to proceed with signature verification by using a single purchase history information item and signature information.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • Consume In-App Product - consumePurchase()

      • The managed product(inapp) cannot be repurchased until the purchased product is consumed. Immediately after a managed product is purchased, the purchase information of the product is managed by ONE store. If the purchased product is consumed, the user's right to purchase the product will be immediately withdrawn. In other words, if a managed product is not consumed after purchase, the product can be used like a non-consumable type product. If the purchased product is consumed immediately, it can be used like a consumable type product. If the purchased product is consumed after a certain period of time, it can be used like a subscription-type product. For details, refer to 'How to Implement In-App Purchases Case by Case'. To consume the purchased product, pass to the consumePurchase method the 'purchaseId' which is delivered when the purchase is completed or purchase history is checked, and call. The following is the sample code to call the method. After the completion of purchase process, if you want to provide the items of a developer's app for users, you must provide them after confirming that the result of the request of the method which consumes the purchased product is success.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • Request Change to Subscription Status - manageRecurringProduct()

      • As for the subscription(auto) product, payment is automatically made one month after the first purchase. If you want to change the status of the subscription product before the automatic payment is made, revise the status of subscription(recurringState) using this method (status information is included in the 'check purchase history' information). At the time when you reserve the cancellation of subscription, pass the action field as "cancel" and call. If you want to cancel the reservation of the subscription cancellation, pass the action field as "reactive" and call. The following is the sample code to call the method.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

    • Request Login to ONE store - getLoginIntent()

      • ONE store's payment module supports the processing of the user who is not logged in. If the RESULT_NEED_LOGIN ('refer to (v0.9) 8. In-App Purchase Reference > Server Response Codes' ) is passed as the result value of ONE store's API call, developers can notify users that the ONE store login is needed, or can expose ONE store's login screen via the getLoginIntent. You can call the screen with the startActivityForResult after receiving the intent of ONE store's login activity by using the getLoginIntent method in an app applied with ONE store's IAP SDK. The following is the sample code to call the method.

      • This method may be blocked when called in the UI thread, and therefore you must call it by creating a thread.

      • You can find the detailed response codes and specifications in In-App Purchase Reference. Upon the completion of login process, the result value is passed to the onActivityResult method of the Activity that called the login method. At this moment, the Activity.RESULT_OK value or the Activity.RESULT_CANCELED value is passed to the resultCode, and you will receive the payment result code value and login information data as Bundle in the Intent data.

Implement Using In-App Purchase SDK

  • If you directly create the IAP code through the" Directly Implement In-App Purchase Service Interface" approach, you can develop it more extensively, however have no choice but to increase the amount of the code. For a more convenient implementation, use the IAP SDK which wrapped the IAP service. The IAP SDK provides the PurchaseClient class for a more convenient and intuitive use by hiding the parts that use the IAP service. Refer to "Add In-App Purchase Library" to find a way to add the SDK to the development project.

    • PurchaseClient Class

      • The SDK defines any additional error codes that could happen only in the SDK, other than the In-App Purchase Reference > Server Response Code that occurs when using the AIDL.

      • Developers must check the Server Response Codes in addition to these error codes and proceed to handle each error situation.

  • About Major Classes in SDK

    • IInAppPurchaseService AIDL InterfaceIt is the AIDL interface file which is defined to communicate with ONE store's IAP service.

    • PurchaseClient ClassAll methods used for IAP are included in this class. Each method is implemented by wrapping the features provided by the ONE store IAP service. The method which has 'Async' postfix in its name is processed by creating threads internally to ensure a safe operation while being executed on the UI thread. The table below shows the methods provided by the PurchaseClient class and the method information mapped to the IAP service.

    • IapEnum ClassThis class defines the enum value used in the methods of the apps that use the IAP SDK. It also defines the ProductType("inapp, auto), the RecurringType(-1, 0, 1), and the RecurringAction("cancel", "reactivate").IapResult ClassThis class defines the error code value which is passed to the onError listener after completing the method calls by using the IAP SDK.

    • Security ClassThis class provides a signature verification feature to confirm that data about purchase result or purchase information is not forged/falsified when the ONE store IAP is used. Verification is made using an authentication key issued by developers. For details, refer to 'Preparatory Work > Issue License Key'.

    • ProductDetail / PurchaseData Class

    • This class defines a response model for checking in-app product information in the SDK and a response model for purchase results

    • AppInstaller ClassThis class provides a feature that induces the installation and update of the OSS apps because the OSS apps are required upon in-app purchases.

  • Initialize & Connect In-App Purchases

    • To use the IAP SDK, you are required to create a PurchaseClient object and proceed with initialization to execute the purchase method. First of all, put the Context information of current Activity and the signature verification key value when creating the PurchaseClient object. After the object is created, proceed with connection by executing the connect. During the process, a connection with the IAP service is made in the SDK and a variety of variables for purchase are set up.

    • The thing to be cautious of when performing the 'connect' is that the onErrorNeedUpdateException() of the ServiceConnectionListener will be called if the ONE store service (OSS) apps are not installed or the version of the OSS apps does not support IAP v 17. Once this error is called, call the PurchaseClient.launchUpdateOrInstallFlow method which updates or installs the OSS apps as does the code seen above. And, when the activity is terminated, put in the onDestroy method the code which releases the PurchaseClient.

  • Initialize & Connect In-App Purchases

    • To use the IAP SDK, you are required to create a PurchaseClient object and proceed with initialization to execute the purchase method. First of all, put the Context information of current Activity and the signature verification key value when creating the PurchaseClient object. After the object is created, proceed with connection by executing the connect. During the process, a connection with the IAP service is made in the SDK and a variety of variables for purchase are set up.

  • Check In-App Product Information

    • If in-app IDs that you want to get are put in the form of the ArrayList in the parameter of the queryProductAsync method and called, the result will be passed to the registered listener. The in-app ID is a Custom in-app ID which is designated when developers register in-app products on the Developer Center. In-app product information gives a response in the form of the ProductDetail model of the SDK to the onSuccess listener.

  • Request Purchase

    • To execute purchase, call the launchPurchaseFlowAsync method. When the method is called, developers randomly enter in-app ID, in-app product name, in-app product type and the developerPayload(up to 100bytes), and these values are used to confirm data consistency or additional data after the payment is made. And the requestCode delivered through parameters is used later to confirm the data passed to the onActivityResult.

    • When the purchase is successful, the onSuccess listener receives a response and will be passed to the PurchaseData specification of the SDK. Developers confirm data consistency or additional data through the developerPayload according to the passed responses, and proceed with signature verification using signature information. Finally, when it comes to the managed product, provide users with the product by consuming the product.

    • ONE store is proceeding with various benefits promotions for users, including discount coupons and cash-back services. When purchase is requested, developers can limit or allow the application's users to participate in the promotions by using the gameUserId and promotionApplicable parameters. Developers select and pass a unique user identification number of the app in question and the app's participation in the promotions, and then ONE store applies the user's promotion benefits based on that value.

      The gameUserId, protectionApplicable parameters are optional and must be used only in advance for the promotion with ONE store department manager. In general, the value should not be sent. In addition, the gameUserId should be sent to a hashed unique value so that there is no privacy information protection issue when sending values in advance.

    • For more information on the purchase to be passed to the listener when payment is successful, refer to 'In-App Purchase Reference'. The result of the completion of payment is passed to the onActivityResult of the Activity which called the launchPurchaseFlowAsync, and the handlePurchaseData method must be added here to process the purchase result within the SDK. When the handlePurchaseData method is executed and if the PurchaseFlowListener which is entered as a purchase request parameter is null, a false is returned. When it comes to processing success and error, the response result is passed through the PurchaseFlowListener listener.

  • Check Purchase History

    • By calling the queryPurchasesAsync method, get information about a user's managed products(inapp) which are not consumed yet and subscription(auto) currently in use. Within the SDK, the signature verification is proceeded to check whether the data on purchase information is forged/falsified. If the signature verification fails, the IapResult.IAP_ERROR_SIGNATURE_VERIFICATION value defined in ‘IapResult’ will be passed to the onError listener. If this error occurs, the purchase information result data might have been forged, and therefore you are required to check whether there were abusing attacks related to the purchase.

    • When it comes to the managed product(inapp) received from the 'check purchase history', developers can provide the user with the products by comsuming the product.

  • Consume In-App Product

    • The managed product(inapp) cannot be repurchased until the purchased product is consumed. Immediately after a managed product is purchased, the purchase information of the product is managed by ONE store. If the purchased product is not consumed, the user's right to purchase the product will be immediately withdrawn. In other words, if a managed product is consumed after purchase, it can be used like a non-consumable type product. If the purchased product is consumed immediately, it can be used like a consumable type product. If the purchased product is consumed after a certain period of time, it can be used like a subscription-type product. To consume the purchased product, pass the purchase information received from the launchPurchaseFlowAsync or queryPurchasesAsync to the parameter of the consumeAsync method and call.

  • Request Change to Subscription Status

    • As for the subscription(auto) products, payment is automatically made one month after the first purchase. If you want to change the status of the subscription before the automatic payment is made, revise the status of the subscription(recurringState) using this method. (status information is included in the 'check purchase history' information) If you want to request change to the status of the subscription, pass the launchPurchaseFlowAsync or queryPurchasesAsync received from purchase information to the parameter of the manageRecurringProductAsync method. At the time when you reserve the cancellation of subscription, pass the action field as "cancel" and call. If you want to cancel the reservation of the subscription cancellation, pass the action field as "reactive" and call. The following is the sample code to call the method.

  • Request ONE store Login

    • To perform the ONE store login, call the launchLoginFlowAsync method. The requestCode passed to the parameter is used to confirm the data that will be passed to the onActivityResult later.

  • The result of the completion of login is passed to the onActivityResult of the Activity that called the launchLoginFlowAsync, and the handleLoginData method must be added here to process the purchase result within the SDK. When the handleLoginData method is executed and if the LoginFlowListener which is entered as a purchase request parameter is null, a false is returned. When it comes to processing success and error, the response result is passed through the LoginFlowListener listener.

Cautions for Implementation of Consumable Products

  • If purchased once, the managed product is managed by ONE store and the same product cannot be repurchased. To use it as a consumable-type product which can be purchased repeatedly, the purchased product is required be consumed immediately after the purchase is completed, and items must be provided to users after the consumption request is successful.

  • Even if the purchase by users is completed, the result might be passed as failure to a developer's app when the network is temporarily disconnected during the purchase process. Or the purchase result may not be received at all due to the app crashing caused by unknown errors. In this case, a serious problem will arise in which users are not provided with the items of a developer's app even though they paid the amount of money. To minimize such a problem and prevent problems from occurring when users buy the same products, the list of in-app products which were not consumed should be imported and the consumption of product should be proceeded, during the execution of app or by providing a purchase recovery button. And then a logic must be entered to reprocess the provision of a developer's app items.

Last updated