In-app Purchases

Validate cross platform purchases with a billing process

Gamedonia provides a way for your game to get revenue through in-app purchases thanks to the integration with different stores.

Our in-app purchases system includes a fraud protection mechanism to avoid fraudulent transactions. The validation is done both on the client side and on the server side. Any suspsicious transactions will be automatically rejected.

Gamedonia calls will only work under a valid Gamedonia session. This means there needs to be a user logged in with Gamedonia. The main exceptions are, for obvious reasons, creating and logging users in.

Create a store product

First of all you will need to create and configure your product items at the corresponding store of your target devices. Follow these simple guides to create in-app purchase products depending on the platform you are developing on:

iOS

Follow this iOS guide to setup an app enable for In-App Purchases.

Android

To be able to operate with real products on your Android app, you will need to at least upload an Alpha or Beta APK that only will be available to whitelisted users.

Follow this Android guide on how to setup your products with Google Play.

Setup the project

To enable In-app purchases in your project, you need a previous configuration.

Unity

Add the GamedoniaStoreInAppPurchases script to your Gamedonia game object. See the next screenshot on how your Game object should look like with this script ( it's possible that you have other scripts attached to the Gamedonia game object. It's ok, you need them for other Gamedonia features). The script is located under Assets/Plugins/Gamedonia.

Set the Android Publickey (Public key assigned when setting up Google In-App Purchases).

You don't need to set this field if you're developing for iOS only.

Other SDKs

When using any of the other Gamedonia SDKs, you will need to initialize in-app purchases at your code like this:

TGDOptions options(true, false, false);
options.androidPublickey = CCString::create("My-Android-Publickey");

GamedoniaSDK::initializeWithOptions("My-Gamedonia-API-Key", "My-Gamedonia-Secret-Key", "http://api.gamedonia.com:8080", "v1", &options);
			// Register as delegate
    		[Gamedonia purchase].delegate = self;
		
import com.gamedonia.sdk.GamedoniaInAppPurchases;

...

var options:GDOptions = new GDOptions();
options.inAppPurchases = true;
Gamedonia.initializeWithOptions( "your_api_key", "your_secret", "http://api.gamedonia.com", "v1", options );

TODO: Not implemented yet.

Android manifest

You need to add these lines to your AndroidManifest.xml file in order to enable in-app purchases for your game.

<uses-permission android:name="com.android.vending.BILLING">
</uses-permission>
<activity android:name="com.gamedonia.inapppurchase.BillingProxyActivity" android:theme="@style/Theme.Transparent"></activity>
<service android:name="com.gamedonia.inapppurchase.UnityAndroidInterface">
</service>

TODO: Not implemented yet.

Take into account that Flash Builder modifies your bundle ID and sets it like this: air.your.package.name, so your app in Google Play Store will need to have that same name in order to work.

<application>
	<activity android:name="com.gamedonia.inapppurchase.BillingProxyActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"></activity>

	<meta-data android:value="APP_KEY:your_google_license_key" android:name="APP_KEY"></meta-data>
	<service android:name="com.gamedonia.inapppurchase.BillingService" />
</application>

TODO: Not implemented yet.

Set Non-consumable products

You can define two kinds of products at the store:

  • Consumable products: This kind of product can be purchased multiple times. It's useful for items like life potions, boosts... Disposable items that can be used and purchased again and again.
  • Non-consumable products: This kind of product can only be bought once. An example would be unlocking new levels.
string [] keys = new string[1];
keys[0] = "PRODUCT_ID";
GamedoniaStore.SetNonConsumables(keys, keys.Length);
var productsList:Array = new Array( "PRODUCT_ID" );
GamedoniaInAppPurchases.instance.setNoConsumableProducts(productsList);

Request product details

You can get detaiils from all the products you have at the store by calling the RequestProducts method. For each product, you will get its description, price, etc.

The response to this call is obtained through a callback method registered to an event. After creating the callback function, a petition to request product details can be done. Note that you can request details about many products at the same time.

