Native IAP for Galaxy Watch

Samsung In-App Purchase (IAP) for Galaxy Watch is a Galaxy Store service that allows third-party watch applications to sell in-app items.

IAP for Galaxy Watch only works if your Galaxy Watch is paired with your phone.
The IAP Client for watch communicates with the IAP Client for phone, which internally manages communication with supporting IAP services and the Samsung ecosystem (such as Samsung Account, Samsung Checkout, and Samsung Rewards). In other words, it acts as an intermediary between the watch app and Samsung IAP phone system.

You can concentrate on integrating IAP API calls and IAP Server API calls into your watch app.

To integrate IAP for Galaxy Watch:

  • Using Tizen Extension SDK, IAP Native APIs enables you to easily integrate IAP functionality into your watch app, such as configuring IAPs, getting item details, offering and selling items, and managing purchased items.
  • Using Galaxy Watch Studio (formerly Galaxy Watch Designer), you can make your own watch face that prompts for payment after a free trial period, without the complexity of coding. For more details, see the Galaxy Watch Studio online tutorial.

By integrating IAP features, your watch apps can sell these types of in-app items:

Item type

Description

Consumable App users can use items only one time (for example, coins, special powers, or gems).
Items can be repurchased only after they are consumed.

Nonconsumable App users can use items any number of times (for example, e-books or game boards).
Items cannot be repurchased.

Autorecurring subscription These items are purchased automatically at specific intervals.
App users can access items (such as magazines, e-zines, or newspapers) any number of times during a free trial or while their paid subscriptions are active.
App users can cancel at any time after purchase during subscription period.
App users can repurchase items after cancellation.

Integrate IAP into your watch app

This section explains how to prepare your app to sell in-app items using Tizen Extension SDK. You can use Galaxy Watch Studio to make a watch face that prompts for payment after a free trial period, without the complexity of coding. See the Galaxy Watch Studio online tutorial for more information.

To prepare for integrating IAP features and testing the integration, perform the following steps:

1. Create a project

Create a project in Tizen Studio. The application API version must be at least 2.3.2 in the tizen-manifest.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<manifest xmlns="http://tizen.org/ns/packages" api-version="4.0.0" package="org.tizen.nativeiap" version="1.0.0">
</manifest>

2. Add Permissions to tizen-manifest.xml

<privileges>
    <privilege>http://tizen.org/privilege/billing</privilege>
</privileges>

3. Register app and in-app items in Seller Portal

During IAP integration, you may need to test IAP features. Samsung IAP needs information about your app and in-app items registered in Seller Portal.

