Skip to content

Adobe AIR native extension (ANE) for Android to purchase in multiple markets

License

Notifications You must be signed in to change notification settings

manjav/air-extension-cross-billing

Repository files navigation

About

air-extension-inappbilling is an Adobe AIR native extension (ANE) to purchase products for multiple Android markets (locals and global).
...........راهنمــــــای فـــــــارسی..........

We prepared 2 type projects template:

  1. Flash Professional(Animate) template for Flash Designers.
  2. Pure Action Script template for Flash Developers to use Flash Builder, Flash Develop or Intellij Idea.

Test Project

It uses Google Play In-app Billing version 3 API.
Supported functionality:

  • purchase of items;
  • restoration of previously purchased items;
  • consumption of items;
  • subscriptions (not tested).

Docs

Please, read docs and try ANE before asking any questions.
http://developer.android.com/google/play/billing/index.html
http://help.adobe.com/en_US/air/extensions/index.html

Step 1 : Insert ANE file into your Adobe AIR Project

Add iabilling.ane file from package folder to your Adobe AIR project.
Tutorial: How to embed ANEs into FlashBuilder, Flash(Animate) and FlashDevelop

Step 2 : Initializing based on selected market:

Insert All uses items into '_items' array.

Get base64key from market console and replace with '==5AMP1E8A5E64KE7=='.
Also if you want add new market, you had to added new case with 'bindeURL' and 'packageURL'.

import com.gerantech.extensions.iab.Iab;
import com.gerantech.extensions.iab.Purchase;
import com.gerantech.extensions.iab.events.IabEvent;
...

// provide all sku items
_items = new Array("my.product.id1", "my.product.id2", "my.product.id3");
var _marketName:String = "google";
var base64Key:String, bindURL:String, packageURL:String;
switch ( _marketName ) {
	case "google":
		base64Key = "==5AMP1E8A5E64KE7==";
		bindURL = "com.android.vending.billing.InAppBillingService.BIND";
		packageURL = "com.android.vending";
		break;

	case "cafebazaar":
		base64Key = "==5AMP1E8A5E64KE7==";
		bindURL = "ir.cafebazaar.pardakht.InAppBillingService.BIND";
		packageURL = "com.farsitel.bazaar";
		break;

	case "myket":
		base64Key = "==5AMP1E8A5E64KE7==";
		bindURL = "ir.mservices.market.InAppBillingService.BIND";
		packageURL = "ir.mservices.market";
		break;

	case "cando":
		base64Key = "==5AMP1E8A5E64KE7==";
		bindURL = "com.ada.market.service.payment.BIND";
		packageURL = "com.ada.market";
		break;
	default:
		trace("BillingManager ::: market name[" + _marketName + "] is invalid.");
		break;
}

Iab.instance.addEventListener(IabEvent.SETUP_FINISHED, iabSetupFinishedHandler);
Iab.instance.startSetup(base64Key, bindURL, packageURL);
...
function iabSetupFinishedHandler(event:IabEvent):void {
	trace("BillingManager ::: iabSetupFinishedHandler", event.result.message);
	Iab.instance.removeEventListener(IabEvent.SETUP_FINISHED, iabSetupFinishedHandler);
	queryInventory();
}

Step 3 : Get all inconsumed purchase items and consume:

Sometimes users can not complete purchase flow cause network problems or other fatal errors. you can restore items after initializing to better user experience.

/**Getting purchased product details, Iab should be initialized first</br>
* if put items args getting purchased and not purchased product details
*/
function queryInventory():void {
	//restoring purchased in-app items and subscriptions
	Iab.instance.addEventListener(IabEvent.QUERY_INVENTORY_FINISHED, iabQueryInventoryFinishedHandler);
	Iab.instance.queryInventory();
}
...
function iabQueryInventoryFinishedHandler(event:IabEvent):void {
	Iab.instance.removeEventListener(IabEvent.QUERY_INVENTORY_FINISHED, iabQueryInventoryFinishedHandler);
	if ( !event.result.succeed ) {
		trace("iabQueryInventoryFinishedHandler failed to finish.");
		return;
	}

	// consume all consumable items
	/*for each(var k:String in _items) {
		var purchase:Purchase = Iab.instance.getPurchase(k);
		if( purchase == null || purchase.itemType == Iab.ITEM_TYPE_SUBS )
			continue;
		consume(purchase.sku);
	}*/
}

Step 4 : Making purchase:

When user tapped or clicked on 'BUY' button call purchase method. dont forget in order to purchase that item must be consumed.
For consumable items you should consume items immediatly after purchase finished in listener method.

// making the purchase, Iab should be initialized first
Iab.instance.addEventListener(IabEvent.PURCHASE_FINISHED, iabPurchaseFinishedHandler);
Iab.instance.purchase(sku, Iab.ITEM_TYPE_INAPP, payload);
...
function iabPurchaseFinishedHandler(event:IabEvent):void {
	trace("BillingManager ::: iabPurchaseFinishedHandler", event.result.message);
	Iab.instance.removeEventListener(IabEvent.PURCHASE_FINISHED, iabPurchaseFinishedHandler);
	if (!event.result.succeed) {
	    trace(event.result.response, event.result.message);
	    return;
	}
	var purchase:Purchase = Iab.instance.getPurchase(event.result.purchase.sku);
	if( purchase == null )
	    queryInventory();
	else // if you want immediatly consume after purchase
	    consume(purchase.sku);
}

Step 5 : Consume purchase items:

For non-consumable item not needs to using this method.

function consume(sku:String):void {
	trace("BillingManager ::: consume", sku);
	Iab.instance.addEventListener(IabEvent.CONSUME_FINISHED, iabConsumeFinishedHandler);
	Iab.instance.consume(sku);
}

function iabConsumeFinishedHandler(event:IabEvent):void {
	trace("BillingManager ::: iabConsumeFinishedHandler", event.result.message);
	Iab.instance.removeEventListener(IabEvent.CONSUME_FINISHED, iabConsumeFinishedHandler);
	if (!event.result.succeed) {
	    trace("iabConsumeFinishedHandler failed to consume:", event.result.message);
	    return;
	}
}

Step 6 : Manifest Edition :

Add Billing permissions based on selected market Add the following lines to your AIR Aplication-app.xml file inside <manifestAdditions>

<!-- In APP Billing permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<!--For Google-->	<uses-permission android:name="com.android.vending.BILLING" />
<!--For CafeBazaar-->	<!--<uses-permission android:name="com.farsitel.bazaar.permission.PAY_THROUGH_BAZAAR" />-->
<!--For Myket-->	<!--<uses-permission android:name="ir.mservices.market.BILLING" />-->
<application android:enabled="true" >
     <activity android:name="com.gerantech.extensions.IabActivity"
	  android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
	  android:background="#30000000"
	  android:screenOrientation="portrait"
	  android:configChanges="orientation|keyboardHidden" />
</application>

Add extension id Extension ID: com.gerantech.extensions.iabilling

<extensions>
     <extensionID>com.gerantech.extensions.iabilling</extensionID>
</extensions>

Testing

http://developer.android.com/google/play/billing/billing_testing.html

Misc

ANE is build for AIR 18.0+, in order to rebuild for another version do the following:

  • edit "air\extension.xml" and change 18.0 in very first line to any X.x you need;
  • edit "package.bat" and in the very last line change path from AIR 18.0 SDK to any AIR X.x SDK you need;
  • execute "package.bat" to repack the ANE.