Cheers for jumping in!
Sure…
Use case
When a new user signs up, add them as a customer to Stripe as well as create a subscription for them on Stripe.
Stripe functions
(All tested and working correctly from the ‘billing and plans’ page I have set up for already signed up users. These are all functions getting called via a validated method from the client when they select a plan to change to/subscribe to.
// Create a customer on stripe. Pass in email (required) and description (practice name)
export const createCustomerOnStripe = ({ email, clientName }) =>
stripe.customers.create({ email, description: clientName });
// Once a customer is created, add a subscription for them (include token if it is a paid plan)
export const addSubscriptionToCustomer = ({ stripeId, planId, token }) => {
if (token) {
return stripe.subscriptions.create({ customer: stripeId, plan: planId, source: token });
}
return stripe.subscriptions.create({ customer: stripeId, plan: planId });
};
// Update payment card for customer
export const updatePaymentCard = ({ stripeId, token }) => stripe.customers.update(stripeId, { source: token });
// Change from an existing subscription to a different one
export const changeSubscription = ({ subscriptionId, planId, token }) => {
if (token) {
return stripe.subscriptions.update(subscriptionId, { plan: planId, source: token });
}
return stripe.subscriptions.update(subscriptionId, { plan: planId });
};
Now, the validated methods that call the functions above take care of the users I already have, but new users, I wish them added on Stripe to a free plan when they sign up.
So…
Working fine before any modifications:
Accounts.onCreateUser(({ email, planId, clientName }, user) => {
// Add some data to the new user so they don't have an empty dashboard
seedNewAccount(user._id, clientName, email);
return user;
});
Not working:
1 Turning it into an async function
Note - This does actually create the customer on Stripe no problem, but the overall onCreateUser ends up returning a promise that resolves into the user, and that throws the account creation process off (it does not expect a promise).
Accounts.onCreateUser(async ({ email, planId, clientName }, user) => {
// Add some data to the new user so they don't have an empty dashboard
seedNewAccount(user._id, clientName, email);
// Once all the above is successfully done, add the client to Stripe with a free subscription
const { id: stripeId } = await createCustomerOnStripe({ email, clientName });
const { id, status, current_period_end } = await addSubscriptionToCustomer({
stripeId,
planId,
})
const planInfo = { stripeId, status, renewalDate: current_period_end, planId }
user.planInfo = planInfo;
return user;
});
2 Using Meteors wrapasync
Accounts.onCreateUser(({ email, planId, clientName }, user) => {
// Add some data to the new user so they don't have an empty dashboard
seedNewAccount(user._id, clientName, email);
// Once all the above is successfully done, add the client to Stripe with a free subscription
function addToStripe() {
const { id: stripeId } = await createCustomerOnStripe({ email, clientName });
const { id, status, current_period_end } = await addSubscriptionToCustomer({
stripeId,
planId,
})
const planInfo = { stripeId, status, renewalDate: current_period_end, planId }
user.planInfo = planInfo;
}
const syncAddToStripe = Meteor.wrapAsync(addToStripe);
syncAddToStripe();
return user;
});
I’ve tried so many variations it’s starting to get muddled, but I think the above snipped ended up not working at all.
I think it is because the wrapAsync expects a callback while this is promise based?
3 Using an async function within onCreateUser
Kind of a noobish approach this, but summary is it ends up with the same issue as number 1. The moment you add an async function, the whole thing becomes promise based and you can’t directly return the user
Am I on the right track with any of the approaches above or wildly off? I’m hoping that I am on the right track and just a tweak or two will be sufficient to get this working.