To register an app and its in-app items:

  1. Sign in to Seller Portal (https://seller.samsungapps.com) using your Samsung account.

  2. Click Add New Application.

  3. Click Galaxy Watch, select the default language, and click Next.

  4. In the Binary tab, upload your app TPK.

  5. In the App Information tab, enter fundamental app details.

  6. In the Country / Region & Price tab, specify a free or paid app, a paid app price, and countries to sell your items.

  7. In the In App Purchase tab, register one or more in-app items.

4. Integrate IAP features

#include <iap-galaxyapps.h>

Operation mode

IAP supports three operational modes. One is for enabling billing for item purchases, and the other two are for testing IAP functions without billing app users for item purchases.

Mode

Description

IAP_GALAXYAPPS_COMMERCIAL_MODE

Financial transactions do occur for successful requests, and actual results are returned (successful or failed).
The app gets in-app item information of the app whose status in Seller Portal is For sale.

IAP_GALAXYAPPS_SUCCESS_TEST_MODE

Financial transactions do not occur (app users are not billed for item purchases), and successful results are always returned.
The app gets in-app item information of the app whose status in Seller Portal is Registering or Updating.

IAP_GALAXYAPPS_FAILURE_TEST_MODE

All IAP requests fail.
Negative testing to ensure that your app can handle errors such as improper input and user actions.

Get in-app items available for purchase

To get all registered in-app items from Galaxy Store, use the iap_galaxyapps_get_item_list()method.

Pass in the index of the first and last item, the item type, service mode, callback function, and user data as parameters.

When the reply is delivered, the iap_galaxyapps_reply_cb callback is invoked with the iap_galaxyapps_h object that stores the query results:

  • To get the request result from the iap_galaxyapps_h object, use the iap_galaxyapps_get_value() method.

  • If the request was successful, you can get all the item details from the iap_galaxyapps_h object using the iap_galaxyapps_foreach_item_info() method.

Request

For details, see the iap_galaxyapps_get_item_list()

int iap_galaxyapps_get_item_list (int start_number, 
                                  int end_number, 
                                  const char *item_type, 
                                  iap_galaxyapps_mode_e mode, 
                                  iap_galaxyapps_reply_cb reply_cb, 
                                  void *user_data)

Response

typedef void(* iap_galaxyapps_reply_cb)(iap_galaxyapps_h reply, 
                                        iap_galaxyapps_error_e result, 
                                        void *user_data)
  • Common result

    Key Value type

    Description

    mErrorCode int Error code number
    mErrorString String Error message
    mExtraString String Extra result
    mStartNumber int Index of the first item on the list
    mEndNumber int Index of the last item on the list
    mTotalCount int Total number of items based on the first and last item index
  • Item details

    Key Value type

    Description

    mItemId String Item ID number
    This is the same as the item ID used in the request.

    mItemName String Name provided during the item registration in the Seller Portal
    mItemPrice String Item price in a local currency
    mItemPriceString String Currency code + price
    For example: €7.99

    mCurrencyUnit String Device user currency unit
    For example: $, Won, or Pound

    mCurrencyCode String Currency code
    For example: EUR or GBP

    mItemDesc String Item description provided during the item registration
    mItemImageUrl String Item image URL provided during the item registration
    mItemDownloadUrl String Item download URL provided during the item registration
    mType String Item type:
    00: Consumable
    01: Non-consumable
    02: Non-recurring Subscription
    03: Auto-recurring Subscription
    10: All

    mSubscriptionDurationUnit String Subscription duration unit, defined as an upper case string:
    YEAR, MONTH, WEEK, DAY

    mSubscriptionDurationMultiplier String If the item type (mType) is 02 or 03, this is the item duration.
    Combined with mSubscriptionDurationUnit, it expresses the subscription duration, for example, 1MONTH.

    mJsonString String Original JSON string

Code snippet

  • To handle the request output data, define a structure for it:

    struct output_data {
        char* mErrorCode;
        char* mErrorString;
        char* mExtraString;
    
        char* mStartNumber;
        char* mEndNumber;
        char* mTotalCount;
    
        char* mItemId;
        char* mItemName;
        char* mItemPrice;
        char* mItemPriceString;
        char* mCurrencyUnit;
        char* mCurrencyCode;
        char* mItemDesc;
        char* mItemImageUrl;
        char* mItemDownloadUrl;
        char* mPaymentId;
        char* mPurchaseId;
        char* mPurchaseDate;
        char* mVerifyUrl;
        char* mType;
        char* mSubscriptionDurationUnit;
        char* mSubscriptionDurationMultiplier;
        char* mSubscriptionEndDate;
        char* mJsonString;
    };
    typedef struct output_data_s;
    
  • Request the available items, and retrieve the item details in the reply callback:

    /* Request the available item list */
    int ret = iap_galaxyapps_get_item_list(1, 10, "10", IAP_GALAXYAPPS_COMMERCIAL_MODE, __get_item_list_cb, NULL);
    if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
        /* Error handling */
        return;
    }
    
    static bool
    __foreach_item(iap_galaxyapps_h handle, void *user_data) {
        output_data value = {0,};
    
        /* Get item properties */
        iap_galaxyapps_get_value(handle, "mItemId", &value.mItemId);
        iap_galaxyapps_get_value(handle, "mItemName", &value.mItemName);
        iap_galaxyapps_get_value(handle, "mItemPriceString", &value.mItemPriceString);
        iap_galaxyapps_get_value(handle, "mItemDesc", &value.mItemDesc);
    
        /* Handle properties */
        return true;
    }
    
    /* Callback */
    static void
    __get_item_list_cb(iap_galaxyapps_h reply, iap_galaxyapps_error_e result, void *user_data)
    { 
        if (result != IAP_GALAXYAPPS_ERROR_NONE) {
            char *mErrorString = NULL;
            iap_galaxyapps_get_value(reply, "mErrorString", &mErrorString);
            /* Error handling */
            return;
        }
        
        /* Retrieve all items contained in the handle */
        int ret = iap_galaxyapps_foreach_item_info(reply, __foreach_item, NULL);
        if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
            /* Error handling */
            return;
        }
    
        return;
    }
    

