#trippleg_api

1 messages · Page 1 of 1 (latest)

umbral matrixBOT
#

👋 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/1283857637632512021

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

cinder veldt
#

Hello! So it sounds like you're using this approach but you don't want to have the "Save payment details for future purchases" checkbox present?

autumn kindle
#

Yep! That's exactly right

#

At the same time, I want to automatically save payment details

cinder veldt
#

The checkbox is required because explicit consent is required. There's no way that I'm aware of to remove it.

autumn kindle
#

Is there another payment flow you would recommend for my requirements? Or do you think CustomerSession -> SetupIntent -> PaymentIntent is the best I can get

cinder veldt
#

That's the flow I would recommend.

autumn kindle
#

If we have to have recurring payments, what's the best way to force them to check this box?

#

I can always try to hook in and validate on the client right

cinder veldt
#

You can't force them to check the box. You can, however, make sure they end up with a saved Payment Method set up for future use afterward and, if they don't have one, you can indicate it's required and send them through the flow again.

#

And you can add UI elements to indicate it's required, yep.

umbral matrixBOT
autumn kindle
#

You can, however, make sure they end up with a saved Payment Method set up for future use afterward and, if they don't have one, you can indicate it's required and send them through the flow again.
Reading this a couple times it sounds like just a different type of validation. E.g. we can validate the resulting payment method or we can validate the form directly

#

Thank you by the way for helping out here

#

Is this the standard approach for a subscription service in Stripe?

When a customer opts into a subscription service, they have to have a stored payment method. What it sounds like you're saying is that even on a subscription we need explicit consent from the customer on the checkbox. Simply agreeing to terms and clicking the "Order" button isn't enough

lethal girder
#

Hi there 👋 jumping in as my teammate needs to step away soon.

Sorry to take this back to the beginning of the conversation a bit. For Solution 1 from your original description, can you elaborate on what you mean when you say you cannot pay with the stored payment method?

autumn kindle
#

Hey Toby, no problem at all. Thanks for jumping in here.

For Solution 1, I couldn't find a way to display stored payment methods on this page and allow the customer to use them for payment (Like for Solution 2, which is what the screenshot is showing)

lethal girder
#

Gotcha, do you have an example of a Payment Method where you saw that behavior? My suspicion is it's not being shown there due to a misalignment in allow_redisplay values in the Payment Element and the Payment Method.
https://docs.stripe.com/api/payment_methods/object#payment_method_object-allow_redisplay

autumn kindle
#

One moment while I dig this up

#

Okay here's everything I'm working with:

Server creates this:
setup_intent = Stripe::SetupIntent.create({ customer: current_account.stripe_id, automatic_payment_methods: { enabled: true, allow_redirects: "never" }, usage: "off_session", })

Here's my Elements provider:
<Elements stripe={stripePromise} options={{ clientSecret, }} > {children} </Elements>

And this SetupIntent results in no stored payment methods appearing on the UI

#

I'm not working with any PaymentMethod objects until the SetupIntent is confirmed on the client, but at that point it's too late right?

lethal girder
#

I don't believe so. Can you try something for me? Can you try setting payment_method_data.allow_redisplay to always when creating the Setup Intent?
https://docs.stripe.com/api/setup_intents/create#create_setup_intent-payment_method_data-allow_redisplay

This is a newer flow so I don't know it off the cuff here, and without seeing a specific Payment Method that was created by your flow I'm doing a bit of guessing. But I suspect everything is being left with default values, so allow_redisplay on the Payment Method is being left as unspecified and the Elements integration later is only showing PMs where allow_redisplay is set to always.

autumn kindle
#

Alright so adding that:
Stripe::SetupIntent.create({ customer: current_account.stripe_id, automatic_payment_methods: { enabled: true, allow_redirects: "never" }, payment_method_data: { allow_redisplay: "always", }, usage: "off_session", })

Resulted in this error:
Missing required param: payment_method_data[card].

So then I did this:
Stripe::SetupIntent.create({ customer: current_account.stripe_id, automatic_payment_methods: { enabled: true, allow_redirects: "never" }, payment_method_data: { allow_redisplay: "always", type: "card", }, usage: "off_session", })

And got this error:
Missing required param: payment_method_data[card].
What's odd to me though is that looks like payment_method_data also takes in super specific payment methods, seemingly omitting an option for card.

If it helps, I did provide a screenshot of the stored payment methods on this account, which do appear when I use a CustomerSession and Solution 2

lethal girder
#

Yup, that first error is an indication I was sending you down the wrong path. Let me check the other end of this where I think you can change some behavior.

autumn kindle
#

Sure, thanks a bunch for the help here

lethal girder
#

Alright, so instead of adjusting the Setup Intent creation, can you try adjusting the Customer Session creation thats used to generate the session used with the Payment Element. The value I think you want to adjust here is the components.payment_element.features.payment_method_allow_redisplay_filters, and will want to update it to have a list with all available values, what we show at the end of the description for the field here:
https://docs.stripe.com/api/customer_sessions/create#create_customer_session-components-payment_element-features-payment_method_allow_redisplay_filters

