Fulfill your orders
Learn how to fulfill orders after a customer pays with Stripe Checkout.
You wrote the code to display a beautiful payment form on your website. Now, when a customer pays, you need notification that you can fulfill their order.
In this guide, you’ll learn how to:
- Receive an event notification when a customer pays you.
- Handle the event.
- Use Stripe CLI to quickly test your new event handler.
- Optionally, handle additional payment methods.
- Turn on your event handler in production.
Install Stripe CLI
The quickest way to develop and test webhooks locally is with the Stripe CLI.
As a first step, follow the install guide for Stripe CLI.
After you finish the install guide, run the following command to test that your Stripe CLI installation works:
stripe status ✔ All services are online.
If you see a success message after running stripe status
, you’re ready to move on to the next step.
Create your event handlerServer-side
In this section, you’ll create a small event handler so Stripe can send you a checkout.session.completed
event when a customer completes checkout.
First, create a new route for your event handler. Start by printing out the event you receive. You’ll verify that delivery is working in the next step:
Testing
Run your server (for example, on localhost:4242
). Next, set up Stripe CLI to forward events to your local server, so you can test your event handler locally:
stripe listen --forward-to localhost:4242/webhook Ready! Your webhook signing secret is 'whsec_<REDACTED>' (^C to quit)
Next, go through Checkout as a customer:
- Click your checkout button (you probably set this up in the Accept a payment guide)
- Fill out your payment form with test data
- Enter
4242 4242 4242 4242
as the card number - Enter any future date for card expiry
- Enter any 3-digit number for CVV
- Enter any billing postal code (
90210
)
- Enter
- Click the Pay button
You should see:
- A
checkout.session.completed
in thestripe listen
output - A print statement from your server’s event logs with the
checkout.session.completed
event
Now that you’ve verified event delivery, you can add a bit of security to make sure that events are only coming from Stripe.
Verify events came from Stripe
Anyone can POST data to your event handler. Before processing an event, always verify that it came from Stripe before trusting it. The official Stripe library has built-in support for verifying webhook events, which you’ll update your event handler with:
Testing
Go through the testing flow from the previous step. You should still see the checkout.session.completed
event being printed out successfully.
Next, try hitting the endpoint with an unsigned request:
curl -X POST \ -H "Content-Type: application/json" \ --data '{ fake: "unsigned request" }' \ -is http://localhost:4242/webhook HTTP/1.1 400 Bad Request ... more headers
You should get a 400 Bad Request
error, because you tried to send an unsigned request to your endpoint.
Now that the basics of the event handler are set up, you can move on to fulfilling the order.
Fulfill the orderServer-side
To fulfill the order, you’ll need to handle the checkout.session.completed
event. Depending on which payment methods you accept (e.g., cards, mobile wallets), you’ll also optionally handle a few extra events after this basic step.
Handle the checkout.session.completed
event
Now that you have the basic structure and security in place to make sure any event you process came from Stripe, you can handle the checkout.session.completed
event. This event includes the Checkout Session object, which contains details about your customer and their payment.
When handling this event, you might also consider:
- Saving a copy of the order in your own database.
- Sending the customer a receipt email.
- Reconciling the line items and quantity purchased by the customer if using
line_item.adjustable_quantity
.
Add code to your event handler to fulfill the order:
Testing
Ensure that stripe listen
is still running. Go through Checkout as a test user, just like in the prior steps. Your event handler should receive a checkout.session.completed
event, and you should have successfully handled it.
Handle delayed notification payment methodsServer-side
This step is only required if you plan to use any of the following payment methods: Bacs Direct Debit, Boleto, Canadian pre-authorized debits, OXXO, SEPA Direct Debit, or SOFORT.
When receiving payments with a delayed notification payment method, funds aren’t immediately available. It can take multiple days for funds to process so you should delay order fulfillment until the funds are available in your account. After the payment succeeds, the underlying PaymentIntent status changes from processing
to succeeded
.
You’ll need to handle the following Checkout events:
Event Name | Description | Next steps |
---|---|---|
checkout.session.completed | The customer has successfully authorized the debit payment by submitting the Checkout form. | Wait for the payment to succeed or fail. |
checkout.session.async_payment_succeeded | The customer’s payment succeeded. | Fulfill the purchased goods or services. |
checkout.session.async_payment_failed | The payment was declined, or failed for some other reason. | Contact the customer via email and request that they place a new order. |
These events all include the Checkout Session object.
Update your event handler to fulfill the order:
Testing
Ensure that stripe listen
is still running. Go through Checkout as a test user, like you did in the prior steps. Your event handler should receive a checkout.session.completed
event, and you should have successfully handled it.
Now that you’ve completed these steps, you’re ready to go live in production whenever you decide to do so.
Go live in production
After you’ve deployed your event handler endpoint to production, you need to register your live URL with Stripe. Follow this quick guide to set that up.