Purchase an in-app item

To purchase items from Galaxy Store, use the iap_galaxyapps_start_payment() method.

Pass in the index of the item ID, service mode, callback function, and user data as parameters.

When the reply is delivered, the iap_galaxyapps_reply_cb callback is invoked with the iap_galaxyapps_h object that stores the query results:

  • To get both the request result and the purchased item details from the iap_galaxyapps_h object, use the iap_galaxyapps_get_value() method.

Request

For details, see the iap_galaxyapps_start_payment()

int iap_galaxyapps_start_payment(const char *item_id,
                                 iap_galaxyapps_mode_e mode,
                                 iap_galaxyapps_reply_cb reply_cb,
                                 void *user_data)

Response

typedef void(* iap_galaxyapps_reply_cb)(iap_galaxyapps_h reply, 
                                        iap_galaxyapps_error_e result, 
                                        void *user_data)
  • Common result

    Key Value type

    Description

    mErrorCode int Error code number
    mErrorString String Error message
    mExtraString String Extra result
  • Purchased item details

    Key Value type

    Description

    mItemId String Item ID number
    This is the same as the item ID used in the request.

    mItemName String Name provided during the item registration in the Seller Office
    mItemPrice Double Item price in a local currency
    mItemPriceString String Currency code + price
    For example: €7.99

    mCurrencyUnit String Device user currency unit
    For example: $, Won, or Pound

    mCurrencyCode String Currency code
    For example: EUR or GBP

    mItemDesc String Item description provided during the item registration
    mItemImageUrl String Item image URL provided during the item registration
    mItemDownloadUrl String Item download URL provided during the item registration
    mPaymentId String ID of the payment
    mPurchaseId String Purchase ticket ID used to verify the purchase with the Store IAP server
    mPurchaseDate String Date of purchase
    For example: "2020-11-15 10:31:23"

    mVerifyUrl String Server's URL, which can be used in combination with other parameters to verify the purchase with the IAP server
    mJsonString String Original JSON string

Code snippet

/* Purchase an item */
int ret = iap_galaxyapps_start_payment("item_id", IAP_GALAXYAPPS_COMMERCIAL_MODE, __purchase_cb, NULL);
if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
    /* Error handling */
    return;
}
/* Callback */
static void
__purchase_cb(iap_galaxyapps_h reply, iap_galaxyapps_error_e result, void *user_data)
{
    output_data value = {0,};

    if (result != IAP_GALAXYAPPS_ERROR_NONE) {
        iap_galaxyapps_get_value(reply, "mErrorString", &value.mErrorString);
        /* Error handling */
        return;
    }

    /* Get properties of the purchased item */
    iap_galaxyapps_get_value(reply, "mItemId", &value.mItemId);
    iap_galaxyapps_get_value(reply, "mItemName", &value.mItemName);
    iap_galaxyapps_get_value(reply, "mItemPriceString", &value.mItemPriceString);
    iap_galaxyapps_get_value(reply, "mItemDesc", &value.mItemDesc);

    /* Handle properties */

    return;
}

Get a list of purchased items

To get a list of all items purchased from Galaxy Store, use the iap_galaxyapps_get_purchased_item_list() or iap_galaxyapps_get_purchased_item_list_by_item_ids() method:

  • For iap_galaxyapps_get_purchased_item_list(), pass in the index of the first and last item, the item type, the start and end date, the callback function, and user data as parameters.
  • For iap_galaxyapps_get_purchased_item_list_by_item_ids(), pass in the item IDs separated by comma (,), the callback function, and user data as parameters.

