#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/1450131042164801546
๐ 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_code, 2 days ago, 18 messages
- ironbeard_code, 2 days ago, 31 messages
- ironbeard_integration-questions, 3 days ago, 36 messages
- ironbeard_code, 4 days ago, 37 messages
Here's my code in the checkout (to save a PM first and then show a "review your order" page with PM details before creating the Subscription):
form.addEventListener('submit', async (event) => {
event.preventDefault();
const { setupIntent, error } = await stripe.confirmSetup({
elements,
redirect: 'if_required',
confirmParams: {
expand: ['payment_method'],
return_url: window.location.origin + "{{ next_url }}",
}
})
if (error) {
message.innerText = error.message
} else if ( false ) {
// Your customer will be redirected to your `return_url`. For some payment
// methods like iDEAL, your customer will be redirected to an intermediate
// site first to authorize the payment, then redirected to the `return_url`.
} else {
const pm = setupIntent.payment_method
// Use pm to fill out some hidden form fields to send to server, like pm.id, pm.card.last4
}
Hi ๐ yes you can, depending on your exact requirements. Is something not working as you're hoping when you test it out?
https://docs.stripe.com/payments/accept-a-payment?platform=web&ui=elements#enable-saving-the-payment-method-in-the-payment-element
Oh wait, or are you saying you want to build your own page?
Yeah, I was going to put it in my accounts page, something like this:
I suppose I was wondering how I can capture the changed details for an updated / deleted PM, since I probably won't be calling confirmSetup() in js when those actions happen. Do I hjave to just rely on webhooks?
Or is this not an intended usecase for PaymentElement?
Hm, I don't think it's meant to be used that way. Do you have the ID of a Payment Method you tried to update? We can see if that generated any Events you could use, though initially I'm thinking of server-side Events. Let me think through whether this may throw anything client-side.
well, idk if I should use it this way if it feels like I'm going against the grain. I suppose I wanted something like https://docs.stripe.com/customer-management/portal-deep-links#what-is-a-flow the "payment_method_update" portal flow, but hosted on my own site
(and really, I kind of want to limit customers to one PM per account, and have that be their default, but let them change/update the PM as they see fit, but that restriction isn't worth a whole lot of extra work)
Hhmm gotcha. I agree that Saved Payment Methods don't sound like the perfect fit for that. I think it's more a checkout-streamlining solution rather than a full-fledged wallet management solution.
If you showed SPM just before paying, that could be helpful, but I think it would be tricky to make this work decently well for managing payment methods for Subscriptions (I'm guessing but it sounds like that's where this is heading).
SPM?
Saved Payment Methods, sorry, it's internal shorthand that slipped out
No worries ๐ (and yeah, all products are subscriptions).
I might just go with the "payment_method_update" flow. Is the idea that, when a user logs into my website I can create a stripe.billing_portal.Session? Since there's links to e.g. Accounts > Wallet on the menu of every page, I'd like to avoid hitting the Stripe API that often
Yup, that's how the flow starts. You create a Billing Portal Session for your Customer, and you can use the payment_method_update flow to deeplink them straight to payment method updates when they access the generated link.
It will redirect your customers to our hosted page rather than keeping them on your site though.
yeah. It was easy enough to make my own CRUD form for cards, but I'm not really sure what details would get updated if they had ACH Credit or Bank Transfer PMs, which I'm now adding to supported options
Looking at what the API exposes support for updating, I only see cards and ACH Debits that seem to have updatable fields aside from billing details:
https://docs.stripe.com/api/payment_methods/update
Letting customers just add new PMs may be easier than needing to allow them to update existing ones.
Good point. Just allow them to add a new one and handle removing/detaching/deleting old ones internally.
What's the parameter to make a new payment method the customer's default for everything? Will a customer default override a Subscription default pm?
Setting it as the invoice_settings.default_payment_method on the Customer makes it the default for the Customer, but any default_payment_method set at the Subscription level will take precedence over that value.
So if you're setting it at the Subscription level, you'll want to loop through all active Subscriptions for the Customer, and either unset the default_payment_method (if you're switching to setting this at the Customer level) or update it to the desired new Payment Method.
So easier to not specify default_payment_method at the Subscription level, just create a Subscription with customer and payment_behavior='default_incomplete' will grab the default pm of the customer and attempt payment immediately?
Not with default_incomplete, first payment won't be attempted then. You'll want to use allow_incomplete if you want to immediately attempt the first payment. (Or error_incomplete is an option if you'd rather receive an error back for incomplete initial payments)
Though I do recall us talking about how default_incomplete was better for your use-case recently, not sure if that was a different project
Okay, I think I see the path forward. Does PaymentElement have a param that allows me to make sure the PM created via the SetupIntent is set as customer.invoice_settings.default_payment_method, or do I need to do that on the backend?
You'll need to set invoice_settings.default_payment_method on the Customer object yourself
Yeah, I think default_incomplete was necessary before I moved to having a /checkout/review page. My situation involves potentially having two Subscriptions per customer (a newsletter and a SaaS), so if I was creating the Subscriptions before getting the PMs (to display invoices, possibly prorated invoices for upgrades), then I think I'd have to create the Subscriptions with default_incomplete, but then I couldn't display the PM details in a /checkout/review page.
So now I'm using PaymentElement on /checkout/payment (with a customer id that was create in the previous step, /checkout/info), and then on the review page, when someone clicks "Submit Order" I'm creating (one or two) Subscriptions there and letting them attempt payment at that point
Gotcha!
But if I had a Customer with a default payment method set (from /checkout/payment/) and two Subscriptions with a customer id set and default_incomplete (created on GET of /checkout/review/ to show full invoice details and so they didn't attempt charge immediately), what kind of API call could I use to charge the cards on the subscriptions when the customer hits "Submit Order" (e.g., on POST of /checkout/review/)?
That's when you can make a request to confirm the Payment Intent associated with the first Invoice that was generated for the Subscription(s).
oooh. Right. So subscription.latest_invoice.payment_intent. and I could just try to confirm it, I wouldn't need to pass any payment method details? The nature of the payment_intent is that it already knows the customer and subscription/invoice and payment method that it's for?
Correct, the Subscription will pull the default Payment Method from the Customer and pass that to the Invoice it creates, which passes it down to the Payment Intent.
Does that feel like a front end or backend thing to you? My website is a very traditional hypermedia / "multi-page app"
It feels like a backend request to me. The only reason I can think of to do it client-side, is if it's likely customer action will be required to attempt the payment. But it sounds like that will already be handled, and most of the time the first payment won't require customer action.
And if you're confirming two payments at once, you're going to want to catch the outcomes of that to make sure it gets displayed to your customer the way you want. (For instance if one succeeds but the other fails)