Selling digital goods

How to

Sell digital goods that you offer in your app.



paymentservice_request_events(0);           // 0 indicates that all events
                                            // are requested

paymentservice_set_connection_mode(true);   // Allows local testing

purchase_arguments_t *args = NULL;


paymentservice_purchase_arguments_set_digital_good_id(args, "ID-Digital-Good-1" );
paymentservice_purchase_arguments_set_digital_good_sku(args, "SKU-Digital-Good-1");
paymentservice_purchase_arguments_set_digital_good_name(args, "Digital Good 1");
paymentservice_purchase_arguments_set_metadata(args, "Metadata for sample purchase");
paymentservice_purchase_arguments_set_app_name(args, "Payment sample app");
paymentservice_purchase_arguments_set_app_icon(args, "");
paymentservice_purchase_arguments_set_group_id(args, get_window_group_id());
paymentservice_purchase_arguments_set_vendor_content_id(args, "ID-vendor-content");
paymentservice_purchase_arguments_set_vendor_customer_id(args, "ID-vendor-customer");
paymentservice_purchase_arguments_set_extra_parameter(args, "extrakey1", "extraval1");
paymentservice_purchase_arguments_set_extra_parameter(args, "extrakey2", "extraval2");
paymentservice_purchase_arguments_set_extra_parameter(args, "extrakey3", "extraval3");

if (paymentservice_purchase_request_with_arguments(args) 
        fprintf(stderr, "Error: purchase request failed.\n");


unsigned request_id = 0;

bps_event_t *event = NULL;
bps_get_event(&event, -1);        // -1 means that the function blocks
                                  // until an event is received

if (event) {
    if (bps_event_get_domain(event) == paymentservice_get_domain()) {
        if (SUCCESS_RESPONSE == 
            paymentservice_event_get_response_code(event)) {
                if (PURCHASE_RESPONSE == bps_event_get_code(event)) {
                    // Handle a successful purchase here
                    char* digital_good =
                       paymentservice_event_get_digital_good_id(event, 0);
                    char* digital_sku =
                       paymentservice_event_get_digital_good_sku(event, 0);
                    // ...

                } else {
                    // Handle a successful query for past purchases here
                    int numPurchases =
                    // ...
        } else {
            int error_id = paymentservice_event_get_error_id(event);
            const char* error_text =
            fprintf(stderr, "Payment System error: ID: %d  Text: %s\n",
                error_id, error_text ? error_text : "N/A"); 

Build requirements

You must include the following header files from the BlackBerry Platform Services (BPS) library:

#include <bps/bps.h>
#include <bps/paymentservice.h>

This solution requires that you register any digital goods that you want to make available in your app in the vendor portal for the BlackBerry World storefront.


You can create apps that offer digital goods for your users to download. You might offer additional levels for a game, or premium content for other types of apps. You can use the Payment Service to make digital goods available for purchase in your apps.

Initialize the BlackBerry Platform Services library

First, you must initialize the BlackBerry Platform Services library by calling bps_initialize(). When you initialize the library, you can call other functions in the BlackBerry Platform Services library, including Payment Service functions. You can then call paymentservice_request_events() to start receiving Payment Service events.

Set the connection mode

It's a good idea to set your app's connection mode to local. The default connection mode is network, which means that purchase requests are sent to the Payment Service servers. When you use this mode, your app receives the purchase responses and results, and you might incur charges for accidental purchases. Local connection mode is useful when you test your app because you won't be charged for digital goods when you use this mode. To switch to local connection mode, call paymentservice_set_connection_mode() and pass in the argument true. When the connection mode is set to local, your app receives a simulated purchase response and purchase result. You should remove all calls to paymentservice_set_connection_mode() when your app is ready for public distribution, so that purchase requests are processed correctly.

Specify parameters for the digital good

Next, you need to specify the parameters for the digital good that a user can purchase. To do that, you can use the purchase_arguments_t structure, the purchase_arguments_create function, and the various paymentservice_purchase_arguments_set functions. Create a pointer for the purchase_arguments_t structure. In our example, we use purchase_arguments_t *args = NULL; to do that. Use the purchase_arguments_create function to change the pointer from NULL to point to the purchase_arguments_t structure. To populate the purchase_arguments_t structure with the parameters for the digital good, call the paymentservice_purchase_arguments_set functions and pass in the pointer. The parameters should match those that you register with BlackBerry World.

You might notice that the get_window_group_id() function is passed in the paymentservice_purchase_arguments_set_group_id function, but is not declared in the code sample. The get_window_group_id function is a user-defined function that gets the app's unique process ID. The process ID is then sent to the Payment Service, which assigns a unique number to the digital good that is used to display dialog boxes in the app.

Initiate the purchase

To initiate the purchase of the digital goods, call paymentservice_purchase_request_with_arguments and pass in the pointer to the purchase_arguments_t structure.

Respond to events

Your app can now 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(). An event code of PURCHASE_RESPONSE indicates that the event was generated in response to a purchase request. An event code of GET_EXISTING_PURCHASES_RESPONSE 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()).

Each Payment Service event also includes a response code, which you can determine by calling paymentservice_event_get_response_code(). A response code of SUCCESS_RESPONSE indicates that the request that generated the event was successful, and a response code of FAILURE_RESPONSE indicates that the request was unsuccessful. See the full list of events that the Payment Service generates.

When you know the type of Payment Service event that was received and the response code of the event, you can respond to the event any way you want. For example, if the event indicates that a purchase request was successful, you might want to retrieve purchase information, such as the ID or SKU of the digital goods (by calling paymentservice_event_get_digital_good_id() or paymentservice_event_get_digital_good_sku()), and act on that information accordingly. If the event indicates that a request for past purchases was successful, you might want to retrieve the number of past purchases that the user made (by calling paymentservice_event_get_number_purchases()). You can also respond to events that indicate that a request was unsuccessful and use paymentservice_event_get_error_id() and paymentservice_event_get_error_text() to get information about the error.

Nice to know

When you specify the parameters for digital goods that users can purchase, you don't need to specify both the ID and the SKU; you can provide one or the other. If you provide both the ID and the SKU, the ID takes precedence, and the SKU is used only if the digital goods can't be located on the Payment Service server using the ID.

Last modified: 2014-05-14

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

comments powered by Disqus