When the reply is delivered, the iap_galaxyapps_reply_cb callback is invoked with the iap_galaxyapps_h object that stores the query results:

  • To get the request result from the iap_galaxyapps_h object, use the iap_galaxyapps_get_value() method.

  • If the request was successful, you can get all the item details from the iap_galaxyapps_h object using the iap_galaxyapps_foreach_item_info() method.

Request

For details, see the iap_galaxyapps_get_purchased_item_list() and iap_galaxyapps_get_purchased_item_list_by_item_ids()

int iap_galaxyapps_get_purchased_item_list(int start_number,
                                           int end_number,
                                           const char *start_date,
                                           const char *end_date,
                                           iap_galaxyapps_reply_cb	reply_cb,
                                           void *user_data)
int iap_galaxyapps_get_purchased_item_list_by_item_ids(const char *item_ids,
                                                      iap_galaxyapps_reply_cb reply_cb,
                                                       void *user_data) 	

Response

typedef void(* iap_galaxyapps_reply_cb)(iap_galaxyapps_h reply, 
                                        iap_galaxyapps_error_e result, 
                                        void *user_data)
  • Common result

    Key Value type

    Description

    mErrorCode int Error code number
    mErrorString String Error message
    mExtraString String Extra result
    mStartNumber int Index of the first item on the list
    mEndNumber int Index of the last item on the list
    mTotalCount int Total number of items based on the first and last item index
  • Purchased item details

    Key Value type

    Description

    mItemId String Item ID number
    This is the same as the item ID used in the request.

    mItemName String Name provided during the item registration in the Seller Portal
    mItemPrice String Item price in a local currency
    mItemPriceString String Currency code + price
    mCurrencyUnit String Device user currency unit
    mCurrencyCode String Currency code
    mItemDesc String Item description provided during the item registration
    mItemImageUrl String Item image URL provided during the item registration
    mItemDownloadUrl String Item download URL provided during item registration
    mType String Item type:
    00: Consumable
    01: Nonconsumable
    02: Nonrecurring subscription
    03: Autorecurring subscription
    10: All

    mPaymentId String ID of the payment
    mPurchaseId String ID of the purchase
    mPurchaseDate String Date of purchase
    For example: "2020-11-15 10:31:23"

    mSubscriptionEndDate String If the item type (mType) is 02 or 03, this is the due date
    mJsonString String Original JSON string

Code snippet

int ret = iap_galaxyapps_get_purchased_item_list(1, 10, "20200101", "20221231", __get_purchased_item_list_cb, NULL);
if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
    /* Error handling */
    return;
}
// item IDs can be obtained by seperating the values returned by the  iap_galaxyapps_get_item_list() with comma(,).
int ret = iap_galaxyapps_get_purchased_item_list_by_item_ids("item1,item2,item3", __get_purchased_item_list_cb, NULL);
if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
    /* Error handling */    
    return;
}
static bool
__foreach_purchased_item(iap_galaxyapps_h handle, void *user_data) {
    output_data value = {0,};

    /* Get properties of the item */
    iap_galaxyapps_get_value(handle, "mItemId", &value.mItemId);
    iap_galaxyapps_get_value(handle, "mItemName", &value.mItemName);
    iap_galaxyapps_get_value(handle, "mItemPriceString", &value.mItemPriceString);
    iap_galaxyapps_get_value(handle, "mItemDesc", &value.mItemDesc);

    /* Handle properties */

    return true;
}

/* Callback */
static void
__get_purchased_item_list_cb(iap_galaxyapps_h reply, iap_galaxyapps_error_e result, void *user_data)
{ 
    if (result != IAP_GALAXYAPPS_ERROR_NONE) {
        char *mErrorString = NULL;
        iap_galaxyapps_get_value(reply, "mErrorString", &mErrorString);
        /* Error handling */
        return;
    }

    /* Retrieve all items contained in the handle */
    int ret = iap_galaxyapps_foreach_item_info(reply, __foreach_purchased_item, NULL);
    if (ret != IAP_GALAXYAPPS_ERROR_NONE) {
        /* Error handling */
        return;
    }

    return;
}

Handling errors

During the IAP process, various errors can occur, for example, due to an unstable network, connection error, invalid account, or invalid product.