In order to display all saved payment methods, specify [“always”, “limited”, “unspecified”].

autumn kindle
#

So the result of that can be seen in the screenshot (which is basically the same outcome as Solution 2 where the customer has to explicitly check a box to store their payment method). but let me provide the code to be sure I didn't boof anything:

Server session creation
customer_session = Stripe::CustomerSession.create({ customer: current_account.stripe_id, components: { payment_element: { enabled: true, features: { payment_method_redisplay: "enabled", payment_method_save: "enabled", payment_method_save_usage: "off_session", payment_method_allow_redisplay_filters: ["always", "limited", "unspecified"], }, }, }, })

Elements provider
<Elements stripe={stripePromise} options={{ mode: 'setup', currency: 'usd', customerSessionClientSecret, }} > {children} </Elements>

lethal girder
#

If you want to remove the option for customers to choose whether to save their payment method for future usage, so you can instead hard code that into the intents you create, then you'd also want to change the value for components.payment_element.features.payment_method_save when creating the Customer Session. You'll want to set that to disabled to remove the checkbox.
https://docs.stripe.com/api/customer_sessions/create#create_customer_session-components-payment_element-features-payment_method_save

autumn kindle
#

Hardcode where?

#

As far as I'm aware, the intent is created by the ElementsProvider / PaymentElement

lethal girder
#

By nature of using a Setup Intent, they're explicitly for saving payment methods for reuse later.

autumn kindle
#

I didn't see an option for that in the configuration

lethal girder
#

That's not correct, intents are created by your server

autumn kindle
#

Ohhh hold on a sec

lethal girder
#

Let's take a step back, and make sure I'm understanding your flow correctly.

You want to have two steps here right?

  1. Collect payment method details from your customer for reuse
  2. Process a payment for your customer allowing them to use payment methods they've already saved.
autumn kindle
#

Correct

lethal girder
#

In step 2, do you also want to let customers provide new payment method details, or only allow them to use already saved payment methods?

autumn kindle
#

I would like to give them the option to enter new payment information

#

And the option to use the already saved payment method

lethal girder
#

Sorry, needed a moment to think about how to do that cleanly. I think what you'll want to do for Step 2 then, is when you create the Customer Session, leave that payment_method_save parameter set to disabled. Additionally, when you create your Payment Intent for that (but please let me know if you're using the flow where you create intents after displaying the Payment Element, as this part will be a bit different then) you'll want to set setup_future_usage based on how you plan to let the customers use the payment methods in the future. If the Customer will always be on your site when you're processing payments for them, you can set it to on_session, otherwise set it to off_session:
https://docs.stripe.com/api/payment_intents/create#create_payment_intent-setup_future_usage

autumn kindle
#

Got it, lemme try that out now. I'm pretty sure I had done something similar before and ran into issues

#

Before I do that, I just want to tripple check that my current flow is clear to you:

  1. Server creates CustomerSession
  2. Server sends client secret to the frontend
  3. Frontend runs stripe.createConfirmationToken and sends it to sever
  4. Server uses the confirmation token to create and confirm a SetupIntent
  5. The SetupIntent returns a payment method id, which we use to create and confirm a PaymentIntent / charge the customer
lethal girder
autumn kindle
#

Oh no my bad if that was miscommunicated, yeah my flow has been creating and confriming Payment Intents server side. Basically Solution 2 that I had originally

#

As it stands the SetupIntent and PaymentIntent are created back to back on the server

lethal girder
#

Ooohh, okay, then scrap what I said about Payment Intents 😅
I was thinking you were using those to render the Payment Element and was making suggestions to let them save payment methods.

autumn kindle
#

My bad haha

lethal girder
#

Haha no worries! It's all part of the process

autumn kindle
#

But my 1, 2, 3 steps is more accurate

lethal girder
#

So, the part I'm not clear on then though, is why you want to let your customers see their already saved payment methods in the Payment Element if the Payment Element is only being used with Setup Intents. The saved payment methods would have already been set up, so I'm not grasping the benefit of letting the customer select them again.

cinder veldt
#

Hello again! I'm back and taking over. One thing we don't recommend people do is use a Setup Intent and then turn right around and use a Payment Intent immediately. Is that what you're doing, or is there a delay between the Setup Intent and the Payment Intent?

autumn kindle
#

Hello again!

#

There is no delay correct

#

Luckily this is not turned on in prod lol

cinder veldt
#

Yeah, so we recommend against using both a Setup Intent and a Payment Intent at the same time. Setup Intents are only designed to be used when you're not taking a payment.

autumn kindle
#

The reasoning for doing it back to back is because we wanted to confirm payment on the server

cinder veldt
#

If you are taking a payment, and also wnt to set up the payment method for future use, you should use a Payment Intent with setup_future_usage set.

#

You can still confirm on the server using this approach.

autumn kindle
#

This is what I followed for Solution 1

#

The drawback was that I couldn't figure out how to show the user's existing saved payment methods

cinder veldt
autumn kindle
#

I have to run but I will try this and get reach out again if I have more issues, thank you for the help