Weekend Coder: Utilizing in-app purchases

By Brian Scheirer on 17 Aug 2013 03:28 pm EDT

I have tried a few pricing models, free only, free w/ ads, free version/paid version, etc but the best I've found is using the "freemium" model. The idea behind freemium is the app is initially free but to access additional portions or to gain extra ability in the app is to pay real money. This same methodology can be applied to already paid apps, thus recreating premium plus apps. Not only have I found this as the most financially beneficial but end users seem to like it the best too and it is not that difficult to implement. To add in-app purchases we'll use the BlackBerry Payment Service.

Few things before I get started, this is not an exhaustive sample on in-app purchases, in fact I am only going to go through a purchase of a consumable good. In app purchases have multiple models within it such as subscriptions and non-consumable goods. Implementing the others are much different but I’ll leave that to you to implement based off your own needs.

Though there is already a really good BlackBerry sample here, there are just too many bells and whistles in there that I find to be annoying. This sample will use the PaymentServiceControl.cpp and .hpp files from that sample but I will strip out the unnecessary parts. Plus I'll explain everything along the way. So go ahead and grab those files from the sample mentioned above.

Now that you have the source of that code pulled, let’s create a new project. I called my "PaymentTest." First let’s added the necessary library to our .pro file:

LIBS += -lbbplatform

Next, there are few things we need to add to the main.cpp file of our app, first a couple includes:

#include "PaymentServiceControl.hpp"

#include <bb/platform/PaymentManager>

These includes are to call to the cpp/hpp file we grabbed from BlackBerry's sample and to the built-in Payment Manager API.

Add the platform namespace:

using namespace bb::platform;

Then within the main function a few more lines of code fromt he sample:

PaymentManager::setConnectionMode(PaymentConnectionMode::Test); // Register our class that wraps the C++ PaymentService interface with QML so that we // can make calls into the PaymentService and get results, through QML. qmlRegisterType("com.sample.payment", 1, 0, "PaymentServiceControl");

The setConnectionMode is to toggle between "Test" and "Production"... keep it in Test for now so you can test, and you'll change to production before submitting to BlackBerry World (more on that in a bit). And as you can see from the comment in the sample, the qmlRegisterType is to access the Payment Service from QML.

For this basic example nothing else needs to be done in C++, so we can head over to QML for the rest of the app. Let’s create a testing UI in our main.qml:

import bb.cascades 1.0 Page {     Container {         Button {             text: "Buy 200 Coins"             onClicked: {                             }         }         Label {             id: coinCount             text: "0"         }     } }

So we would like for when we press the button the user can add 200 coins to their coin count Label (and obviously use the payment system to do so). Let’s declare our payment class we defined in our C++ file:

import com.sample.payment 1.0

And add the PaymentServiceControl as an attached object to the Page (taken from main.qml of the BlackBerry sample) and delete out the signal actions for each function. So we’d have the following:

attachedObjects: [         PaymentServiceControl {             id: paymentControl             property string id             property string sku             property string name             property string metadata             onPriceResponseSuccess: {             }             onPurchaseResponseSuccess: {                             }             onExistingPurchasesResponseSuccess: {             }             onSubscriptionTermsResponseSuccess: {             }             onCancelSubscriptionResponseSuccess: {             }             onCheckStatusResponseSuccess: {             }             onInfoResponseError: {             }         }     ]

The only function we’ll use is onPurchaseResponseSuccess{} and we want to tie that to our Button:

//... Button {     text: "Buy 200 Coins"    onClicked: {          paymentControl.id = "123456789"          paymentControl.sku = "SKU-1"          paymentControl.name = "200 Coins"          paymentControl.metadata = "200 Coins"          paymentControl.getPrice(paymentControl.id, paymentControl.sku)          paymentControl.purchase(paymentControl.id, paymentControl.sku, paymentControl.name, paymentControl.metadata)      } } //... onPurchaseResponseSuccess: {    var coins = Number(coinCount.text);    coinCount.text = coins + 200;   }

If you’ve done this correctly you should get the following sequence of events:

Few things to note now… We have made a fake app, with fake SKUs for in app purchases, fake ID, and we are running in a test environment. So when you want to go live you need to do the following steps.

1. Change the Payment manager in your main.cpp from Test to Production:

PaymentManager::setConnectionMode (PaymentConnectionMode::Production);

2. Create Digital Goods within Manage Products in your BlackBerry Vendor Portal:

3. Replace the SKU, ID, etc in your main.qml with actual information created from your Vendor account. Note the id will be generated after you create the good, so you will need to go back into the goods and click on it to see the id.

Now if you run the app with these changes it will no longer allow you to make the purchase and get an App World error. That is because it is trying to connect to the Payment server and if your app wasn’t downloaded through BlackBerry World you will get errors. But I assure you, it is ready and once it has been approved everything should work correctly.

Final notes… Realize I have told you no mechanism to save coin counts here so you make sure you do that in you live app or customers will be very mad if they buy coins and they aren’t saved once they close the app. Also be aware of the different license types of your virtual goods. Such as coins would be Consumable meaning the system will allow users to buy them over and over. Where as if you are selling more levels of a game that would be Non-Consumable as once the user has purchased the “level pack” they won’t be allowed to purchase it again.

Reader comments

Weekend Coder: Utilizing in-app purchases


Мy вroтнer'ѕ ғrιeɴd Вryαɴ ѕнowed мe нow Ι cαɴ мαĸe ѕoмe cαѕн wнιle worĸιɴɢ ғroм мy нoмe oɴ мy coмpυтer... ɴow Ι eαrɴ 84.46 bucks every нoυr αɴd Ι coυldɴ'т вe нαppιer... Вeғore тнιѕ joв Ι нαd тroυвle ғιɴdιɴɢ joв ғor мoɴтнѕ вυт ɴow wнeɴ Ι ɢoт тнιѕ ɢιɢ Ι woυldɴ'т тrαde ιт ғor ɴoтнιɴɢ... W­WW.ⅮAY37.Ⅽ­OⅯ

I understand the money making model with in-app purchases, but I really despise them with a lot of the new games out today. I would most rather pay for a full version than be nickel-and-dimed. And please don't state a game is free when in fact it's just a lure to get you to play then pay.

Posted via CB10

I think though, on average - games make more with the lure and pay model.

I don't do in app or ads in my apps - either it's free or gimme 99 cents. But I also make very little cash so...

Posted via CB from my LE

Developing apps takes time and as the old saying goes: "time equals money." The market did this to themselves. They wanted everything to be free. Developers responded by giving you taste for free and asking for you to pay once you were hooked.

I don't see the trend changing anytime soon. So if this is what it is, I'm just here to show devs how to take advantage of the functionality.

Posted via CB10

Only way to properly show code in the browser makes it not show well on the app. If you look on a desktop or in the browser it is much more readable.

Plus considering you need to be on a real computer to code, not sure if this is a big deal, however if you have suggestions to fix let me know

Posted via CB10

I develop games for BlackBerry 10 with cocos2dx with in app purchase, but I don't understand about .pro file and .qml because when the project from cocos2dx import to the qnx ide, there is no pro and qml. I tried to add manual pro and qml but cause error.. there is any idea? Thx

Posted via CB10

I would really like to see this method applied to allow free trial apps. Almost every app for Windows Phone allows free trial of an app with the option to purchase but most apps for BlackBerry 10 won't let you try before you buy which is very frustrating! I purchased ARKick yesterday only to find out it wasn't what I was looking for so I just dumped 3 bucks down the toilet. Why wasn't I allowed to try it first? This will make consumers think twice before dropping 3 bucks and developers will lose money because of it. Please make App World more like the Windows Phone store where the consumer has the option for a trial before purchasing!

Posted via CB10

I actually hate paying money in-app, I'd prefer to buy it fully from the store. I feel more secure that way, too.

Posted via CB10

Using in app payments through BlackBerry Payment Service goes through BlackBerry World, therefore just as secure. Uses the same payment system (paypal, carrier billing, cc, etc).

Posted via CB10

Nice article. But I am still a little bit puzzled about the "virtual" goods. A much more frequent use case it to offer the posibility to buy a digital good, like downloading songs, plug-ins or e-books. It seems that BlackBerry does not offer any solution to developers for selling digital goods...

Sure you can do it but it's a bit more complex. You would set up one consumable digital good for each price point. Say for instance "99cent song" as one... once the user buys "99cent song" you would fire a signal that says purchase has been made AND it would be up to you to say download song 1 (rather than song 2 or 3 or 4 etc). Again that's on you to make the song/book/plug-in identifier along with the purchase, shouldn't be too difficult.

Posted via CB10

Thanks for your answer! The problem is that I only get a signal but I need to have a server and provide my own authentication method to offer the download in a secure way.