#CMarabate

1 messages · Page 1 of 1 (latest)

frozen bisonBOT
pearl osprey
#

Hi there, you can use Stripe's customerID to map with your customers in your own DB.

vagrant nebula
#

Hi, so I have done that already I think. I have used Auth0 Actions which creates a a Stripe Customer ID and adds it to my Auth0 users app_metadata added to the Login Flow but I am having a hell of a time figuring out how to use it to add roles to the app_metadata based on the customers purchases.

pearl osprey
#

So it's more a question on how your application handle the Auth instead of payments?

vagrant nebula
#

Well ideally I would want it to set the roles after Stripe checkout is completed but I tried that first and I was able to get it to the point where I could complete checkout for a product and it would return me to the /success page and say everything was successful and it even added the customer in Stripe but no matter what I tried I could not get it to set the roles. I was calling a Netlify Function in the code for the success page. Was that a better approach?

#

Any way it can be accomplished I am cool with at this point lol

pearl osprey
#

So you only want to set the role on customer (I assume the role is enable paid customer to enjoy your service) when the first invoice of the subscription is paid successfully?

vagrant nebula
#

Yeah pretty much.

#

Here is a function I created for returning the Role name based on the product's price id...
// Get role name from product ID
function getRoleFromPlan(planId) {
switch (planId) {
case 'price_1LAIw9FUDFxTEzZGYzM290b6':
return 'Free Member';
case 'price_1LAIzgFUDFxTEzZGIhVayoGC':
case 'price_1MbqhmFUDFxTEzZGSxfA0Ed5':
return 'Epic Member';
case 'price_1LAJ0tFUDFxTEzZGaNqoqBqi':
case 'price_1MbqiVFUDFxTEzZGo87RhTHT':
return 'Legendary Member';
default:
return null;
}
}

pearl osprey
#

OK. I'll suggest you to listen to webhook event invoice.paid, which is fired when a invoice is paid successfully.

vagrant nebula
#

Okay thanks but I tried using a webhook once too and it was very confusing to me. Do you have a example of how to use a webhook to do something like this you can link me to or something?

pearl osprey
vagrant nebula
#

Perfect thanks a bunch!

vagrant nebula
#

Is this correct? And will it trigger automatically whenever stripe receives an invoice.paid event, I don't need to call it in my code anywhere?

#

My code for the handle-subscription-change function is...

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const ManagementClient = require('auth0').ManagementClient;

// Set up the Auth0 Management API client
const auth0 = new ManagementClient({
  domain: process.env.AUTH0_DOMAIN,
  clientId: process.env.AUTH0_API_EXPLORER_CLIENT_ID,
  clientSecret: process.env.AUTH0_API_EXPLORER_CLIENT_SECRET,
  audience: `https://${process.env.AUTH0_DOMAIN}/api/v2/`,
});

// Get role name from product ID
function getRoleFromPlan(planId) {
  switch (planId) {
    case 'price_1LAIw9FUDFxTEzZGYzM290b6':
      return 'Free Member';
    case 'price_1LAIzgFUDFxTEzZGIhVayoGC':
    case 'price_1MbqhmFUDFxTEzZGSxfA0Ed5':
      return 'Epic Member';
    case 'price_1LAJ0tFUDFxTEzZGaNqoqBqi':
    case 'price_1MbqiVFUDFxTEzZGo87RhTHT':
      return 'Legendary Member';
    default:
      return null;
  }
}

exports.handler = async (event) => {
  const sig = event.headers['stripe-signature'];
  let eventObject;

  try {
    eventObject = stripe.webhooks.constructEvent(event.body, sig, 'whsec_MKxjsjSYqz5MdmetrTCbupmAQD2hFxpX');
  } catch (err) {
    return { statusCode: 400, body: `Webhook Error: ${err.message}` };
  }

  if (eventObject.type === 'customer.subscription.updated') {
    const subscription = eventObject.data.object;
    const userId = subscription.metadata.userId;

    // Update user role in Auth0 based on subscription status and price ID
    const isSubscriptionActive = subscription.status === 'active';
    const role = isSubscriptionActive ? getRoleFromPlan(subscription.items.data[0].price.id) : 'Free Member';

    try {
      await auth0.updateUserMetadata({ id: userId }, { app_metadata: { role } });
      return { statusCode: 200, body: 'Webhook received successfully' };
    } catch (error) {
      console.error(error);
      return { statusCode: 500, body: 'Error updating user role in Auth0' };
    }
  }

  return { statusCode: 200, body: 'Webhook received successfully' };
};
pearl osprey
#

