In-App Purchases?


#1

How to Implement in-App purchases that is both for android and ios…?

I followed http://www.plungeinteractive.com/blog/implementing-in-app-purchases-on-ios-games-based-on-cocos2d-x-part-2/#comment-102 this but it is not complete and it is just for Ios…


#2

Would one of the extensions be suitable? Flurry Wrapper or Chartboost? I’ve not tried this yet but it is on my to do list, would be interested in finding out the best way to do cross-platform IAP myself.


#3

i dont have idea about them…Is there any way to implement IAP by using uikit? I have idea that i should be do like calling methods to cross platform like c*+ to obj-c, obj-c to c*+ and c++ to java…but it is messy :confused:


#4

I don’t think anything like this exists… at least I haven’t found it. The problem comes from the fact that you need different IAP code for each Android app store, and they all work differently. It’s quite a bit of work to support all app stores, but unfortunately that seems to be the only solution as of now.

For my projects I support IAP on Apple App Store (easy peasy to implement), Google Play (really quite tough), Amazon App Store (easy), and Samsung Apps (not too bad). The only one which was a real nuisance to implement was Google Play, for which I used this helper library: https://github.com/robotmedia/AndroidBillingLibrary

Hope that helps,

Ben


#5

Hmm can u tell me how you support IAP on app Store? for android i will see your link :slight_smile:


#6

You should use the Apple StoreKit libraries. Read the docs here: http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction/Introduction.html

Ben


#7

I know but the problem is it is in obj-c but cocos2dx is in c++.How can i configure it using storekit?


#8

You can run Objective-C alongside C++ in the same file just fine. I suggest you read some of the introduction docs as this kind of stuff is covered in the first few sections.

Good luck!

Ben


#9

Ben Ward wrote:

You can run Objective-C alongside C++ in the same file just fine. I suggest you read some of the introduction docs as this kind of stuff is covered in the first few sections.
>
Good luck!
>
Ben

In my latest game i implemented inapp purchases for both iOS and Android.
The biggest problems i had were the differences between iOS and Android purchases.
On iOS a lot is handled by Apple and on Android you have to handle most of the stuff yourself.
For example:

Restoring purchases:
Android: No need for this, you can check all purchases online without log on.
iOS: You need to manually restore purchases, the user will need to input username/password

Outstanding purchased:
Android: You need to check these at startup, it’s the same mechanism as restoring because in Android you control the lifecycle
iOS: will push outstanding purchases to the app automatically.

Product lifecycle
Android: You are in control, all items are consumables (with the 3.0 billing api)
iOS: lifecycle is handled by store/apple

If i have some sparetime this evening i will try to post my code.


#10

@edvin thank you…please post your code i m a newbie in cocos2dx i will be very thankful to you…:slight_smile:


#11

Check here: http://www.cocos2d-x.org/news/79


#12

gamier champ wrote:

@edvin thank you…please post your code i m a newbie in cocos2dx i will be very thankful to you…:slight_smile:

I have attached my code (zip file).

It’s not 100% documented but maybe it will help you implement te purchases.
For my next project i will look at Soomla.


#13

Can you please tell me how and where to call the functions.
Thank you in advance


#14

Muniraj Sunderavel wrote:

Can you please tell me how and where to call the functions.
Thank you in advance

Hi,

I will try to write a small tutorial this weekend but i’m quite busy at the moment.:slight_smile:


#15

I am eagerly waiting for your reply.


#16

Muniraj Sunderavel wrote:

I am eagerly waiting for your reply.

Sorry for the late reply, i was ill this weekend :frowning:
I’ll try to copy and paste some of my code in the thread this evening.
B.t.w. you could also check the soomla library, i intend to use this one next time.


#17

Thanks for the reply.
Soomla is very detailed and I dont want a detailed store like soomla.
Simple in-app purchase is required.
I tried both your games (ios and android) and need similar in-app purchases.
It will be very helpful of you.
Thank you


#18

Muniraj Sunderavel wrote:

Thanks for the reply.
Soomla is very detailed and I dont want a detailed store like soomla.
Simple in-app purchase is required.
I tried both your games (ios and android) and need similar in-app purchases.
It will be very helpful of you.
Thank you

This is what i use in my gamesettingssingleton, the code is for setting up the billing (check for outstanding purchases etc)

`static void loadSKUItemsHandler(int error)
{
if (error == GoogleBilling::LOADSKUITEMS_ITEMS_YES)
{
CCLog(“Billing: Inventory loaded”);
GameSettingsSingleton::_billing = true;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
CCLog(“Billing: Check if full version is purchased”);
if (GoogleBilling::Billing::isPurchased(“asteroidinvaders_full_version”))
{
CCLog(“Billing: full version!”);
GoogleBilling::Google::disableAds();
GameSettingsSingleton::isFullGame = true;
}
else
{
CCLog(“Billing: Adsupported version”);
GoogleBilling::Google::enableAds();
GameSettingsSingleton::isFullGame = false;
}

    // Check if there are outstanding purchases for extra time
    CCLog("Billing: Check if 60 seconds of time was purchased");
    if (GoogleBilling::Billing::isPurchased("60seconds"))
    {
        CCLog("Billing: consume the extra time item!");
        GameSettingsSingleton::extraTimePurchased = 60;
    }
    else
    {
        CCLog("Billing: no outstanding purchases of extra time");
    }

#endif
}
else if (error == GoogleBilling::LOADSKUITEMS_ITEMS_NO)
{
GameSettingsSingleton::_billing = false;
CCLog(“No items, Billing Unavailable”);
}

if (GameSettingsSingleton::isFullGame)
{
    GoogleBilling::Google::disableAds();
}

}

static void BillingInitHandler(int error)
{
if (error == GoogleBilling::INIT_BILLING_YES)
{
CCLog(“Billing initialised”);
GoogleBilling::Billing::loadSKUItems(loadSKUItemsHandler);
}
else if (error == GoogleBilling::INIT_BILLING_NO)
{
CCLog(“Billing not availalble!”);
}
}

void GameSettingsSingleton::initBilling()
{
CCLog(“BillingInit”);
_billing = false;
GoogleBilling::Billing::init(BillingInitHandler);
}
`
For buying things i use:

`static void fullversionPurchased(int result)
{
Shop::me->hideMessage();
if (result == GoogleBilling::PURCHASE_ALREADY_PURCHASED)
{
Shop::me->textLayer->fireFloatingMessage(“Already purchased!”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop:Item already purchased!”);
GameSettingsSingleton::isFullGame = true;
GoogleBilling::Google::disableAds();
GameSettingsSingleton::GetInstance()->saveSettings();
}
else if (result == GoogleBilling::PURCHASE_FAIL)
{
Shop::me->textLayer->fireFloatingMessage(“Failed/Canceled”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop:Purchase failed or canceled!”);
GameSettingsSingleton::isFullGame = false;
GoogleBilling::Google::enableAds();
GameSettingsSingleton::GetInstance()->saveSettings();
}
else if (result == GoogleBilling::PURCHASE_SUCCESS)
{
Shop::me->textLayer->fireFloatingMessage(“Thank You!”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop: Purchasing done”);
GameSettingsSingleton::isFullGame = true;
GoogleBilling::Google::disableAds();
GameSettingsSingleton::GetInstance()->saveSettings();
}
}

static void extraTimePurchased(int result)
{
Shop::me->hideMessage();
if (result == GoogleBilling::PURCHASE_ALREADY_PURCHASED)
{
Shop::me->textLayer->fireFloatingMessage(“Already purchased!”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop:Item already purchased!”);
GameSettingsSingleton::extraTimePurchased = GameSettingsSingleton::extraTimePurchased + 60;
GameSettingsSingleton::GetInstance()->saveSettings();
}
else if (result == GoogleBilling::PURCHASE_FAIL)
{
Shop::me->textLayer->fireFloatingMessage(“Failed/Canceled!”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop:Purchase failed or canceled!”);
GameSettingsSingleton::extraTimePurchased = 0;
GameSettingsSingleton::GetInstance()->saveSettings();
}
else if (result == GoogleBilling::PURCHASE_SUCCESS)
{
Shop::me->textLayer->fireFloatingMessage(“Thank You!”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
CCLog(“Shop: Purchasing done”);
GameSettingsSingleton::extraTimePurchased = GameSettingsSingleton::extraTimePurchased + 60;
GameSettingsSingleton::GetInstance()->saveSettings();
}
}

void Shop::buyRemoveAdsCallback(cocos2d::CCObject *pSender)
{
if (GameSettingsSingleton::_billing)
{
CCLog(“LevelTwo: Purchasing full version”);
GoogleBilling::Billing::purchase(“asteroidinvaders_full_version”, 10001,fullversionPurchased);
//GoogleBilling::Billing::purchase(“android.test.purchased”, 10001,fullversionPurchased);
message = textLayer->fireFloatingMessage(“Please wait…”, -1, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
}
else
{
CCLog(“LevelTwo: Billing unavailable”);
message = textLayer->fireFloatingMessage(“Not available…”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
}
}

void Shop::buy60secondsCallback(cocos2d::CCObject *pSender)
{
Shop::me->hideMessage();
if (GameSettingsSingleton::_billing)
{
CCLog(“LevelTwo: Purchasing 60 seconds”);
GoogleBilling::Billing::purchase(“60seconds”, 10001,extraTimePurchased);
//GoogleBilling::Billing::purchase(“android.test.purchased”, 10001,fullversionPurchased);
message = textLayer->fireFloatingMessage(“Please wait…”, -1, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
}
else
{
CCLog(“LevelTwo: Billing unavailable”);
message = textLayer->fireFloatingMessage(“Not available…”, 2.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
}
}

void Shop::restorePurchasesCallback(cocos2d::CCObject *pSender)
{

if (GameSettingsSingleton::_billing)
{
    message = textLayer->fireFloatingMessage("Please wait..", 3.0f, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);
    CCLog("LevelTwo: restoring in-app purchases");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

    GoogleBilling::Billing::purchase("RESTORE", 1, fullversionPurchased);

#endif

}
else
{
    message = textLayer->fireFloatingMessage("Not available!", 2.0, 0.5f, GameSettingsSingleton::relPos(50, 50), ccLIGHTGREY);

    CCLog("LevelTwo: Billing unavailable");
}    

}`

I hope this helps?


#19

Hi very much thanks for the reply.
I got the ios version working.
There is problem in the android version.
when i compile the code i get these error in termimal
undefined reference to `GoogleBilling::Billing::isPurchased(char const*)‘
undefined reference to `GoogleBilling::Google::disableAds()’
undefined reference to `GoogleBilling::Google::enableAds()‘
undefined reference to `GoogleBilling::Billing::isPurchased(char const*)’
undefined reference to `GoogleBilling::Billing::loadSKUItems(void (*)(int))‘
undefined reference to `GoogleBilling::Billing::init(void (*)(int))’
I dont know what i am missing
Does the project have JNI file for android version.
As there is no jni binding code in the zip file.
If so can you please add it to the zip file .
Thank you in advance


#20

Muniraj Sunderavel wrote:

Hi very much thanks for the reply.
I got the ios version working.
There is problem in the android version.
when i compile the code i get these error in termimal
undefined reference to `GoogleBilling::Billing::isPurchased(char const*)‘
undefined reference to `GoogleBilling::Google::disableAds()’
undefined reference to `GoogleBilling::Google::enableAds()‘
undefined reference to `GoogleBilling::Billing::isPurchased(char const*)’
undefined reference to `GoogleBilling::Billing::loadSKUItems(void (*)(int))‘
undefined reference to `GoogleBilling::Billing::init(void (*)(int))’
I dont know what i am missing
Does the project have JNI file for android version.
As there is no jni binding code in the zip file.
If so can you please add it to the zip file .
Thank you in advance

The jni code was indeed missing,I’ve added it to the new zip file.