#richard-subscription-post

1 messages ยท Page 1 of 1 (latest)

rough turretBOT
astral shoal
#

Hello ๐Ÿ‘‹
Can you share some example events?

young canyon
#

The JSON?

astral shoal
#

event IDs

#

evt_xx

young canyon
#

Oh just the id, sure

#

Here is the latest one: evt_3Nud8lHmbFSnTqkp1wQOAvfa

astral shoal
#

It seems to be coming from your node server

young canyon
#

So it's a problem with the code?

astral shoal
#

Yes

#

You'd likely want to check if you're calling subscriptions API from a conditional somewhere

young canyon
#
exports.stripeWebhookPaymentIntent = onRequest(async (req, res) => {
  const sig = req.headers["stripe-signature"];

  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.rawBody,
      sig,
      "whsec_ZxpfuVomIUNTnOZk31ayR06teinexnoG"
    );
  } catch (err) {
    res.status(400).send(`Webhook Error: ${err.message}`);
    return;
  }

  // Handle the event
  switch (event.type) {
    case "payment_intent.succeeded":
      const paymentIntentSucceeded = event.data.object;
      const proPrices = [
        { price: process.env.PRICE_PRO_FLAT, quantity: 1 },
        { price: process.env.PRICE_PRO_USAGE },
      ];

      const elitePrices = [
        { price: process.env.PRICE_ELITE_FLAT, quantity: 1 },
        { price: process.env.PRICE_ELITE_USAGE },
      ];

      try {
        const subscription = await stripe.subscriptions.create({
          customer: paymentIntentSucceeded.customer,
          payment_settings: { save_default_payment_method: "on_subscription" },
          items:
            paymentIntentSucceeded.metadata.plan == "pro"
              ? proPrices
              : elitePrices,
        });
        logger.log({ subscriptionCreated: subscription });

        return res.json();
      } catch (e) {
        logger.error({ stripeError: e });
        return res.status(401).json({ stripeError: e });
      }
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  // Return a 200 response to acknowledge receipt of the event
  res.send();
});

#

Is this switch statement a problem here?

rough turretBOT
young canyon
#

I thought it's commonly used for webhooks

astral shoal
#

So you're not checking if the payment_intent.succeeded event came from a subscription invoice payment or not.

#

which might be causing the infinite loop

young canyon
#

I'm sorry I don't understand. How would I do that?

astral shoal
young canyon
#

Okay, but what do I do with this to not get the loop? I don't understand how is this generating the loop

astral shoal
#

If it belongs to an existing subscription then you would want to avoid creating a new subscription

So don't call create subscription API

young canyon
#

Oh, so the paymentIntent webhook creates new subscription which is immediately paid, so there is another webhook and so on. Am I understanding it right?

astral shoal
#

Correct, that's the loop

young canyon
#

Okay, I'll do what you said. Thanks

astral shoal
#

NP! ๐Ÿ™‚ Good luck

young canyon
#

Sorry, one more question, because I think I'm creating the subscription wrong here. If I create a subscription after getting paid (when payment_intent.succeed occurs) should I create this subscription with status=active to prevent from charging the customer with creation of the subscription?

astral shoal
#

Yes. Let's take a step back. What's your end goal here?

Seems like you're creating a one-off PaymentIntent prior to creating the subscription.

mighty loom
#

richard-subscription-post

young canyon
#

Yes, it's a android app so I chose the way to first show the PaymentSheet from sdk and after user inputs payment method I create a subscription

#

I don't want to create a subscription every time user accidently presses a button so I take the payment info and charge them first

mighty loom
#

@young canyon Then the best option is to create the Subscription with a trial period upfront since they already paid the first month and then you pick trial_end to be whenever you want their next payment to happen

young canyon
#

You mean instead of status=active right?

#

I think creating already active subscription (if it's possible) will be less confusing. With trial_end the status will be trialing which might be kinda confusing for me

#

But I guess I'm gonna try both ways

mighty loom
#

the idea is that you collect card details first and then instead of creating a PaymentIntent you create a Subscription with default_incomplete and confirm its underlying PaymentIntent. It's just way harder to design and build and I can't help you with the flutter specific parts

young canyon
#

So there is not such thing for mobile develompent provided by Stripe right?

mighty loom
#

We have tons of mobile development solutions. We have an iOS, Android and React Native SDK, but we don't have a flutter one

young canyon
#

Oh damn ๐Ÿ˜‚

young canyon
mighty loom
#

I would try that way I just told you it likely is supported by Flutter sincethey have that "deferred" flow in the doc you linked me to

young canyon
#

I just was about to explain to you why it is not possible in Flutter with this third-party SDK and it the process of explaining it here I realized it is indeed possible ๐Ÿ˜‚

#

I don't know why haven't I done it like that before

#

Because when you create a subscription with default_incomplete you have access to its paymentIntent client_secret right?

#

If you expand it

#

If this is a case then it's possible for sure and it's thousand times easier to implement.

#

Thanks for suggesting that and refreshing my mind

mighty loom
#

to be clear the whole "defer intent" is new-ish, it shipped like 3 months ago on our end and then it took a while for our Mobile SDKs to add support and the Flutter 3rd party builds on top of our Mobile SDK so I am not surprised