Selling digital goods

The Payment Service classes are included in the BlackBerry 10 Native SDK. Before you set up the Payment Service, you must register your app and its digital goods in the BlackBerry World storefront. To learn more, see Registering with BlackBerry World.

To get started adding digital goods to your app, see Setting up the Payment Service.

Initiating a purchase

After you create a payment instance in your app, you can initiate a purchase in your app. You receive a response to this request when a user completes the purchase process (which may include steps such as signing in to a BlackBerry ID and setting up a preferred payment method).

When you request a purchase, only the ID or SKU of the digital good to be purchased is required; you don't need to provide both. If the ID and SKU are both provided, then the ID is used. To use the SKU, you must pass an empty string for the digitalGoodId.

The following code sample requests a purchase using the paymentservice_purchase_request() function.

To analyze the results of the paymentservice_purchase_request(), you must first use the paymentservice_event_get_response_code() function to verify if the request finished. If the Payment Service server is unable to finish the request, an error is returned.

If an error is returned, you can use paymentservice_event_get_error_info() and paymentservice_event_get_error_text() to present a dialog box or toast to your user. If no error is returned, you can use the paymentservice_event_get_metadata() function to present information about the successful purchase to the user.

do_purchase(int selected_index, char** result_str)
{
    unsigned request_id = 0;
    purchase_params_t params = 
        *available_purchase_info[selected_index];

    paymentservice_purchase_request(params.digital_good_id, 
        params.digital_good_sku, 
        params.digital_good_name,
        params.metadata, 
        params.purchase_app_name, 
        params.purchase_app_icon, 
        get_window_group_id(), 
        &request_id);

    sprintf(*result_str, 
        "Sent purchase request. ID: %d\n", 
        request_id);
}

When you request a purchase, the digital good name and the purchase metadata are optional parameters, and you might use them in the following scenarios.

Using a single ID, name, or SKU to represent multiple digital goods

If it is impractical to create a unique name and SKU for each of your digital goods, you can use the same name and SKU for multiple digital goods. Any digital good that is part of a group of digital goods with the same name and SKU must be registered as consumable in the BlackBerry World vendor portal. Static digital goods can be sold only once, consumable digital goods can be sold many times. For more information about registering different types of digital goods, see Registering with BlackBerry World.

Information that differentiates each digital good in the group (for example, which level was purchased) must be placed in the metadata field.

The technique of creating a single name and SKU for multiple digital goods lets you update the purchase options without submitting a new version of your app.

For example, if a game sells additional levels at a single price point, you can use a generic digital good with the name "My game level" for all such levels. When a user makes a purchase, the game app should override "My game level" with the name of the level that the user purchased. This approach makes sure that the users are aware of exactly what they are purchasing on the purchase confirmation screen.

do_purchase(int selected_index, char** result_str)
{
    unsigned request_id = 0;
    purchase_params_t params = 
        *available_purchase_info[selected_index];

    // Request a purchase using the ID, SKU, name, and metadata.
    // The metadata specifies unique information about this
    // digital good, which is in group of digital goods that 
    // share the same ID and SKU. You must pass a metadata 
    // argument that allows you to differentiate between digital 
    // goods that reference the same SKU.

    paymentservice_purchase_request(params.digital_good_id, 
        params.digital_good_sku, 
        params.digital_good_name,
        params.metadata, 
        params.purchase_app_name, 
        params.purchase_app_icon, 
        get_window_group_id(), 
        &request_id);

    sprintf(*result_str, 
        "Sent purchase request. ID: %d\n", 
        request_id);
}

Using specific purchase metadata

You can use the same name and SKU for multiple digital goods and use the metadata to handle purchases of this digital good. When you request a purchase in your app, you can pass a metadata argument that allows you to differentiate between digital goods that reference the same SKU.

For example, if a book vendor offers multiple titles at a single price point ($4.99) and represents the titles on the vendor portal as a single digital good ("Romance novel"), the ISBN of the book and the title of the book can be retrieved as purchase metadata and displayed on the purchase confirmation screen instead of the digital good name.

Responding to a purchase

Your app can listen for a Payment Service event by calling bps_get_event(). After an event is received, you should determine whether it's a Payment Service event by calling bps_event_get_domain() and paymentservice_get_domain().

You can determine event codes by calling bps_get_event_code(). The PURCHASE_RESPONSE response code indicates that the event was generated in response to a purchase request. The GET_EXISTING_PURCHASES_RESPONSE response code indicates that the event was generated in response to a request for the past purchases that the user made in the app (a call to paymentservice_get_existing_purchases_request()).

A response code of FAILURE_RESPONSE indicates that the request was unsuccessful. If an error is thrown, you can get more information on the error:

You can find the ID and SKU of the digital good.

To present information about the successful purchase to the user, you can use the paymentservice_purchase_arguments_get_metadata() function.

Checking for past purchases

If your app needs a list of digital goods that a user already purchased (for example, to avoid offering a digital good that the user already owns), you can retrieve the existing purchases that a user made. These purchases include the purchases that a user made before an upgrade and the purchases that a user made after your app was removed and downloaded again.

The following code sample requests the list of existing purchases by using the paymentservice_get_existing_purchases_request() function, passing in a Boolean value to refresh the data from the server.

The paymentservice_get_existing_purchases_request() function accepts a parameter called allow_refresh, which is a Boolean value that indicates whether the list of past purchases should be refreshed when a request is made. A value of true indicates that data is refreshed from the server, and a value of false means that a cached list of purchases is returned.

do_get_existing(int selected_index, char** result_str)
{
    unsigned request_id = 0;
    if (selected_index == GET_EXISTING_REFRESH_FALSE) {

        paymentservice_get_existing_purchases_request(false, 
            get_window_group_id(), 
            &request_id);

    } else if (selected_index == GET_EXISTING_REFRESH_TRUE) {

        paymentservice_get_existing_purchases_request(true, 
            get_window_group_id(), 
            &request_id);
    }

    sprintf(*result_str, 
        "Sent getExistingPurchases request. ID: %d\n", 
        request_id);
}

If an error is thrown, you can use the following functions to get more information:

Best practices

To minimize the number of requests to the Payment Service and limit your app's network and data usage, you can provide a way for the user to refresh existing purchases from the server in your UI. You can implement a button or action that allows the user to restore past purchases. You can request existing purchases with a option to get purchases from the BlackBerry World server when the button is tapped.

If you can't add a refresh option to your UI, you can request existing purchases from the BlackBerry World local cache (on the device) when your app starts. If the local cache is stale, the purchase history is automatically retrieved from the server.

You should store a record of the purchases that a user makes because digital goods represent features or goods in your app. You can use a QSettings object. The QSettings class provides persistent platform-independent application settings across sessions. You can use the values in QSettings to determine which features of your app should be available. You should update these settings when successful purchases are made, so that the user can use the new features right away.

There are a few scenarios where your QSettings can become out of sync:

  • The user makes a purchase on one device (for example, a BlackBerry PlayBook) then tries to use the purchase on another device (for example, a BlackBerry 10 device).
  • The user restores a device to a backup made before certain purchases were made.

For these scenarios, it is a good practice to either provide a manual way for users to retrieve past purchases (by using a button or menu item on the screen) or perform periodic requests to get purchases from the BlackBerry World server.

Last modified: 2014-09-30



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus