Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting meteor call to return stripe payments response

I've been working with Meteor and the stripe package to try and make a customer. So First I have my client side code which calls a method on the server so when clicked i have in the client.js:

Meteor.call('usersignup', function (error, result) {
    console.log (result);
});

So this calls the Method on the server.js:

var Future = Npm.require('fibers/future');
var stripe = StripeAPI('my key'); // secret stripe API key

Meteor.methods({

    usersignup: function(cusEmail){
        var fut = new Future();

        stripe.customers.create(
            { email: cusEmail },
            function(err, customer) {
                if (err) {
                    console.log(err);
                    fut.ret;
                }
                fut.ret(customer);
            }
            );
        return fut.wait();
    },

    userfail: function(cusid){
        var fut = new Future();

        stripe.customers.retrieve(cusid, function(err, result) {
            if(err){
                    console.log(err);
                    fut.ret;
                }
                fut.ret(err, result);
            });
        return fut.wait();
    }

});

Now this works and creates a customer when I log onto the stripe.com dashboard but I'm trying to get the response returned to the client well at least the customer id for now and print it in the console. This is where I can't seem to get it to work. It'll log undefined when I do console.log(result). Any ideas?

EDIT: So I put the fiber and the stripe key as global variables now and don't get an error but the returns don't seem to be returning any values. so on the client side I have:

'click #signupsubmit': function (event) {
    console.log("hello");
    var whatis = getVal(); // function gets value of forms and returns object
    var testid;
    var cusid = Meteor.call('usersignup', whatis.email, function (error, result) {
        if (error) {
            console.log(err.message);
            return;
        }
        console.log(result);
        console.log("meteor call");
        testid = result;
        return (result);
    });
    console.log("outside call");
    console.log(testid);
    console.log(cusid);
    },
});

So i've been running some console.log tests and it seems it executes the meteor.call and keeps going down the line. Console.log of both testid and cusid return undefined but a couple seconds later I receive the console.log of result and the string "meteor call" from inside the meteor.call. Is there a way to wait for the meteor call to finish then run the rest of what is in my click function? so console output will go like:

  • "hello"
  • "outside call"
  • test id undefined
  • cusid undefined
  • "meteor call"
  • "result"
like image 918
asiammyself Avatar asked Apr 20 '13 17:04

asiammyself


2 Answers

Keep in mind that the stripe API doesn't use Fibers. You need to put it in manually. The callback doesn't reach the client because by then it would have already got a response (its async)

You can use something like this to wait for a result from the stripe callback before a result is returned to the client:

var stripe = StripeAPI('mykeygoeshere');  // secret stripe API key
var Future = Npm.require('fibers/future');

var fut = new Future();

stripe.customers.create(
    { email: '[email protected]' },
    function(err, customer) {
        if (err) {
            console.log(err.message);
            fut.ret;
        }
        fut.ret("customer id", customer.id);
    }
);
return fut.wait();

Here a Future is used and it waits for a result to be received from the stripe callback before a result is returned to the client.

More info can be found on Fibers/Futures & Synchronous Callbacks incuding how to go about them & when to use them:

  1. Meteor: Calling an asynchronous function inside a Meteor.method and returning the result
  2. https://github.com/laverdet/node-fibers
  3. https://gist.github.com/possibilities/3443021
like image 184
Tarang Avatar answered Nov 14 '22 14:11

Tarang


Here's something simpler. Meteor now has Meteor.wrapAsync() for this kind of situation:

var stripe = StripeAPI("key");    
Meteor.methods({

    yourMethod: function(callArg) {

        var charge = Meteor.wrapAsync(stripe.charges.create, stripe.charges);
        charge({
            amount: amount,
            currency: "usd",
            //I passed the stripe token in callArg
            card: callArg.stripeToken,
        }, function(err, charge) {
            if (err && err.type === 'StripeCardError') {
              // The card has been declined
              throw new Meteor.Error("stripe-charge-error", err.message);
            }

            //Insert your 'on success' code here

        });
    }
});

I found this post really helpful: Meteor: Proper use of Meteor.wrapAsync on server

like image 31
jacksonkernion Avatar answered Nov 14 '22 14:11

jacksonkernion