Git Product home page Git Product logo

atomic-plugins-inapps's Introduction

#Atomic Plugins for In-App Purchases

This repo contains In-App purchase APIs designed using the Atomic Plugins paradigm. You can integrate IAPs in your app and take advantage of all the features provided: elegant API, local and server-side receipt validation, secure consumable and non-consumable purchase tracking, local product cache and more. The API is already available in many languagues and we plan to add more in the future:

Currently there are 3 in-app purchase providers implemented but new ones can be easily added:

  • Apple AppStore (iOS/Mac)
  • GooglePlay
  • Amazon AppStore.

You can contribute and help to create more awesome plugins.

##About Atomic Plugins

Atomic Plugins provide an elegant and minimalist API and are designed with portability in mind from the beginning. Framework dependencies are avoided by design so the plugins can run on any platform and can be integrated with any app framework or game engine.

#Provided APIs

##iOS API:

###API Reference

See API Documentation

See LDInAppService.h header file for a complete overview of the capabilities of the class.

See InAppTest for a complete project that tests all the features provided in the API.

###Introduction

LDInAppService class provides an easy to use and secure in-app purchase API. Built-in support for local and server-side receipt validation, consumable and non-consumable purchase tracking and local product cache. Completed purchases are secured using Apple's keychain services and are remembered even if the user deletes the app.

###Setup your project

You can use CocoaPods:

pod 'LDInAppService'

###Example

LDInAppService * service = [[LDInAppService alloc] init];

[service addPurchaseObserver: self]; //optional delegate to observe purchases
[service start]; //start processing transactions

[service fetchProducts:@[@"productIds"] completion:^(NSArray *products, NSError *error) {
     //fetch products from remote server
}];

service.products; //local cached products

[service purchase:productId quantity:2 completion:^(NSError *error) {
    //purchase consumable or non consumable products
}];
[service consume:productId quantity:1]; //consume product

[service isPurchased:productId]; //check if a productId is purchased
[service stockOfProduct:productId]; //check available stock of consumable products

[service restorePurchases:^(NSError *error) {
     //restore non-consumable purchases
}];
[service setValidationHandler:^(NSData *validationReceipt, NSString *productId, LDValidationCompletion completion) {
    //custom server validation
    completion(nil); //Call completion with nil error if validation succeeds
}];
[service setLudeiServerValidationHandler]; //validate using Ludei's Cloud server

##Android API:

###API Reference

See API Documentation

See InAppTest for a complete project that tests all the features provided in the API. In order to test Android In-Apps select the googlePlayRelelease or amazonRelease built variant in Android Studio. You must set your custom productIds in MainActivity.java and set your bundleId and versionCode in the build.gradle

You also have to configure your release signingConfig. Add these properties to your global gradle.properties file

STORE_FILE=/Users/user/.android/company.keystore
STORE_PASSWORD=xxxxx
KEY_ALIAS=xxxxxxx
KEY_PASSWORD=xxxxx

###Introduction

InAppService interface provides an easy to use and secure in-app purchase API. Built-in support for local and server-side receipt validation, consumable and non-consumable purchase tracking and local product cache. Single API for multiple IAP providers.

Setup your project

Releases are deployed to Maven Central. You only have to add the desired dependencies in your build.gradle:

dependencies {
    compile 'com.ludei.inapps.googleplay:1.0.0' //Google Play IAP Provider
    compile 'com.ludei.inapps.amazon:1.0.0' //Amazon AppStore IAP Provider
}

###Example

//create the service instance using the desired provider
InAppService service =  new GooglePlayInAppService(context);
//service =  new AmazonInAppService(context);

service.fetchProducts(productIds, new InAppService.FetchCallback() {
    public void onComplete(List<InAppProduct> products, InAppService.Error error) {
        //fetch products from store
    }
});

service.getProducts(); // Local cached products

service.purchase(productId, new InAppService.PurchaseCallback() {
    public void onComplete(InAppPurchase purchase, InAppService.Error error) {
        //purchase product
    }
});

service.consume(productId, 1, new InAppService.ConsumeCallback() {
    public void onComplete(int consumed, InAppService.Error error) {
        //consume product
    }
});

