I am using Meteor.wrapAsync in a Method to process a stripe credit card payment. It works, but I do not want to return the entire response from theStripeAPI.charges.create to the client. How can I process the results of the wrapAsync function and return a new object from the method.
Meteor.methods({
createStripeCharge: function(params){
var charge = {amount: params.amount, currency:'usd', source: params.token.id}
var StripeAPI = stripe(<myprivatestriplekey>);
let chargeStripeCard = Meteor.wrapAsync( StripeAPI.charges.create, StripeAPI.charges );
let payment = chargeStripeCard( charge );
return payment;
}
});
Yes - that’s expected. Your return is in the callback, not the Method. The Method returns undefined before the callback is executed - standard async JavaScript behaviour.
So, use wrapAsync as you’ve done (the syntax is correct - but I’ve not checked the Stripe API). The thread will be suspended until the (now hidden) callback resolves and you can work with payment before the return.
No - I am using wrapAsync - I know the method returns before the API call returns. I was giving you a snippet based on the original code posting . To make it clearer I will post the whole method here:
Meteor.methods({
createStripeCharge: function(params){
var charge = {amount: params.amount, currency:'usd', source: params.token.id}
var StripeAPI = stripe(<myprivatestriplekey>);
let chargeStripeCard = Meteor.wrapAsync( StripeAPI.charges.create, StripeAPI.charges );
let payment = chargeStripeCard( charge, function (err,res) { return res.id} );
return payment;
}
});
Wow - i think i must be having a slow day. I was thinking the chargeStripeCard function only ran on the return - it runs before the return, and return waits for the response.
A follow on question : how would you handle a situation where you have multiple embedded external API calls in a method, and you only want to RETURN your method once the final API call has returned.
Would you wrapAsync each API call, assuming the Stripe API does not handle promises?, and if so - which wrapAsync identifier do you pass to the return value of the method.
Example :
'createStripeSubscription': function (params){
//create a subscription based on a $ amount decided by the user
// check if a subscription plan exists for the chosen $ amount
// if a plan does not exist then create a plan for that $ amount
// turn the user into a customer based on their credit-card token.id
// subscribe the customer to the new plan / or existing plan.
var self = this;
import stripe from 'stripe';
let StripeAPI = stripe(Meteor.settings.private.stripe.testSecretKey);
//************************
//Here is where I am not certain how to handle the wrapAsync. I am just pasting as if it were a sync function below, without any async conversions
//************************
//****** API CALL 1 ********
StripeAPI.plans.retrieve( "monthsub_" + params.amount, checkIfPlanExists );
var checkIfPlanExists = function(err, plan) {
if (err){ //ie a stripe subscription plan with this id does not exist
//****** API CALL 2 ********
let planDetails = { amount: params.amount, interval: "month", name: "monthsub_" + params.amount, currency: "usd", id: "monthsub_" + params.amount};
StripeAPI.plans.create(planDetails, createCustomer);
}
else{
self.planID = plan.id;
let CustomerDetails = {source: params.token.id};
StripeAPI.customers.create( customerDetails, subscribeCustomerToPlan);
}
}
var createCustomer = function(err, plan) {
if (err) { //return an error message };
//****** API CALL 3 ********
self.planID = plan.id;
let CustomerDetails = {source: params.token.id};
StripeAPI.customers.create( customerDetails, subscribeCustomerToPlan);
}
var subscribeCustomerToPlan = function(err, customer) {
if (err) { //return an error message };
//****** API CALL 4 ********
let subscriptionDetails = { customer: customer.id, plan: "monthsub_" + params.amount } ;
StripeAPI.subscriptions.create(subscriptionDetails, completeSubscription);
}
var completeSubscription = function(err, subscription) {
if (err) { //return an error message };
if (subscription){
console.log(subscription)
//log in localDB
//return Method to Meteor.call with subscription details
}
}
}