We can use Stripe's Customer Portal to allow our users to manage their subscription and payment information. We will configure the Customer Portal in the Stripe Dashboard and create the required pages for
Additionally, we create an API route to initiate our customer portal session. Similarly to our API route that charges for a subscription, we need to get the token from the cookie, add it to the Supabase session and fetch the associated
updated event gets triggered for creating a new subscription, as well as updating an existing one, and we want to perform the same changes in our Supabase DB, we can replace our case statement to handle
Lastly, we implement a case for
null. Since this event doesn't actually trigger until the end of the customer's billing cycle, we can manually cancel the user's subscription from the Stripe dashboard.
Instructor: [0:00] We want our users to be able to manage their own subscription from their dashboard. Let's set up a customer portal in Stripe. Let's go to Settings and then under Billing, Customer Portal. If we scroll down, we can choose what we want our customers to be able to do in their portal.
[0:14] I want customers to be able to see their invoice history and update their billing information. I also want them to be able to update their payment methods, cancel subscriptions. I want that to take place at the end of their billing cycle and I want customers to be able to switch between different pricing plans.
[0:40] Let's set this to http://localhost over port 3000/terms and then /privacy. We want our default redirect link to be our dashboard. Let's save these settings and confirm our password, and now we need to create those pages for terms and privacy.
[1:15] We want to add a Manage Subscription button to redirect our user to the Stripe customer portal. We also want this button to only appear once we finish loading, which means we need to wrap these two adjacent siblings in a fragment.
[1:32] We probably want to push that button down a little bit. When we click that button, we want to load Stripe's portal. We're going to want to make a request to an API route to initiate this session so we need to import Axios and use it to make a get request to /API/portal.
[1:57] This data will contain a URL that we want to redirect the user to. Let's bring in the useRouter hook from next/router and get our router instance in our component. We can redirect to that URL by calling router.push and giving it data.URL.
[2:13] Let's create this API route, which similarly to our subscription logic, we'll need to import these libraries. Get the Supabase user from our cookie. Send a failure response if we don't have a user. Pass the token out of our cookie.
[2:29] Set it to our Supabase session so we can make a request for the associated Stripe customer and then initialize a Stripe client. Let's copy this across. We're only two levels deep rather than three.
[2:45] Now we can create a new customer portal session by calling stripe.billingportal.sessions.create and passing it an object where our customer is set to our Stripe customer. Our return URL is set to http://localhost over port 3000/dashboard.
[2:58] We can then send back our response, which is an object with the key URL set to our session URL. Remember we're then taking that URL and redirecting our user to this Stripe customer portal. Let's click Manage Subscription. We can then update our plan.
[3:18] We could go to the Yearly Pro Plan and click Continue. It's going to tell us the difference that we'll need to pay for this new subscription. Now our user is on that yearly plan. However, if we go back to our dashboard, it still says that we're on the monthly plan.
[3:33] This is because we're not currently listening to webhooks about changes to a customer subscription. We're only listening for when a new subscription is created. When a customer creates or updates their subscription, we want to perform the same logic.
[3:46] We want to set the isSubscribe column to true, and update the interval. Since the updated event gets sent both when the customer creates a subscription and when they update it, we can just listen to that single event for both cases.
[3:58] Now if we manage our subscription again and set our plan back to the basic plan and then back to yearly again, we see that data reflected correctly in our dashboard. The other case we need to handle is when a user wants to cancel their plan.
[4:14] Let's add a break for the end of this case. Then let's add a case for customer.subscription.deleted. In this case, we also want to update the users profile table, but this time updating is subscribed to false, and setting our interval to null. We can add a break for the end of that case.
[4:31] If our user cancels their plan, we'll see that that's been cancelled in Stripe. Now when we head back to our dashboard, it still says we're subscribed to our yearly plan. That's because this event doesn't trigger immediately when the customer cancels their subscription.
[4:46] It triggers at the end of their current billing cycle when their subscription actually expires. We can trigger this event manually by heading over to the Stripe dashboard, finding our Pro subscriber that's already canceled, and cancelling their subscription from here.
[5:00] We can say we want this to happen immediately and click cancel subscription. If we go back to our dashboard and refresh, we'll see that our user is no longer subscribed.