If an error occurs, your application receives the iap_galaxyapps_error_e error type in the iap_galaxyapps_reply_cb callback. Handle all errors appropriately.

  • Error Code

    Error Code

    Description

    IAP_GALAXYAPPS_ERROR_NONE

    Successful
    IAP_GALAXYAPPS_ERROR_PAYMENT_IS_CANCELED

    Payment canceled
    IAP_GALAXYAPPS_ERROR_NETWORK_NOT_AVAILABLE

    Network is not available
    IAP_GALAXYAPPS_ERROR_IO_ERROR

    IOException
    IAP_GALAXYAPPS_ERROR_TIMED_OUT

    Timeout exception
    IAP_GALAXYAPPS_ERROR_INITIALIZATION

    Failure during IAP initialization
    IAP_GALAXYAPPS_ERROR_NEED_APP_UPGRADE

    Samsung IAP upgrade is required
    IAP_GALAXYAPPS_ERROR_COMMON

    Error while running IAP
    IAP_GALAXYAPPS_ERROR_ALREADY_PURCHASED

    Error when a non-consumable product is repurchased or a subscription product is repurchased before the product expiration date
    IAP_GALAXYAPPS_ERROR_REQUEST_PAYMENT_WITHOUT_INFO

    Error when payment is requested without bundle information
    IAP_GALAXYAPPS_ERROR_PRODUCT_DOES_NOT_EXIST

    Error when the requested item list is not available
    IAP_GALAXYAPPS_ERROR_CONFIRM_INBOX

    The payment result is not received after requesting payment from the server, and the purchased item list is not confirmed
    IAP_GALAXYAPPS_ERROR_NOT_EXIST_LOCAL_PRICE

    The item is not for sale in the country
    IAP_GALAXYAPPS_ERROR_NOT_AVAILABLE_SHOP

    IAP is not supported in the country
    IAP_GALAXYAPPS_ERROR_INVALID_PARAMETER

    Invalid parameter
    IAP_GALAXYAPPS_ERROR_KEY_NOT_FOUND

    Specified key is not found
    IAP_GALAXYAPPS_ERROR_NOT_SUPPORTED_DEVICE

    The device does not support IAP
    IAP_GALAXYAPPS_ERROR_OUT_OF_MEMORY

    Out of memory
    IAP_GALAXYAPPS_ERROR_PERMISSION_DENIED

    Permission denied

Verify a purchase

This server API enables your server and client app to verify that a specified in-app item purchase and payment transaction were successfully completed. The API returns a JSON object with a successful status and details about a successful transaction and the item or with a failure status. This API can help to prevent malicious purchases and ensure that purchase and payment transactions were successful when the client app experiences network interruptions after an item purchase and payment transaction.

Request

https://iap.samsungapps.com/iap/appsItemVerifyIAPReceipt.as?protocolVersion=2.0&purchaseID={purchaseID}
  • The purchaseID is assigned by Samsung IAP. Your app receives it in the iap_galaxyapps_h object as response of iap_galaxyapps_start_payment() and the key is mPurchaseId.

Response

  • Success

    {
        "itemId" : "item01",
        "paymentId":"ZPMTID20131122GBI0015292", 
        "orderId": "S20200106KRA1908790",  
        "itemName":"Test Pack", 
        "itemDesc":"IAP Test Item. Best value!", 
        "purchaseDate":"2020-11-22 04:22:36",
        "paymentAmount":"9.000", 
        "status":"true", 
        "paymentMethod":"Credit Card", 
        "mode":"REAL", 
    }
    
  • Fail

    {
        "status":"false"
    }
    

Submit the app to Galaxy Store

1. Check the operation mode

After IAP integration, you must check the operation mode before submitting the app.
If you submit the app with IAP_GALAXYAPPS_SUCCESS_TEST_MODE, the users will get all the items for free.
So, before beta release or normal publication, confirm if the operation mode is IAP_GALAXYAPPS_COMMERCIAL_MODE.

2. Submit the app

When you have created an app version that is ready for review testing and normal publication, register the app and its in-app item, and then click Submit.

For more details, see the App Registration Guide.