I am looking example project for sdkbox iap

I have install sdkbox and iap plugins, but I dont know how I integrate to my project. I have try like no ads example in video but when I add sdkbox::IAPListener my CREATE_FUNC gives error (Allocating an object of abstract class type ‘GameScene’)

you need or override the functions sdkbox::IAPListener needs.

There is extra stuff here, but:

class HelloWorld : public cocos2d::Layer, public sdkbox::IAPListener
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();

    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  
    
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    void onShowAds(cocos2d::Ref* sender);
    void onRequestIAP(cocos2d::Ref* sender);
    void onRestoreIAP(cocos2d::Ref* sender);
    void onIAP(cocos2d::Ref* sender);
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
    
private:

    void updateIAP(const std::vector<sdkbox::Product>& products);
    
    virtual void onSuccess(sdkbox::Product const& p) override;

    virtual void onFailure(sdkbox::Product const& p, const std::string &msg) override;

    virtual void onCanceled(sdkbox::Product const& p) override;
    
    virtual void onRestored(sdkbox::Product const& p) override;

    virtual void onProductRequestSuccess(std::vector<sdkbox::Product> const &products) override;

    virtual void onProductRequestFailure(const std::string &msg) override;
    
    cocos2d::CCMenu* _iapMenu;
    std::vector<sdkbox::Product> _products;
    cocos2d::Label* _txtCoin;
    int _coinCount;
};

#endif // __HELLOWORLD_SCENE_H__
2 Likes

Can I find simple no_ads example project in github?

sorry, no_ads example?

You mean, how to remove ads by making an IAP?

Maybe there are enough pieces here to help:

#include "HelloWorldScene.h"
#include "ui/CocosGUI.h"

USING_NS_CC;

template <typename T> std::string tostr(const T& t) { std::ostringstream os; os<<t; return os.str(); }

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    auto dirs = Director::getInstance();
    Size visibleSize = dirs->getVisibleSize();
    Vec2 origin = dirs->getVisibleOrigin();
    
    _coinCount = 0;
    
    _txtCoin = Label::create("0", "Marker Felt.ttf", 32);
    _txtCoin->setAnchorPoint(cocos2d::Point(0, 0));
    _txtCoin->setPosition(cocos2d::Point(800, 500));
    addChild(_txtCoin);
    
    auto menuNode = Node::create();
    menuNode->setName("menuNode");
    int index = 2;
    
    auto thisSceneLabel = Label::createWithTTF("In-App Purchase Demo", "Marker Felt.ttf", 32);
    thisSceneLabel->setPosition(Vec2(origin.x+visibleSize.width/2, origin.y +visibleSize.height/2).x, (Vec2(origin.x+visibleSize.width/2, origin.y+visibleSize.height).y - (index) * 40));
    
    this->addChild(thisSceneLabel, 1);
    
    sdkbox::IAP::init();
    sdkbox::IAP::setDebug(true);
    sdkbox::IAP::setListener(this);
    
    auto menuItem1 = MenuItemFont::create("Remove Ads");
    menuItem1->setFontNameObj("Marker Felt.ttf");
    menuItem1->setFontSizeObj(32);
    menuItem1->setName("menuItem1");
    menuItem1->setPosition(Vec2(visibleSize.width/2, visibleSize.height/2));
    menuItem1->setCallback([&](cocos2d::Ref *sender)
    {
        onRequestIAP(sender);
    });
    
    auto menu = Menu::create(menuItem1, NULL);
    menu->setName("menu");
    menuNode->addChild(menu, 1);
    menu->setPosition(Vec2::ZERO);
    
    
    auto closeItem = MenuItemFont::create("CloseNormal.png",
        [&](Ref* sender){
        // your code here
    });
    
    this->addChild(menuNode, 2);
    
    return true;
}

void HelloWorld::onRequestIAP(cocos2d::Ref* sender)
{
    sdkbox::IAP::purchase("remove_ads");
}

void HelloWorld::onShowAds(cocos2d::Ref *sender)
{
    CCLOG("Show Ads");
}

void HelloWorld::onRestoreIAP(cocos2d::Ref* sender)
{
    sdkbox::IAP::restore();
}

void HelloWorld::onIAP(cocos2d::Ref *sender)
{
    auto btn = static_cast<Node*>(sender);
    sdkbox::Product* p = (sdkbox::Product*)btn->getUserData();

    CCLOG("Start IAP %s", p->name.c_str());
    sdkbox::IAP::purchase(p->name);
}

void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
    return;
#endif

    Director::getInstance()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

void HelloWorld::onSuccess(const sdkbox::Product &p)
{
    if (p.name == "coin_package") {
        _coinCount += 1000;
        _txtCoin->setString(tostr(_coinCount));
    }
    else if (p.name == "coin_package2") {
        _coinCount += 5000;
        _txtCoin->setString(tostr(_coinCount));
    }
    else if (p.name == "remove_ads") {
        CCLOG("Remove Ads");
    }

    CCLOG("Purchase Success: %s", p.id.c_str());
}

void HelloWorld::onFailure(const sdkbox::Product &p, const std::string &msg)
{
    CCLOG("Purchase Failed: %s", msg.c_str());
}

void HelloWorld::onCanceled(const sdkbox::Product &p)
{
    CCLOG("Purchase Canceled: %s", p.id.c_str());
}

void HelloWorld::onRestored(const sdkbox::Product& p)
{
    CCLOG("Purchase Restored: %s", p.name.c_str());
}

void HelloWorld::updateIAP(const std::vector<sdkbox::Product>& products)
{
    //
//    _iapMenu->removeAllChildren();
//    _products = products;
//    
//    int posX = 0;
//    int posY = 0;
//
//    for (int i=0; i < _products.size(); i++)
//    {
//        CCLOG("iap: %s", _products[i].name.c_str());
//        
//        auto btn = Label::create();
//        btn->setString(_products[i].name.c_str());
////        auto btn = CCMenuItemFont::create(_products[i].name.c_str(), CC_CALLBACK_1(HelloWorld::onIAP, this) );
//        btn->setColor(Color3B::WHITE);
//        btn->setUserData(&_products[i]);
//        btn->setPosition(CCPoint(posX, posY));
//        _iapMenu->addChild(btn);
//        posY += 50;
//    }
}

void HelloWorld::onProductRequestSuccess(const std::vector<sdkbox::Product> &products)
{
    updateIAP(products);
}

void HelloWorld::onProductRequestFailure(const std::string &msg)
{
    CCLOG("Fail to load products");
}
3 Likes

Thank you so much :slight_smile:

sure, if you need anything else, please let me know.

I have two button, I dont understand how it works onIAP? I didnt write ‘onIAP’ func. I set other things and now when I click to my remove ads button console says this Purchase Failed: Invalid product please double check the product id on itunes connect, It is normal or? I am sorry this is my first IAP experience.

  void NoAds( cocos2d::Ref *sender )
{
    sdkbox::IAP::purchase("remove_ads");
}
    void RestorePurchases( cocos2d::Ref *sender )
{
    sdkbox::IAP::restore();
}

have you defined your items in the iTunes Connect interface?

Have I publish first version of game for in app items submit? ITunesconnect says: Your first In-App Purchase must be submitted with a new app version. Select it from the app’s In-App Purchases section and click Submit. By the way, Can you explain to me how it works onIAP function in your codes. I didnt use onIAP, do I need to use it?

You don’t have to submit your IAP, you can still test it. All you need is create a tester user in your iTunesConnect account.

How do I check remove_ads purchased?

void GameScene::ShowAds()
{
     if(adsremoved)//Here how can i check?
    {
    CCLOG("Dont show ads");
    }
    else
    {
    CCLOG("Show Ads");
    }
}

and can you explain how works this function, I dont write this func in my project, I have to?

void HelloWorld::onIAP(cocos2d::Ref *sender)
{
    auto btn = static_cast<Node*>(sender);
    sdkbox::Product* p = (sdkbox::Product*)btn->getUserData();

    CCLOG("Start IAP %s", p->name.c_str());
    sdkbox::IAP::purchase(p->name);
}

Hi,

Review this: http://sdkbox-doc.github.io/en/plugins/iap/v3-cpp/

onIAP() is not part of the listener. it is just what is run when you press the button in the example. So maybe you have a Buy button and you run this when it is pressed.

As far as how to check for removing ads, I think that there are a lot of ways you can accomplish this. Perhaps UserDefaults, perhaps SQLite, perhaps even checking restored purchases.

1 Like

I still have the same problem (Invalid product). How much time did you have to wait for Itunes Connect recognize your Product ID?

Hi I am also running into the error with the “Allocating an object of abstract class type ‘HelloWorld’”.

I actually copied and pasted the code that you said would have all the overridden functions that are needed, but for some reason I still get the error.

Can you show me so I can see what is happening exactly? Maybe a screenshot at least?

Can you confirm what cocos2d-x version, iOS or android, iOS or android version, sdkbox version, please.

I’m using cocos2d-x 3.7.1 on iOS. SDKBOX v0.5.6.20 and sdkbox-iap_v1.2.3.3.

Is it possible that I messed up the installation? I used the automatic sdkbox installer. And then afterwards I used the cocos command to create a project. And then I went into the project directory and typed “sdkbox import iap” into the terminal. The terminal said the installation was successful. Is there anything else that I may have missed?

I bet that if you look you are missing a function in your private section of your header or also, you don’t have all of these functions defined in your .cpp. Double check.

Add this new function please

https://github.com/darkdukey/sdkbox-iap-sample/blob/master/cpp/Classes/HelloWorldScene.h#L43

I was missing
virtual void onInitialized(bool ok);
and
virtual void onRestoreComplete(bool ok, const std::string &msg);

Thanks everyone

DJEclipse: Yes, I was missing that too. Why? Well, I guess we both read carefully the docs: http://sdkbox-doc.github.io/en/plugins/iap/v3-cpp/#usage

And, those docs make no reference at all to those 2 functions (onInitialized & onRestoreComplete). Without those functions, the build in Xcode fails. Adding those? It works.

So, hey COCOS SDKBOX folks: Please update the docs to include all functions needed for a clean build! Thanks so much for your continued great support!

1 Like