Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

MooseSaid's avatar

How to use Stripe client side events

So, I got Stripe working and payment is successfully taken. The problem is that I want to do specific backend actions once payment has been confirmed that it's successful. According to Stripe documentation here That they recommend using their client side events instead of using webhooks, but how would I do that? I thought of making Stripe return me to a route that checks the payment status and if it's successful It shows the success message to the user and send a request to another route to do the actions I need, but thinking about it, if the user kept refreshing this page the action will keep happening. What is the best way to do this? I found Spatie package That would help if i decided to go with webhooks but I'm trying to follow Stripe documentation and recommendations.

0 likes
6 replies
MohamedTammam's avatar

Why not using Laravel cashier and do the payment from your back-end.

If you're not doing it from your back-end, then use webhooks.

1 like
MooseSaid's avatar

@MohamedTammam I'm using Stripe PHP package to make a one time payment. The backend handles the payment amount and everything while the front end is being used only to pass card details. so now I just want a way to fetch the success response to do backend actions. I'm trying to figure out what to do in this case.

martinbean's avatar

@moosesaid Nope, you absolutely should be using webhooks to fulfill orders on successful payments, and not rely on client-side events.

The user could close the tab (accidentally or deliberately), lose connection, or suffer a power outage between a payment being confirmed and any client-side code completing. This is why you should use webhooks: webhooks will be tried and retried until successful.

1 like
MooseSaid's avatar

@martinbean Okay so can you just help me wrap my head around webhooks? I mean,

I have a stripe controller that creates payment intent with amount and currency on checkout page mount.

$paymentIntent = PaymentIntent::create([
                'amount' => $amount,
                'currency' => $currency,
                'automatic_payment_methods' => [
                    'enabled' => true,
                ],
            ]);

then a user makes a payment and I'm confirming the payment like so

async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const { error } = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: "url to where???????",
    },
  });

}

Now what? where should the return_url take the user to? I was considering that it takes the user to a page where it sends another request to the controller and check if the submission was successful because that's the only way I could see that can be adhering to Stripe docs

Stripe recommends handling the payment_intent.succeeded, payment_intent.processing, and payment_intent.payment_failed events.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events is what enables you to accept different types of payment methods with a single integration.

Now if i'm to use webhooks, what should I change? you don't need to code anything just give me the idea and I will dig up the internet

Snapey's avatar
Snapey
Best Answer
Level 122

@MooseSaid return url is what you want the user to see after they complete the payment. ie, a thanks for your order type page, or whatever.

But really you need to confirm that stripe is happy by creating a webhook endpoint and then setting this in the stripe website.

You tell Stipe what events you want to listen to, and the URL that should handle it.

For instance, I have an API route /stripe-webhook which receives ALL webhooks from stripe, validates its stripe calling the endpoint and then processes the event. Processing might just involve setting the status of an order to 'paid'. This bit is really down to your app to decide. Since the webhook is asynchronous, you need to add data into the payment intent that lets your app know which transaction or customer the webhook is concerning. One way is to store the payment intent id, but you could also put meta data in the payment intent, such as order id

1 like
MooseSaid's avatar

@Snapey Thank you so much! I decided to go for Spatie package and handle the webhooks with jobs.

Please or to participate in this conversation.