Best way to do In-App Purchases on Meteor app?


#1

I’m looking at options for in-app purchases on an app via Google Play store and Apple Appstore. What are the best packages to consider?

Are there some code examples out there in the community already?

Nothing turned up on Atmosphere, is there something everyone knows that I don’t?

Thanks!


Need help adding in-app-purchases to a Meteor app. Specifically adding 'subscription' support for Android Play Store
#2

#3

You’d be looking for a cordova plugin that has a matching Meteor package.

I haven’t been able to find any for you.

You could probably package it up yourself if you’re up to it, there’s some information here


#4

Cordova plugins don’t need a matching Meteor package. They can be installed by itself, using either the old Cordova plugin name syntax or a github tarball. See the documentation here.. Maybe with Meteor 1.2 this also supports the new plugin registry syntax, haven’t read the new docs so far.


#5

OO cool! Didn’t notice that.

A package would still be cool though. Old post updated :smile:


#6

Hey hi

Yeah I think the obvious plugin would seem to be https://github.com/j3k0/cordova-plugin-purchase

But if my previous experience with Cordova plugins with Meteor is anything to go by, it is not likely to work straightforwardly - especially something complicated like in-app purchase. Hence the ask around for prior experiences / code examples. Seen anything?


#7

Does anyone have any code example.
Because calling the store object is not working for me.

Example:

store.register({
    id:    "com.example.app.inappid1",
    alias: "100 coins",
    type:  store.CONSUMABLE
});

#8

How are you getting on with this?

I’m part way through my integration with j3k0’s plugin and it does work, though the documentation could be better.

You need to call store.refresh() after registering your products and handlers before the store object is properly initialised. Did you do that yet?


#9

alveoli - I’m working with the foveo.cordova.purpose plugin you mention, I have the same comment on the documentation. Do you use the store.validate and specifically I can’t make sense out the custom configuration they describe :

store.validator = function(product, callback) {
callback(true, { … transaction details … }); // success!
// OR
callback(false, {
error: {
code: store.PURCHASE_EXPIRED,
message: “XYZ”
}
});
// OR
callback(false, “Impossible to proceed with validation”);
// Here, you will typically want to contact your own webservice
// where you check transaction receipts with either Apple or
// Google servers.
});

If you have a “real” implementation, I would really appreciate it. Thanks in advance.


#10

Sure here’s mine:

        store.validator = function store_validator(product, callback) {
            Meteor.call('iap-plus/validate_iap_order', product, function (error, result) {
                if (error) {
                    callback(false, "Impossible to proceed with validation");
                }
                if (result && result.valid_now === true) {
                    callback(true, product);
                } else if (result && result.valid_now === false) {
                    //store.INVALID_PAYLOAD   = 6778001;
                    //store.CONNECTION_FAILED = 6778002;
                    //store.PURCHASE_EXPIRED  = 6778003;
                    log_s.trace('store_validator: callback false');
                    callback(false, {
                        code: result.failure_code, // could be INVALID_PAYLOAD or PURCHASE_EXPIRED
                        message: "Validation failed"
                    });
                } else {
                    callback(false, "Impossible to proceed with validation");
                }
            });
        };

My Meteor method iap-plus/validate_iap_order is where I do all the funky stuff with remote server calls to Apple or Google, etc. I chose https://github.com/Wizcorp/node-iap for that. I ended up using my own fork of node-iap as it doesn’t support subscriptions as-is.

The other thing to note is it’s worth checking out the source code for how the different failure codes are handled, to make sure you pass the right one… if I remember correctly there’s some difference with how it might retry the validation…that information isn’t documented.

Good luck!


#11

thanks so much. I had a similar function but it does not seem to get
invoked (store.verify()?) when running in the sandbox. Is this your
experience? haven’t pushed to production, thanks again


#12

[post deleted, was posted by mistake]


#13

In my experience it invokes verify a lot! A lot more than I wanted or expected! Even during startup of the app, if the user has purchased something it gets verified again.

Verify happens when the product’s state becomes Approved. This change of state event can only happen when (1) you call store.refresh() or (2) you call store.order().

Have you checked to see your product is state=Approved?


#14

Thanks for your response, really appreciate it.
I JUST think I figured out my problem, I was using the test app largely out of the box. It looks
like “finish” was being called before verify.
Thanks again - Lou


#15

Nice glad it worked out :+1:


#16

Alveoli - Still working to get the plugin to fully cooperate. What
appears to be the remaining open end is “restore”. If I make a purchase
on one phone and then go to another phone with the same test ID, the way
I understand things, the plugin should query the store and find that the
purchase is owned by the test ID. The plugin on phone 2 does not see the
receipt. Am I missing something? how do you handle restores? How do you
handle restores? thanks


#17

https://github.com/j3k0/cordova-plugin-purchase worked for me both android and ios… and our app is already in productio…


#18

What product type did you use? consumable, non-consumable, auto-renewable subscription, non-renewing subscription?


#19

product type i used was subscription


#20

@alveoli I saw that you had an issue with the app crashing after you made a purchase on Android. Did you discover what the issue was? I’m having the same problem and I get the same error.