Webhook Events Overview0:00
Okay, let's take a look at webhooks. So Stripe has a list of events that can be sent out via webhooks to inform your application that something has happened. Cachier has some defaults in place to automatically handle these events if you want to. So the events that Cachier handles are these ones right here, and they are pretty self-explanatory. And the endpoint for handling webhooks is this one right here. So if we do php artisan route:list, and let's look for Stripe, then we can see this Stripe webhook, and it's calling this WebhookController class and a handleWebhook method. So we'll set up a webhook in Stripe. So say for example, customer deleted, and it's going to ping the endpoint that we specify,
So we'll set up a webhook in Stripe. So say for example, customer deleted, and it's going to ping the endpoint that we specify, and we'll do that in a second. It's going to hit this route in our app, which points to this controller and this method, which is right here, it's in the package directory. So handleWebhook, it's going to grab the payload and formulate a method name. So in our case, handleCustomerDeleted, and then it's going to call that method here. So let's look at that handleCustomerDeleted. And all it does is mark any subscriptions as canceled, and set these columns to null. So let's see if we can get this to work.
Disable CSRF for Webhooks1:14
And all it does is mark any subscriptions as canceled, and set these columns to null. So let's see if we can get this to work. So what's the first step here? Is there anything up here, you can also make use of the Stripe CLI to do this, but I'm just going to make use of tunnels. So first thing to do is exclude these endpoints from CSRF protection. So let's grab this, let's go to verifyCsrfToken in our code. So let's look for that verifyCsrfToken. And let's add this endpoint in our except array. Okay.
Configure Webhook Secret1:50
And let's add this endpoint in our accept array. Okay. Next is, see here, this is if you want to handle other events besides these ones here, and we'll do that in a second. But the next step I want to do is verifying webhook signatures. So we have to add a Stripe webhook secret. So we know that the request is coming from Stripe. So we have to do is set up an endpoint or set up a webhook within Stripe. So if you go to developers, webhooks, as you can see, I have one set up here. And let me just edit this one.
Expose Local Webhook Endpoint2:49
So I like to make use of a tool called Expose. And this creates a tunnel between your local project and the internet. So all I have to do is run Expose. And if you don't have this tool, it's similar to ngrok, if you've heard of ngrok before. And if you're making use of valet, you can also do valet share, which makes use of ngrok. But I like using Expose. So let's do that. And now we have an endpoint. And this is accessible over the internet as long as this terminal tab is opened. So let me copy this.
And this is accessible over the internet as long as this terminal tab is opened. So let me copy this. And our endpoint is /stripe/webhook. So let's do that. Let me edit this. Okay, let's update this. /stripe/webhook, okay. And like I said, these are the events that Stripe is listening to. And if it encounters any of these, it will ping this endpoint here. Okay, so let's update the endpoint.
And if it encounters any of these, it will ping this endpoint here. Okay, so let's update the endpoint. And let me just confirm my password. And now we have to set up that Stripe webhook secret right here, like I said earlier. So we know the request is coming from Stripe. So let me just add this to my .env file. Let me just put it here. And I'll just paste it in behind the scenes. So it's right here, by the way. So yeah, let me just paste that in.
Test Customer Deleted Event4:12
So it's right here, by the way. So yeah, let me just paste that in. Okay, so I pasted that in my .env file. And now let's go ahead and make a customer in Stripe. So right now, I don't have any customers in Stripe. So my database is empty as well. So let's go ahead and make a new User. So let's say me. Okay, let's register this User. And this will log us in as well.
Okay, let's register this User. And this will log us in as well. And now let's also create a User in Stripe. So to do that, let's just make use of this form that we created that accepts payment. And again, it's going to mash for two here. And this should be successful and create a User in Stripe. Okay, so let's subscribe now. Sorry, keep doing that. Okay, so that was successful. We now have this User in our database.
for that event here. And we specified it in the webhook. So these are one of the ones that Cashier handles. And we also specified that in the webhook. So let's take a look at webhooks again. And if you click on this one, and if you scroll down, you'll see that some webhooks did happen here because it also included these events. But let's do it again for customer.delete. And see if another one happens here for customer.delete. So let's delete that customer within Stripe.
And see if another one happens here for customer.delete. So let's delete that customer within Stripe. So again, if you take a look at the code, what this should do is hit the endpoint and hit this method. So it should mark these columns as null. So as you see right now, Stripe ID and card brand is filled out because we have that user in Stripe right here. So this should be null after everything happens if I did everything correctly. So let's try that. Let's delete this customer.
So let's try that. Let's delete this customer. Delete. Okay, and it might take a second. Okay, so the customer was deleted. We can take a look at the exposed dashboard as well, or the tool in the CLI. And you can see it did hit this endpoint here. And now if you take a look at our database, this should be null when I refresh, or these two, or these three. And they are cool.
Override Webhook Event Handler7:21
Here's the request that Stripe made to our endpoint. And here is the response that our server gave to Stripe. Now if you want to customize that functionality or add a new event, then just add the event here. And we also have to customize the controller. So for this Controller that I showed you that had the logic, if you either wanted to customize this or add a new event, then we have to override this method or make a new one for a new event. So let me show you what I mean. So up here, or no, it's down here, right here. So in this case, I am going to override the same event, so the CustomerDeleted event.
So up here, or no, it's down here, right here. So in this case, I am going to override the same event, so the customerDeleted event with this new controller. So as you see, this new controller that we're going to create extends the WebhookController that I just showed you. And then for whatever event you want to listen to, you can just create a new one or override the one if you're overriding a current event, like we're going to do here. So let me just open this up again. It's lc, cashier, new, Stripe, sorry, okay. And let's do php artisan make:controller.
It's lc, cashier, new, Stripe, sorry, okay. And let's do php artisan make:controller. Let's call it WebhookController as well. Or you can name it something else if you want. Okay. And let's go ahead and open that WebhookController. And it's right here. And let's extend this CashierController, which is this other WebhookController from the package directory. Let's grab this out of here.
the package directory. Let's grab this out of here. Oops. Okay. And let's grab this import. And I don't think we need request. And now in our case, I'm just going to copy and paste this method because this is the one I want to override. But if you want to respond to another event, just make a new method called handle and whatever the event name is in camelCase.
But if you want to respond to another event, just make a new method called handle and whatever the event name is in camel case. So let me just grab this, put it in our controller, and we'll add some extra logic in here to make sure it works. And I always forget this when I'm overriding methods, but you also have to import anything that you're using here. So in our case, subscription. And let's make one extra piece of functionality. So we know we're calling this one instead of the other one. So I'm just going to log something into the log.
So we know we're calling this one instead of the other one. So I'm just going to log something into the log. Let's just say customer was deleted. And then we'll add that customer's information. So user email. And let's make sure to import log. Okay. And let's try this out. So I deleted my customer in Stripe. So I have to make another one in Stripe again.
So I deleted my customer in Stripe. So I have to make another one in Stripe again. So I'm just going to migrate fresh seed. So we delete our user in our database and just go through the same steps. So let me create a new user again. The register route. I'm going to create the same user. Okay. This should log us in. And let's go ahead and subscribe again.
This should log us in. And let's go ahead and subscribe again. So we create this User in Stripe. MASH 4.2. Create the User in Stripe. Okay. Let's make sure that that User was created. Okay. There it is. And before I delete the User, let me just clear my log here.
There it is. And before I delete the User, let me just clear my log here. Okay. I'm going to delete everything in my laravel.log. And now let's go ahead and delete this User. Make sure my exposed tunnel is still up. And it is. Delete this User. Delete and delete. And let's see this happen in our exposed dashboard, hopefully.
Route Custom Webhook Controller11:35
And nothing's happening. So I definitely have an error. So it was a 200. Okay. So there's no error. So I know what I forgot to do. I forgot to set up the route for that new controller. And that's in the documentation. I just forgot to scroll down. So now we have to overwrite this to make use of the custom controller that we have.
I just forgot to scroll down. So now we have to overwrite this to make use of the custom controller that we have. So sorry about that. We're going to have to make that User again in Stripe, but I'll just edit that out. So let's go to our routes file. Let's add this new route. Make sure to import WebhookController and make sure to import the one that we created. So this one. So it's yeah, this one. And it's pointing to this handleWebhook method that we also created.
So it's yeah, this one. And it's pointing to this handleWebhook method that we also created. So not that one, but this one actually, yes, this one, because it's extending this one over here. Okay. And I'm going to do the same process. I'll just edit that out. I'm going to php artisan migrate:fresh --seed again. And I'm also going to create a new User in Stripe because I just deleted it and it should be empty when I refresh.
And I'm also going to create a new User in Stripe because I just deleted it and it should be empty when I refresh. Okay. So I'll just edit that in. Okay. Customer is back in Stripe. I am going to delete the customer again. Make sure I save my route file. Okay. I did.
