#rfcgreg
1 messages · Page 1 of 1 (latest)
hi, I think this is an issue I've seen before. Are you using one of the 'deferred' integrations where you confirm on the backend?
if so you actually need to pass mandate_data, but it's somewhat buried in the docs
we dont actually take payment at this stage, its "off session"
ah, but overall it's the same idea, when you confirm the SetupIntent to save the card, you need to pass a mandate , here https://stripe.com/docs/api/setup_intents/confirm#confirm_setup_intent-mandate_data
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
if you share the exact request ID req_xx from an error or a a PaymentIntent ID I can have a look, but I think it's this(it's come up a few times recently and the docs are not great here)
hmm I think that example is not a great one since I'm not sure you used a SetupIntent in that case, looks more like you manually created a PaymentMethod and passed it directly when calling the Customer Create API
ah no, you did use one, you just integrate in an unusual way where you run the SetupIntent without a customer and then attach the PM to a customer later
Yeah, so this "payment form" is only to collect payment details, it creates a setupintent first via php, then uses the js to create a payment method and confirm the intent, we then save all that to a new customer as the final step, otherwise if someone abandones we end up with a blank customer
makes sense
sometimes this may also be sent via email or whatever to ask someone to provide their card if they have an invoice or what not
Anyway so we need to pass mandate data into the setupintent when it's confirmed in order for that to be saved to the link payment method?
so yeah the fix is what I said really , you need to pass mandate_data when creating the SetupIntent https://stripe.com/docs/payments/finalize-payments-on-the-server?platform=web&type=setup#create-intent:~:text=When confirming an,and currency
ah but no, it can't be that, because you confirm on the frontend actually
so why isn't stripe.js collecting/passing the mandate for you... I don't know
yep, that was the confusion because the mandate data is the 3DS etc? your bank asking you to confirm. this is normally done when we click the submit button as the js checks the card etc
I am wondering if clicking the box to use link is somehow not triggering the 3ds stuff?
3D Secure isn't really related here I don't think
oh my bad. I might need to re-read
did you already have a support ticket open at https://support.stripe.com/?contact=true for help with this, as you referenced getting help before?
eh, not me personally. Possibly the stripe account holder (boss)
I'm the developer account attached to it
Should I perhaps be requesting access to this new feature?
Try out our latest update
We’re making a slight improvement to the integration below to automatically handle mandate data and future proof your integration. To request early access, please click here.
hmm, maybe!
sorry, there's a lot of things happening with Link and some rough edges, I'm not up to speed with all of them which is why I'd feel better answering in a support ticket where we have more time to dig in
Fair enough, makes sense. We've unfortuantely not had much luck with link. I've been asked to disable it for now due to the issues we're having
oh hmm
This was a quick attempt to try see if I could get it fixed before I look at that
I think maybe your integration is ok but the problem is the mandate is revoked, see https://dashboard.stripe.com/events/evt_1NuY2XBZh6y8njAy2P4plHjy for example which relates to the same pm_xxx from the error you had earlier
what I've seen before is that if you disable Link on your account, effectively that 'cancels' the mandates for existing customers, because you don't want to be able to charge them using Link anymore
It can also happen if the end-customer is disabling Link in their settings
so if you disabled Link on your account around the time of that event, that could be why
It should still be enabled at the moment
the req I sent you was the boss man testing his card last night
yeah sorry I misread the event
ok sorry, it's super busy on Discord at the moment and myself and half the team are in a meeting so we don't have a lot of bandwidth to dig in. I'd suggest writing into https://support.stripe.com/?contact=true with exact code, request IDs, clean reproductions, and we can dig into
yeah sure that's not a problem. I use a user defined settings file so I think I'm just going to add in a condition and a switch to disable or enable link for the tiem being. That way I can keep my code intact for the ticket
I do think there is some confusion here in your testing , because for pm_1NuY2CBZh6y8njAy2jYQ6jHv, the PM from req_aCDrUEIO44y0oN , I really don't see any SetupIntent ever used with it , looks like it was just attached to the Customer directly after creating the PaymentMethod (which we never recommend as it doen't handle 3DS or mandates)
I wonder if it's related to the use of link. without using it, I'm pretty sure they're used
do you have access to our test data? I have a live test form using the same code
you'd be welcome to take a look
as an example this is what we would normally see for a successful non link submission.
I can go ahead and launch a ticket though
Hi there 👋
hello
Was reading through the thread, and I do think passing mandate_data will help avoid that error. Sorry, was trying to find a doc that I swore had a snippet showing that in it, but I'm having trouble finding it.
No worries
Oh, wait, maybe I'm looking at the wrong Payment Intent, this one seems to have been created from the dashboard.
yeah so we don't have a typical setup
this particular integration only ever takes the payment details and saves them to a new customer for later uses (off session) all payments for these would generally be initiated via the dashboard
the company does use other things like pabbly to take direct payments on site. But this particular integration is an inhouse solution we have
Gotcha, I'm going to try to find the Setup Intent for the Payment Method being discussed above.
Hm, no luck though, all I'm seeing is the request to create the Payment Method from the frontend, I'm not seeing any Setup Intent that was created to set up that Payment Method.
is it this one you need? https://dashboard.stripe.com/logs/req_LrV9SRlyYLcAQq
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Checking
That's a request to create a Customer.
Is there a guide that you're following to build this flow?
This was more updating an exsting integration I made a while back
it's been created and updated according to stripe docs at each time
last major work I would say was the migration from stripe card element to the payment element,
Gotcha. So the concern here seems to be that Setup Intents aren't being used. The Setup Intent is the object that is responsible for constructing the mandates for future use, which aligns with the error you're getting when trying to process a payment.
This is our guide for using Setup Intents to save collect payment method details, and save those as Payment Methods, with the Payment Element as the frontend component.
https://stripe.com/docs/payments/save-and-reuse?platform=web&ui=elements
It's a good starting place for flows like this.
Right now it seems like your flow uses Stripe Elements' createPaymentMethod function to create a Payment Method, and then attach that to a newly created Customer.
Instead, you'll want to:
- Create a Customer (if one doesn't already exist)
- Create a Setup Intent for that customer (unless you want to use a deferred intents flow, we can discuss that if so)
- Process the Setup Intent using Stripe.js
The setup intent should be used and confirmed. Not sure why it wasn't showing though
I'm going to try share a condensed version of the js as that may explain better
Also, I'm seeing these objects are from live mode, are you able to reproduce this behavior in test mode as well?
in test mode everything worked, even using confirmCardSetup
sorry that's still kinda long
thats the js anyway.
the intent is also created on page load :
<?php
// Create a Stripe SetupIntent instance
$intent = $stripe->setupIntents->create(
[
'usage' => 'off_session',
'automatic_payment_methods' => [
'enabled' => true,
'allow_redirects' => 'never',
],
]
);
// Set the client secret key into a variable
$clientSecretID = $intent->client_secret;
That's a little concerning since I'm pretty sure confirmCardSetup doesn't work with the Payment Element.
it had been working but not with link. It now uses confirmSetup as shown above
link aside this integration does actually work as expected / intended
It looks like you create a Payment Method from the Elements instance, and then don't use that in the Setup Intent. Taking a closer look, I wonder if your flow is creating multiple Payment Methods.
Here's some info from a successful submission not using link:
app-api-version
2023-08-16
account-api-version
2023-08-16
stripe-php-ver
12.4.0
payment_method
pm_1NuboyBZh6y8njAy2xQ7RZ7I
setup_intent
seti_1NubnkBZh6y8njAyChEETlUb
card_name
test
emailaddress
test@test.com
cardaddress
test,GB,test,test,te11st,
customerID
cus_Oi1s9v9ft5hl5a
thats in test mode right now if it helps
That's the data and ID's that's processed and printed at the end (thank you page of my test form)
Yup, you're creating multiple Payment Methods.
pm_1NuboyBZh6y8njAy2xQ7RZ7I is being created by your call to createPaymentMethod. Payment Methods created that way aren't set up for future usage.
Then you create and process seti_1NubnkBZh6y8njAyChEETlUb, which creates another PM, but that isn't tied to a Customer since the Setup Intent wasn't provided a Customer ID via the customer parameter.
There is a bit of redundancy with the current flow, do you have a use-case that requires you have access to a Payment Method object before you process a Setup Intent for it?
I see... hmmm maybe its been an oversight
I don't think there's a specific reason for that no.
Sorry trying to wrap my head around this
All good! There is quite a bit to digest.
Based on the conversation so far, it sounds like you're leveraging deferred intents and want to set up future payments. So this is the guide that I would recommend using as your reference:
https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&type=setup
yeah thanks. I'll need to look again at my flow I guess. I do indeed see the two PM ID's in the logs now.
would the double Payment method be down to the switch from confirmCardSetup to ConfirmSetup?
Not alone.
I suspect your flow before created a Payment Method then passed that to the confirmCardSetup call which can accept already created PMs. It looks like now createPaymentMethod is still in place which creates the first Payment Method. Then confirmSetup is called which creates the second, since the line to pass the existing PM ID is commented out because that function doesn't accept existing payment methods.
yeah ok I think thats exactly what it is
I did previously pass the payment method to card setup function
Gotcha. In that case, I would recommend making some adjustments to what you have currently. With the main changes being:
- Remove the call to
createPaymentMethod(the Setup Intent will create the PM for you) - Create the Customer before the Setup Intent, and pass the Customer ID to the
customerfield when creating the intent.
So I currently create my customer via PHP after the JS returns a success and what not, I guess you would suggest I create the customer in the js instead?
I'd still do it from server-side code, probably in the same flow that currently creates a Setup Intent and returns its client secret to the frontend.
oh ok, that's the reason I ended up doing the customer at the end. Currently the page loading is the trigger for the setup intent. if I created a customer at this stage any time the page is viewed a new blank customer would be created
https://stripe.awoltech.dev/payment if you're curious to the form itself
Stripe enabled Secure Payment Gateway - Created by Greg Marshall - https://website-hero.co.uk
Since you're using the deferred intents flow, you don't need an intent to render the Payment Element. So you can delay the customer creation as well as the intent creation parts of your process, those pieces can be triggered from the submit event listener.
oh ok that would work
I was under the impression that it was best to have the intent first but I guess that was for the older methods
a lot has changed with stripe over the last couple years, can be hard to keep track of current best practices
Agreed, quite a bit has changed. That approach was the best option when that was the only way the Payment Element could be implemented. We got a lot of feedback that the approach created a lot of unused items that cluttered accounts and dashboard views though, so the deferred flow was built which allows a lot of those objects to be created later in the process when a payment is more likely to occur.