private void OnProductsRequested() {
    if (GamedoniaStore.productsRequestResponse.success) {

        foreach (KeyValuePair<string, Product> entry in GamedoniaStore.productsRequestResponse.products) {
            Product product = (Product)entry.Value;
	    //TODO process the products
        }
    } else {
            //TODO process request productos failure
    }
}
GDInAppService reqService = new GDInAppService();
reqService.RegisterEvent += new InAppEventHandler(OnProductsRequested);
GamedoniaStoreInAppPurchases.AddRequestService(reqService);
string [] keys = new string[1];
keys[0] = "PRODUCT_ID";
GamedoniaStore.RequestProducts(keys, keys.Length);
void MyClass::onReceiveProductRequest(CCArray *products) {
    if (products->count() > 0) {
        CCDictionary* product = dynamic_cast<CCDictionary*>(products->objectAtIndex(0));
        //TODO: process the product details here
    } else {
        //TODO: the product dooes not exist
    }
}
CCArray *products = new CCArray();
products->addObject(productId);
GamedoniaSDKInAppPurchase::getInstance()->requestProducts(products, this, gamedoniaPurchaseProductsRequested_selector(MyClass::onReceiveProductRequest));
			NSSet *productsList = [NSSet setWithObject:@"PRODUCT_ID"];
            [[Gamedonia purchase] requestProducts:productsList];
// Callback
protected function onProductsRequested(e:GamedoniaStoreEvent):void {

	trace ("onProductsRequested (" + e.type + "): " + e.products);
}
// Register event
GamedoniaInAppPurchases.instance.addEventListener(GamedoniaStoreEvent.PRODUCTS_REQUESTED, onProductsRequested);
// Request
var productsList:Array = new Array( "PRODUCT_ID" );
GamedoniaInAppPurchases.instance.requestProducts(productsList);

TODO: Not implemented yet.

The "PRODUCT_ID" may vary between Android, iOS or other platforms. Find this information in the store provider site.

Purchase a product

Once everything is set up, the final step to buy a product is as simple as calling a method. The method to purchase is BuyProduct with the exact id of the product on the store.

To obtain a response to this method, you will need to register to an event to be notified when a purchase is completed.

private void OnProductPurchased() {
    PurchaseResponse purchase = GamedoniaStore.purchaseResponse;
    //TODO: process the purchase details here
}
GDInAppService buyService = new GDInAppService();
buyService.RegisterEvent += new InAppEventHandler(OnProductPurchased);
GamedoniaStoreInAppPurchases.AddPurchaseService(buyService);
GamedoniaStore.BuyProduct("PRODUCT_ID");
void MyClass::onProductPurchased(TGDPaymentTransaction *transaction) {
    if (transaction->success) {
        //TODO: process the purchase details here
    } else {
        //TODO: the product failed to purchase
    }
}
GamedoniaSDKInAppPurchase::getInstance()->buyProduct("PRODUCT_ID", this, gamedoniaPurchaseProductPurchased_selector(MyClass::onProductPurchased));
			[[Gamedonia purchase] buyProductIdentifier:@"PRODUCT_ID"];
// Callbacks
protected function onProductPurchased(e:GamedoniaStoreEvent):void {

	trace ("onProductsPurchased (" + e.type + "): " + e.products);
}

protected function onPurchaseFailed(e:GamedoniaStoreEvent):void {

	trace ("onPurchaseFailed (" + e.type + "): " + e.products);
}
// Register events
GamedoniaInAppPurchases.instance.addEventListener(GamedoniaStoreEvent.PRODUCT_PURCHASED_OK, onProductPurchased);
GamedoniaInAppPurchases.instance.addEventListener(GamedoniaStoreEvent.PRODUCT_PURCHASED_KO, onPurchaseFailed);
// Buy
GamedoniaInAppPurchases.instance.buyProduct("PRODUCT_ID");

TODO: Not implemented yet.