#mhenrixon_code
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/1430846645959921694
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
So the first one goes through, VCR records all the interractions but replaying the interactions isn't working and I am guessing it is because of some timestamp or something.
def add_card_via_stripe(card_number)
# Scope within the native add card turbo frame
within "turbo-frame#native_add_a_card" do
# Find the Stripe Elements iframe for adding a card
Capybara.within_frame first("iframe[title*='Secure payment input frame']") do
# Wait for the form to be ready
assert_selector "input[name='number']", wait: 10
fill_in "number", with: card_number
fill_in "expiry", with: "12#{Date.current.year.next.to_s[2..]}"
fill_in "cvc", with: "123"
# Select country if present
if has_select?("country")
select "United Kingdom", from: "country"
fill_in "postalCode", with: "BT3 9DT"
end
end
# Click the Add Card button (still within the turbo-frame)
click_on "Add Card"
end
# Handle 3D Secure 2 authentication challenge if it appears
if has_selector?("iframe[src*='three-ds-2-challenge']", wait: 5)
Capybara.within_frame first("iframe[src*='three-ds-2-challenge']") do
# Wait for the inner challenge frame to load
assert_selector "iframe#challengeFrame", wait: 10
# Switch to the inner challenge frame where the actual buttons are
Capybara.within_frame find("iframe#challengeFrame") do
# The Complete button has id "test-source-authorize-3ds"
assert_selector "button#test-source-authorize-3ds", wait: 10
click_button "test-source-authorize-3ds"
end
end
end
# Wait for Stripe confirmation and backend processing to complete
# Wait for the spinner to disappear, indicating processing is done
assert_no_selector "turbo-frame#native_add_a_card [data-profile--add-card-modal-component--add-card-modal-component-target='spinner']:not(.d-none)", wait: 10
end
VCR.use_cassette(order_cassette("credit_card"), allow_playback_repeats: true) do
click_pay_now_in_drawer
Sidekiq::Testing.inline!
add_card_via_stripe(PaymentProviders::Stripe::TestCards::REQUIRES_AUTH, @user)
end
# Verify success message appears
assert_text "Payment was successful", wait: 30
assert_selector ".tw-bg-light-green", text: "Fulfilled"
It simply errors on click_on "Add Card" during the replay of the VCR cassette
Hello! Generally the frontend payment UIs do not support automated testing, so you're likely to run into issues similar to this one. Not familiar with VCR or what exactly the test it trying to do?
VCR hooks into all http communications (also from the frontend), saves the responses as a mock response and subsequent replays then use the same stubbed responses.
I am trying to add an off session payment method and using the newly added payment method for the first payment.
So ideally, during the replay, an off session payment method should be created and used.
By replay, I mean when not recording the VCR cassette (only recording once and then infinite replays with that data).
What's the error that's thrown?
Unless it's a Stripe specific error we're not really able to help unfortunately. As noted, we don't official support automated testing on Elements for various reasons so it shouldn't be relied upon
Ok, so the replay of the adding card isn't working. We can't test that at all then? Always manual testing for elements?
What about the off session payment then?
What's the ID of the object? Looks like a Setup Intent (seti_xxx)?
(that's not a payment btw)
I know it isn't a payment yet, I record the card for the off session payments first so that I can use it for the payment: #1430846645959921694 message
This was the originally recorded setup_intent:
{
"id": "seti_1SL4KKIDVHq6Oov9azSS9T9A",
"object": "setup_intent",
"application": null,
"automatic_payment_methods": null,
"cancellation_reason": null,
"client_secret": "seti_REDACTED_secret_REDACTED",
"created": 1761148312,
"customer": "cus_Qxf0F0U6p9qFjA",
"description": null,
"excluded_payment_method_types": null,
"flow_directions": null,
"last_setup_error": null,
"latest_attempt": null,
"livemode": false,
"mandate": null,
"metadata": {},
"next_action": null,
"on_behalf_of": null,
"payment_method": null,
"payment_method_configuration_details": null,
"payment_method_options": {
"card": {
"mandate_options": null,
"network": null,
"request_three_d_secure": "automatic"
}
},
"payment_method_types": [
"card"
],
"single_use_mandate": null,
"status": "requires_payment_method",
"usage": "off_session"
}
Well you said 'What about the off session payment then?' so I assumed you thought it was a payment ๐
There's a 400 on the confirmation of that intent because it's already in a succeeded state: https://dashboard.stripe.com/acct_16rR9PIDVHq6Oov9/test/logs/req_P4etX9Ccmsc43w
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
I suspect that's the error from the screenshot
So how would I make the off session payment happen then so that I can test it? I still need a card on file to be able to test it so I need to add a card to stripe first correct?
The example you shared is a Setup Intent. That API resource facilitates the save/setup of payment methods for future payments. Once that intent is confirmed, and transitions to succeeded state, it generates a pm_xxx object (via payment_method property) that you can then use in subsequent off-session payments. See: https://docs.stripe.com/payments/save-and-reuse?payment-ui=embedded-components#charge-saved-payment-method
succeeded is a terminal state. You can't re-use the intent at that point, which seems to be what you're trying to do. If you want to create a payment for the card you just saved, you'd use a Payment Intent (like in guide above)
Yes yes that's pretty clear but I still have to save:
- The user
- The card (payment method)
- Create the setup intent for my off session payment
- Consume the intent and make the payment
Something like this?
What does 'consume' mean? That's not a term in our API lexicon
Did you read the guide I linked? It expains this end-to-end, from saving the card to charging it off-session later
Well, the setup intent is just an intent right? Not the actual action, it needs to be used?
You confirm it. Once it's confirmed it can be discarded โ you can't use it again for a payment or whatever which seems to be what you're doing. I explained this before, as does the doc
So in my test, i have to:
- create or map an existing stripe customer
- create or retrieve an existing payment method
- use the payment method with the setup intent (off session)
- Make the payment with the intent
I don't understand step 3 โ the Setup Intent generates the payment method
Ah so setup intent is what I need to do for step 2 and then the payment intent as step 3 ?
Yes, exactly
I only worked with checkout sessions before which is a completely different and smoother way of doing it.
Thank you, so instead of doing the setup intent with the stripe lements (link) I just do it in the code and map the data to my customer and then clicking on pay now should work because it is all backend recorded.
No, the Setup Intent will require the Elements components so the customer can provide card details. The Payment Intent part does not as the pm_xxx object ID is a representation of that saved card that you can charge off-session
Honestly, this guide is what you need end-to-end: https://docs.stripe.com/payments/save-and-reuse?payment-ui=elements
Yeah the guide is great! Fitting the guide and translating between the existing code (completely untested), the differences between the native app (that I am working on) and the existing web app payments that uses checkout session is, however, not as straight forward. ๐
But in this guide you link to, the only way to save the payment method for off session payments is via a SetupIntent @candid tiger .
When I come to the PaymentIntent a payment_method: val is required to make the payment and this is why I am here in the first place.
So if the customer is registered in stripe for off session payments (like when I recorded the VCR cassette in the first place).
I could find the customer, his/her payment methods and attach that to the test run that I am currently using (I guess).
Is your intention to save during a payment? Only reason I reference Setup Intents is because you shared one with me
I am trying to write tests for existing code so that I can improve and normalize the flow. This payment is using the credit card on file (off session) or if the user don't have one, takes them through adding a card and then uses it for the order they wanted to pay.
I want to automate our tests for att least the payment because I have now created thousands of orders manually and tested manually and I've had enough
OK, then if there is always a payment, even when it's a new customer without a card, then you can ignore a Setup Intent and instead you can save it during the first payment via the Payment Intent: https://docs.stripe.com/payments/save-during-payment?payment-ui=elements
It might be that there is no payment
Then you'd use a Setup Intent to save the card. Clearly your integration/tests are confused right now as per the original error you shared where you were trying to re-confirm an intent that had already succeeded. I recommend that you step through those guides and understand how the flows work, the purpose and differences between the intents, then we can answer any specifics
Question!
Can I even get this done with a SetupIntent as you said the setup intent requires stripe elements and shouldn't be tested?
I understand the flow perfectly well for the live scenario and I have tested a few thousand times manually that everything is working as it should.
Manual testing is frail and time consuming
Well your automated testing may work today, but there's no guarantee it won't break (e.g. we might change the DOM elements or something)