#richard-subscription-post
1 messages ยท Page 1 of 1 (latest)
Hello ๐
Can you share some example events?
The JSON?
Seems like that event was generated in response to this request
https://dashboard.stripe.com/test/logs/req_xpZKHpikBXj8jA
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
It seems to be coming from your node server
So it's a problem with the code?
Yes
You'd likely want to check if you're calling subscriptions API from a conditional somewhere
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?
I thought it's commonly used for webhooks
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
I'm sorry I don't understand. How would I do that?
You can check if the PaymentIntent belongs to an invoice by looking at invoice parameter
https://stripe.com/docs/api/payment_intents/object#payment_intent_object-invoice
you can expand that parameter, to get the subscription ID that invoice belongs to
Okay, but what do I do with this to not get the loop? I don't understand how is this generating the loop
If it belongs to an existing subscription then you would want to avoid creating a new subscription
So don't call create subscription API
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?
Correct, that's the loop
Okay, I'll do what you said. Thanks
NP! ๐ Good luck
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?
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.
richard-subscription-post
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
Pretty much the same thing that is explaied here:
https://docs.page/flutter-stripe/flutter_stripe/sheet_deferred
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
@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
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
The right option is completely different but you're using a 3rd party tool for Flutter that isn't built by Stripe so it's complex to help you. The right integration path is https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&type=subscription
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
So there is not such thing for mobile develompent provided by Stripe right?
We have tons of mobile development solutions. We have an iOS, Android and React Native SDK, but we don't have a flutter one
Oh damn ๐
You think this way is possible to do with custom UI or something? Or should I stick with what I have done already? What do you think?
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
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
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