I don't see invoice.paid being handled in your code,

vagrant nebula
#

I thought that selecting it when setting up the webhook was all that was needed.

pearl osprey
#

No, you still need to handle the event in your own code.

vagrant nebula
#

Good to know, thanks!

#
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const ManagementClient = require('auth0').ManagementClient;

// Set up the Auth0 Management API client
const auth0 = new ManagementClient({
  domain: process.env.AUTH0_DOMAIN,
  clientId: process.env.AUTH0_API_EXPLORER_CLIENT_ID,
  clientSecret: process.env.AUTH0_API_EXPLORER_CLIENT_SECRET,
  audience: `https://${process.env.AUTH0_DOMAIN}/api/v2/`,
});

// Get role name from product ID
function getRoleFromPlan(planId) {
  switch (planId) {
    case 'price_1LAIw9FUDFxTEzZGYzM290b6':
      return 'Free Member';
    case 'price_1LAIzgFUDFxTEzZGIhVayoGC':
    case 'price_1MbqhmFUDFxTEzZGSxfA0Ed5':
      return 'Epic Member';
    case 'price_1LAJ0tFUDFxTEzZGaNqoqBqi':
    case 'price_1MbqiVFUDFxTEzZGo87RhTHT':
      return 'Legendary Member';
    default:
      return null;
  }
}

exports.handler = async (event) => {
  const sig = event.headers['stripe-signature'];
  let eventObject;

  try {
    eventObject = stripe.webhooks.constructEvent(event.body, sig, process.env.STRIPE_WEBHOOK_SECRET);
  } catch (err) {
    return { statusCode: 400, body: `Webhook Error: ${err.message}` };
  }

  if (eventObject.type === 'customer.subscription.updated') {
    const subscription = eventObject.data.object;
    const userId = subscription.metadata.userId;

    // Update user role in Auth0 based on subscription status and price ID
    const isSubscriptionActive = subscription.status === 'active';
    const role = isSubscriptionActive ? getRoleFromPlan(subscription.items.data[0].price.id) : 'Free Member';

    try {
      await auth0.updateUserMetadata({ id: userId }, { app_metadata: { role } });
      return { statusCode: 200, body: 'Webhook received successfully' };
    } catch (error) {
      console.error(error);
      return { statusCode: 500, body: 'Error updating user role in Auth0' };
    }
  } else if (eventObject.type === 'invoice.paid') {
    const invoice = eventObject.data.object;
    const subscription = invoice.subscription;

    if (subscription) {
      const userId = invoice.metadata.userId;

      // Update user role in Auth0 based on subscription status and price ID
      const role = getRoleFromPlan(invoice.lines.data[0].price.id);

      try {
        await auth0.updateUserMetadata({ id: userId }, { app_metadata: { role } });
        return { statusCode: 200, body: 'Webhook received successfully' };
      } catch (error) {
        console.error(error);
        return { statusCode: 500, body: 'Error updating user role in Auth0' };
      }
    }
  }

  return { statusCode: 200, body: 'Webhook received successfully' };
};
#

Do free subscriptions also trigger the invoice.paid event? I want to test checking out with my Free Subscription to see if it assigns me the Free Member role.

pearl osprey
#

nitpick: invoice.subscription may be null because invoice.paid is also fired for one-off invoice (i.e., not generated by subscription)

vagrant nebula
#

Oh I see what you mean now, thanks...

    let subscription;
    if (invoice.subscription) {
      subscription = invoice.subscription;
    }
pearl osprey
#

By free subscription you mean subscription with trial? Yes an invoice.paid event will be fired for the first $0 invoice as well

vagrant nebula
#

No I mean just a subscription that cost nothing...

pearl osprey
#

Yes, an invoice.paid event will be fired.

vagrant nebula
#

Hmmm so not sure what I did wrong then.

#

Guess it is Auth0 related. Hmmm

pearl osprey
#

Your server returns 500, which means server error. You should check your server log and investigate the problem

vagrant nebula
#

My Netlify Logs for the function?

#

Ahh yeah I see some clues in there. One more thing real quick...
When I click on the customer I made completed checkout for the Free Membership with, I saw the webhook icon but when I clicked it it has the wrong function name it has the name I used last time I tried using a webhook. Where do I change that?

pearl osprey
vagrant nebula
#

I mean that the function I just wrote is named handle-subscription-change not stripe-webhook

pearl osprey
#

That function name is internal to you, you can change to whatever you want as long as the URL that you specify for webhook endpoint is valid.