node.jsstripe-paymentsstripes

Stripe cancel url does not cancel the payment, so stripe does not send a cancel payintent


I'm using stripe with node js to make payment, and I'm creating a session and using the stripe checkout interface. I'm using a webhook for listening to the events, when the payment is created or successfully so stripe sends payment_intent.succeeded so I do something with it. But the problem is when I click on the cancel url to cancel the payment, stripe does not cancel the payment or send a payment_intent.canceled which it is a problem because then I do not know if the payment canceled and I can not do what I planed to do. Here is my code:

// This will share the stripe publickey with the frontend
const webhook = async (req, res) => {
  // Signature verification
  const playload = req.body;
  const sig = req.headers["stripe-signature"];
  const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

  let event;

  try {
    // Checking if the response is actually from stripe
    event = stripe.webhooks.constructEvent(playload, sig, endpointSecret);
  } catch (error) {
    console.log(error.message);
    res.status(400).json({ success: false });
    return;
  }

  // Getting the ad id
  const adID = event.data.object.metadata.id;
  const userEmail = event.data.object.metadata.email;

  // Checking if the payment did faile
  if (
    event.type === "payment_intent.canceled" ||
    event.type === "charge.failed" ||
    event.type === "charge.expired"
  ) {
    const paymentIntent = event.data.object;
    console.log(`PaymentIntent ${paymentIntent.status}`);

    // Sending the deleting request
    await axios.delete(`${process.env.SERVER_URL}/api/v1/single-ad`, {
      data: { id: adID, email: userEmail },
    });

    return res.status(200).json({ message: "Ad is successfully deleted" });
  }

The if statement is never executed because stripe does not send any thing back if the payment is canceled.


Solution

  • The cancel_url field on a CheckoutSession does not automatically cancel the PaymentIntent associated with the CheckoutSession.

    Therefore, this is expected to not happen:

    But the problem is when I click on the cancel url to cancel the payment, stripe does not cancel the payment or send a payment_intent.canceled

    The cancel_url is for if the customer presses the "back" button on the top right of the Checkout page, to cancel out of the payment page. So it would be a URL of your website you specify to land your customer on.

    Even after navigating to a cancel_url, the CheckoutSession remains usable (until it is manually expired or expires by default 24 hrs after creation) or your code cancels the underlying PaymentIntent.