#ironbeard_best-practices
1 messages ¡ Page 1 of 1 (latest)
đ Welcome to your new thread!
â˛ď¸ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
âąď¸ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
đ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1450498242407305269
đ Have more to share? Add more details, code, screenshots, videos, etc. below.
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- ironbeard_subscription-save-payment-methods, 19 hours ago, 62 messages
- ironbeard_best-practices, 22 hours ago, 41 messages
- ironbeard_code, 3 days ago, 18 messages
- ironbeard_code, 3 days ago, 31 messages
- ironbeard_integration-questions, 4 days ago, 36 messages
- ironbeard_code, 5 days ago, 37 messages
Hey there, happy to help you explore options here, but first want to push back on this lightly
One subscription is for SaaS access and the other is a for a newsletter, so unfortunately I kind of need to keep them separate.
What leads you to wanting to keep these separate?
sure
Are they for different billing cadences, or you want management to remain individual in portal, separate discounts/cancellation etc
Just want to understand the parameters before diving in
always happy to make sure I'm doing the right thing. We offer a newsletter subscription (monthly via email, for one year) and a SaaS (website access for a year).
So in order to prevent someone from upgrading to the plan that contains all the data in the last hour, downloading everything, then cancelling, I have to set billing_cycle_anchor: 'now' and proration_behavior: 'always_invoice'.
But if they had the newsletter in the same Subscription, then that would force them to pay for "future" issues right then / extend their newsletter subscription for another year.
I know that's not the WORST thing that could happen (and very very likely to never happen tbh), but it's a consideration I need to bring to the conversation.
I believe the important part is this: any time someone upgrades, they must pay for the full year of access at that point in time. it seems like an inevitable side-effect of this is, that if they had a newletter too, then they must extend the newsletter too, since billing anchor changes and all plans are yearly.
gotcha, ok. That makes sense for saas upgrade management.
I'm asusming, and correct me if wrong, that the saas subscription is considerably higher value than the newsletter
Not really, im just going to treat that as the "primary" subscription
While we are working on making manual reconciliation of payment intents to invoices more flexible, currently what you ask is not possible as framed (bear with me for what i think is a reasonable workaround).
This feature currently allows you to apply multiple payment intents against an open invoices to split up payments: https://docs.stripe.com/invoicing/payment-application
In the future, this method (or a very similar method) will also support applying part of a payment intent to an invoice, so will allow reconciling multiple invoices with a single payment intent.
interesting
Today, what I'd recommend is using your saas subscription as the primary subscription for the elements payment, and leverage add_invoice_items to add a one-time line item for the first newsletter period (optionally discounted, if you like) and complete the payment for the saas plan to collect the customers default invoice payment method.
Then with that PM on file for the customer, you cna create the second subscription for the newsletter with the first period as a free trial, since it was paid as a one-time line item on the primary sub.
(free trial, zero amount price via schedule, or deferred start via schedule all ~interchangeable and up to your preference. if you need to have the active sub in place for your provisioning, then deferred start might not be the best option)
I think at the end of the day, it's not difficult for me to use SetupIntent to collect a pull payment method and associate it with it with two Subscriptions (or set it as customer.invoice_settings.default_payment_method) and confirm their latest_invoice.payment_intent.
But if a client has to use a push PM (bank transfer, and we have a few that do require this), and I create a PI for the sum in order to pass that to the PaymentElement (since 1) I can't use SetupIntent for push PMs like bank transfer, and 2) PaymentElement will require SetupIntent or PaymentIntent, right?). This provides the customer with the modal window with the bank account info for them to transfer. If they send the sum of the two invoice subscriptions, I'm hoping it'll cover the open invoices?
One unfortunate side effect, I suppose, is that the modal window will ask them to include a reference number for the summed PI, not the reference numbers for the two PIs associated with open invoices.
interesting, I need to look more into that. Does your method above preclude me from having a /checkout/review page where I show summary info (include payment method info) before they click a button to confirm the transaction?
Nope, you'd just need to represent the pricing structure to them appropriate on that page (ie, make sure to explain there will be two recurring payments after the single initial payment)
We describe our reconciliation logic here: https://docs.stripe.com/payments/customer-balance/reconciliation#cash-automatic-reconciliation
Ultimately if they sent the correct total (or more) the two invoices should both be paid by the transfer
A given customer has only one VBAN to receive funds, so all reconciliation is central
It's not per-subscription
I'm a little confused with your Subscription + invoice item idea. If I wanted to defer charging the card until after payment method is collected (e.g., /checkout/payment/ will display the PaymentElement, and /checkout/review/ will display user, subscription, and PM info (not in a form) with a "submit purchase" button), do I have to use SetupIntent?
hi there, taking over this thread as synthrider had to step away, give me a few moments to catch up
testing something out real quick, hang tight
ok, just wanted to make sure this would work. you can use the deferred intent flow, similar to what is described here: https://docs.stripe.com/payments/build-a-two-step-confirmation
but instead of using a raw Payment Intent like that doc describes, you would create your subscription while expanding latest_invoice.confirmation_secret and use that secret along with the confirmation token you get from collecting the payment method
you would also want to make sure that in your Payment Element options, mode is set to subscription instead of payment
Do you mean, stripe.Subscription.create(..., expand=['latest_invoice.payment_intent']) and send that PI's client secret to the front end with the PaymentElement, and then use stripe JS createConfirmationToken when the PaymentElement is submitted?
it depends on what API version you're using. older API versions before Basil have latest_invoice.payment_intent, but that went away when Basil stopped having a direct link between Invoice > Payment Intent. with newer API versions, we expose latest_invoice.confirmation_secret as a way to get the secret for the Subscription's first PI immediately on creation
but other than that, yes you're correct
oh, interesting. good to know.
When I use SetupIntent with PaymentElement, I can do
await stripe.confirmSetup({
elements,
redirect: 'if_required', # I don't use PMs that require redirect
confirmParams: {
expand: ['payment_method'],
return_url: window.location.origin + "/checkout/review/",
}
})
// Fill hidden fields using the PM summary info to send it back to server
Can I do a similar expand with the createConfirmationToken?
createConfirmationToken will return a Confirmation Token API object, which will give you the fields documented here https://docs.stripe.com/api/confirmation_tokens/object
the actual Payment Method will be created after the PI is confirmed with that token
but the payment_method_preview attribute on the Confirmation Token will have much of the same info. i.e. for a card, it'll have the brand, expiration, last4 etc
What's the benefit of using ConfirmationTokens vs SetupIntent + creating the PaymentMethod before the /checkout/review/ page?
I suppose I can see ConfirmationToken being nice if I was doing using a SPA framework, but since I have to hit the server between /checkout/payment/ and /checkout/review/ anyways, it seems like SetupIntent is more straightforward, unless there's something that Subscriptions do that would make it require less Stripe API calls?
so the main benefit is that you would only have one authorization. confirming a Setup Intent performs an authorization, and then charging the Subscription would do another one. so it's possible that a customer might have to go through 3DS flow twice, for exmaple
whereas creating a Confirmation Token doesn't perform an auth
oh, interesting
some payment methods also do not support Setup Intents https://docs.stripe.com/payments/payment-methods/payment-method-support#additional-api-supportability
You mean that if I tried to call stripe.PaymentIntent.confirm() on the backend using the PI from subscription.lastest_invoice.payment_intent (using older API) that I could potentially need input from the customer e.g. 3DS flow?
it's possible, yes, which is why we recommend doing that on the front end with stripe.confirmPayment() if you can. it's rare, because we communicate to the bank that it's an off-session transaction, but Stripe can't control when a bank requests 3DS
Since the /checkout/review/ page allows the customer to go back and change what's in their cart, does it make sense to defer the creation of the Subscription until they have pressed the final "Confirm Purchase" button? In that instance, what do I pass to initialize stripe.elements() (on /checkout/payment/)? Just an amount (which I can estimate from using invoice preview) and currency?
I think that makes sense given your flow, yes. you would just pass amount and currency to the elements options
This is probably obvious, but is it crucial that the amount passed to the PaymentElement match the final amount for the PaymentIntent passed to .confirmPayment? It's easy for me to calculate amount most of the time without hitting Stripe servers, just based on what's in their cart, but in the case of subscription updates, I'd need to hit stripe to get the prorated amount.
interesting, I just tested this out, and having a different amount passed to the Payment Element vs. what's on the PI doesn't cause any issue when confirming the PI. based on this line in the docs here I think those params just determine how the PE is displayed / which payment methods are available.
all that to say, I would definitely make your best effort to match the two
Looks like amount is required when using mode: subscription. What's the benefit of using that mode vs mode: setup? Does mode: setup require a SetupIntent?
yes, mode: setup is specifically for working with SetupIntents
Hi there. I'll be taking over for denton here, who needs to step away
so mode: subscription (with amount: x) won't display Bank Transfer in the PE (makes sense). So if I want to offer Bank Transfer in the PE, I need to create the Subscription and pass latest_invoice.payment_intent to the PE (or .confirmation_secret in newer API). Does it still make sense to call stripe.createConfirmationToken() in a situation where someone chose Bank Transfer in the PE? Or what do I need to examine in order to split the logic there?
Just to make sure to call this out since it is a common question, in API versions after 2025-03-31.basil, latest_invoice.payment_intent doesn't exist any more. I assume you're on a API version before that, but there are numerous breaking changes in Billing in 2025.
I think what you're saying is that, because you want for your customers to be able to choose bank transfers to pay their Subscriptions, you're going to create the Subscription and get the client_secret from its initial Invoice, and then you'll use that to render the Payment Element and the Payment Element will get available payment method types from the PaymentIntent (which belongs to the Subscription/Invoice).
So, no, there would be no reason to create a confirmation token in that case. A confirmation token flow would be like you want to collect (a subset of) payment method details, then do some business logic, and then create a Subscription completely on the backend
Well, my real intent is to create a /checkout/review/ page that shows PM summary details (when not using Bank Transfers) that come from /checkout/payment/. In the event of an actual "pull" PM being used (aka not bank transfers), the /checkout/review/ page would have a button to actually confirm the transaction.
Yeah, so that would be like a two-step confirmation process, which we have a specific guide for here, though that is for one-off payments.
Another thing that is pretty common to do is just give the customer an election in the UI like "I want to pay by bank transfer" and "I want to pay another way" and then go one of two logical routes
Yeah, I was just gonna say something similar. Maybe after I collect the customer details, I can offer two buttons to split the path between bank transfer and others.
Thanks for all your help. As a final question, what are the minimum required init args I need to pass in order to get Bank Transfer to show up? It requires either:
- a
PaymentIntent, or amount+currency+mode=payment,
right? I suppose passing a SetupIntent doesn't make sense, nor does mode=setup|subscription.
(and createConfirmationToken requires mode=payment|subscription, amount, and currency, right?)
A question which will clarify the right answer: what collection_method are you using on your non-bank transfer subscriptions? charge_automatically or send_invoice?
If someone isn't using bank transfer, then their subscription should be paid for once they click a button that calls stripe.confirmPayment() with the confirmationToken and paymentIntent from latest_invoice.
Looking at those docs, I think charge_automatically. Yeah, I have that set as the default in my code.
And I ask because Bank Transfers only work with send_invoice subscriptions (guide) so if you're doing charge_automatically for other Subscriptions, it might be easier/better to just provide a UI election like "I want to pay by bank transfer" or "I want to pay another way" and then go down one of two logic paths, because you're going to need a differently shaped api call to POST /v1/subscriptions
with bank transfers, Elements are really only a method of displaying the funding instructions to the user, which can also be had from the Hosted Invoice Page, for what that's worth
so that would be like
Q: Bank Transfers or other stuff?
if Bank transfers:
1. call backend, create Subscription with payload A, get PaymentIntent client secret, use it to render the Payment Element which will display funding instructions to the customer
else
2. either render Payment Element in mode: 'subscription or follow a similar flow as #1 and then pass the first Invoice's client secret back to the client to confirm the payment
I had to step AFK for a bit, but this is very clear, I appreciate the effort. Thanks!