service.isPurchased(productId); //check if a product is purchased
service.stockOfProduct(productId); //check available stock of consumable products 

service.restorePurchases(new InAppService.RestoreCallback() {
    public void onComplete(InAppService.Error error) {
        //Restore completed purchases
    }
});

service.setValidationHandler(new InAppService.ValidationHandler() {
    public void onValidate(String receipt, String productId, InAppService.ValidationCompletion completion) {
        //custom server validation
    }
});

service.setLudeiServerValidationHandler(); //Validate using Ludei's Cloud server

Remember to notify onActivityResult and onDestroy events

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    boolean handled = service.onActivityResult(requestCode, resultCode, data);
    if (!handled) {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

@Override
public void onDestroy()
{
    service.onDestroy();
    super.onDestroy();
}

##JavaScript API:

###API Reference

See API Documentation

For a complete project that tests all the features provided in the API run the following command:

gulp create-cordova

A cordova project is created in test/cordova/InAppTest

###Introduction

Cocoon.InApp class provides a multiplatform, easy to use and secure in-app purchase API. Built-in support for local and server-side receipt validation, consumable and non-consumable purchase tracking and local product cache. Single JavaScript API for multiple IAP providers.

###Setup your project

Releases are deployed to Cordova Plugin Registry. You only have to install the desired plugins using Cordova CLI, CocoonJS CLI or Ludei's Cocoon Cloud Server.

cordova plugin add cocoon-plugin-inapps-ios-appstore;
cordova plugin add cocoon-plugin-inapps-android-googleplay;
cordova plugin add cocoon-plugin-inapps-android-amazon;

The following JavaScript file is included automatically:

cocoon_inapps.js

###Example

// Basic usage, register callbacks first
var service = Cocoon.InApp;
service.on("purchase", {
    start: function(productId) {
        console.log("purchase started " + productId);
    },
    error: function(productId, error) {
        console.log("purchase failed " + productId + " error: " + JSON.stringify(error));
    },
    complete: function(purchase) {
        console.log("purchase completed " + JSON.stringify(purchase));
    }
});

// Service initialization
service.initialize({
        autofinish: true
    }, function(error){

    }
);

service.fetchProducts(productIds, function(products, error){
    //Fetch products from the server
});   

service.getProducts(); //Local cached products

service.purchase(productId, 1, function(error) { // Optional sugar callback
    //purchase product
});

service.consume(productId, 3, function(error) {
    //consume product
});

service.isPurchased(productId); //check if a product is purchased
service.stockOfProduct(productId); //check available stock of consumable products

service.setValidationHandler(function(receipt, productId, completion){
     ... //Custom server validation code
     completion(true); //call completion function with true param if validation succeeds
});

service.setLudeiServerValidationHandler(); //validate using Ludei's Cloud server

##C++ API:

###API Reference

See API Documentation

See InAppService.h header file for a complete overview of the capabilities of the class.

See InAppTest for a complete project (cocos2dx game) that integrates the C++ IAP API.

###Introduction

InAppService class provides a multiplatform, easy to use and secure in-app purchase API. Built-in support for local and server-side receipt validation, consumable and non-consumable purchase tracking and local product cache. Single C++ API for multiple IAP providers.

###Setup your project

You can download prebuilt headers and static libraries from Releases page

These static libraries provide the bindings between C++ and the native platform (iOS, Android, WP, etc). You might need to add some platform dependent libraries to your project (some jar files or gradle dependecies for example). See InAppTest for an already setup C++ multiplatform project.

####Special setup required for Android

There isn't a portable and realiable way to get the current Activity and life cycle events on Android and we don't want to depend on specific game engine utility APIs. C++ and Java bridge is implemented using the SafeJNI utility. Atomic Plugins take advantage of this class and use it also as a generic Activity and Life Cycle Event notification provider. See the following code to set up the activity for atomic plugins and to notify Android life cycle events.

@Override
public void onCreate(Bundle savedInstanceState) {
    //set the activity for atomic plugins and load safejni.so
    SafeJNI.INSTANCE.setActivity(this); 
    super.onCreate(savedInstanceState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    //notify onActivityResult to atomic plugins
    SafeJNI.INSTANCE.onActivityResult(requestCode, resultCode, data);
}

Optionally (but recommended) you can use setJavaToNativeDispatcher to configure the thread in which async callbacks should be dispatched. By default callbacks are dispatched in the UI Thread. For example the following dispatcher is used in the Cocos2dx game engine test project.

@Override
public Cocos2dxGLSurfaceView onCreateView() {
    final Cocos2dxGLSurfaceView surfaceView = super.onCreateView();
    SafeJNI.INSTANCE.setJavaToNativeDispatcher(new SafeJNI.JavaToNativeDispatcher() {
        @Override
        public void dispatch(Runnable runnable) {
            surfaceView.queueEvent(runnable);
        }
    });
    return surfaceView;
}

#####Signing a build for release

Set your bundleId and versionCode in the build.gradle

You also have to configure your release signingConfig. Add these properties to your global gradle.properties file

STORE_FILE=/Users/user/.android/company.keystore
STORE_PASSWORD=xxxxx
KEY_ALIAS=xxxxxxx
KEY_PASSWORD=xxxxx

###Example

//Easy to use static method to instantiate a new service
//You can pass a specific InAppProvider if you have many providers linked in your app and you want to choose one of them at runtime
InAppService * service = InAppService::create();

service->addPurchaseObserver(observer); //optional purchase observer;
service->start(); //start processing transactions

service->fetchProducts(productIds, [=](const std::vector<InAppProduct> & products, const InAppService::Error & error){
    if (error.empty()) {
        //show error
        return;
    }
    // fetch products from remote server
});

service->purchase(productId, [=](const InAppPurchase & purchase, const InAppService::Error & error){
    //purchase product
});

service->consume(productId, 1, [=](int32_t consumed, const InAppService::Error & error){
    //consume product
});

service->isPurchased(productId); //check if a productId is purchased
service->stockOfProduct(productId); //check available stock of consumable products

service->restorePurchases([=](const InAppService::Error & error){
    //restore purchases
});

service->setValidationHandler([=](const string & receipt, const string & productId, const ValidationCompletion & completion){
    //custom server validation code
    completion(InAppService::Error()); //call completion with empty error if validation succeeds
});

service->setLudeiServerValidationHandler(); //validate using Ludei's Cloud server

//delete the service when you are done. You can wrap it into a Smart Pointer if you want.
delete service; 

#License

Mozilla Public License, version 2.0

Copyright (c) 2015 Ludei

See MPL 2.0 License

atomic-plugins-inapps's People

Contributors

badeleux avatar basoko avatar bluesialia avatar mortimergoro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atomic-plugins-inapps's Issues

iOS 6.1.3 Crash : -[LDInAppFetchDelegate respondsToSelector:]: message sent to deallocated instance

Hi,

Firstly thank you for an awesome library. However I'm having an issue with it on ios6 devices.

When I run the 'fetchProducts:completion:' call on an iTouch device running iOS 6.1.3 the app crashes. If I enable zombie objects and try again, I get the following console output:

*** -[LDInAppFetchDelegate respondsToSelector:]: message sent to deallocated instance 0x1f504e40

I noticed if in the following function below, if I comment out the CFRelease line, it prevents the crash but obviously isn't the correct solution as the memory will eventually build up as its not getting released correctly.

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSError * error = nil;
    if (response.invalidProductIdentifiers.count > 0) {
        NSString * msg = @"Invalid products: ";
        for (NSString * pid in response.invalidProductIdentifiers) {
            msg = [msg stringByAppendingString:pid];
            msg = [msg stringByAppendingString:@","];
        }
        error = MAKE_ERROR(0, msg);
    }
    _completion(response.products, error);
    //CFRelease((__bridge CFTypeRef)(self));
}

I should mention this code runs fine on ios7 and above, its just on 6.1.3 I've noticed the issue. Do you know what is causing this and how I can fix it?

Many thanks

IAPs FetchProducts through Cocoon always returns "Invalid Products"

Hi,

I'm trying to use this plugin in a Phaser game that's being deployed to iOS and Android using Cocoon. The API seems to work as it should, but I always get "invalid products" when requesting products from my iOS app. The products are correctly set up in my iTunes Connect account, and in the "Ready to Submit" phase. I’ve also created a TestFlight build but the plugin still gets the “Invalid Products” response.

Here’s my plugin initialisation:
initialize

Fetch Products:
fetch_products

iTunesConnect product IDs:
itc_ids

IAP IDs used in the app:
iap_ids

And the resulting log statement from device:
log_statements

I've hidden the app id from these images but I can 110% guarentee that they are the exact same. I've triple checked them and had 3 co-workers check them for me as well.

My app start looks like this:
bootstrap

The IAP plugin definitely gets initialized after the 'deviceready' signal has been sent. I've also posted on Cocoon's forums but I thought I'd post here too. Any help would be extremely welcomed!

Thanks!

Class not found

Hi there,

I am trying to implement in app purchases for android.
I keep getting this error of "Class not found" when fetchProducts is called from the service.

Does anybody know how to fix it?

Crash within a Qt application on iOS

Using iOS C++ library linked to any Qt application (no difference Widgets or Qt Controls) leads to crash with the following trace:

2015-08-26 13:50:25.800 TestIPWidgets[1969:907] -[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x1e573630
2015-08-26 13:50:25.805 TestIPWidgets[1969:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x1e573630'

It crashes on access _products property within saveProductsToCache or addProduct function.

Where must I put google License Key

Hello there,

I look at this plugin and I think this is great for those who use C++ for their game. This plugin can be a competitor to soomla IAP as that plugin doesn't support cocos2dx 3.3 yet.
For IOS, its look great. But for android, can you give another example using eclipse project as cocos2dx doesn't support android studio yet.

I want to ask, where do i put google license key for c++ project on android? As I see there is no place for google license key on android.

thank you

Crash on Cordova/Android when testing with static responsen

Hi,

I'm trying to use these plugins to implement inapp purchases for a Cordova (v3.6.4) app that I am testing on Android 4.4.2 (Samsung S5 Mini).

Using the static responses as described in http://developer.android.com/google/play/billing/billing_testing.html, I find that android.test.purchased is working fine, but android.test.canceled and android.test.refunded both make the app crash. The start callback of the on purchase event is still called (with the correct product ID), though.

Also, I could not find any information in the API docs on how to handle canceled or refunded purchases. Do these fire the on purchase event, too?

Any help would be greatly appreciated.

Where to put Google Play Public RSA Key? (Cordova)

Hi!
Great plugin!
Works for me on iOS, but on android throws error: java.lang.NullPointerException when trying to fetch products.
Other cordova IAP plugins require google play public key. Maybe it's the problem.
I don't know where to put it. Please help.

Cordova Amazon Plugin Callback?

Hi everyone. First, thank you so much for making this plugin :) Definitely awesome! I'm a self-learned programmer (except for the first two quarters in college), and have been building apps for iOS and now multiplatform using Cordova, html, css, javascript. So my technical side isn't quite as strong as many. I've got a different plugin to work for IAPs for iOS and Google Play. It took awhile, but it works as expected now, and I've trying to implement your plugin now.

I think I've implemented things correctly, because after putting the app as a Test on Amazon Apps, and downloading it with my Android device, I was able to get Test-Charged for my IAPs correctly, and even received confirmation from Amazon that the purchase(s) were made. However, once I get a confirmation, no callback code is being run... so the IAP is charging the user correctly, but the user isn't actually getting the IAP. Maybe I'm putting it in the wrong place, so maybe you could help?

I've tried putting it in two places, look for //HERE:

service = Cocoon.InApp;
service.on("purchase", {
        start: function(productId) {

        },
        error: function(productId, error) {

        },
        complete: function(purchase) {
            // HERE
        }
});

and secondly:

Cocoon.InApp.purchase("iap1", 1, function(error) {
    if(error){

    }
    else {
        // HERE
    }
});

Neither of these two places seem to actually run any of the code. I've tried updating the UI, adding the IAP, and even doing an alert("Do Something"), and nothing works from those spots. However, the Cocoon.InApp.purchase() method works properly, talking with Amazon properly. Now, maybe I am supposed to use the consume method instead? But I'm confused as to what I am supposed to do. Maybe you could help?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.