#rubens_card-3ds
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. Thank you for your patience!
⏱️ We automatically close idle threads, which makes them read-only. Make sure you stick around to chat in realtime! If this thread is closed and you have another question you'll need to start a new thread.
🔗 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/1213228141406068776
📝 Have more to share? You can add more detail below, including code, screenshots, videos, etc.
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.
- rubens-nobre_code, 1 day ago, 69 messages
Sorry not sure I understand the question
Already looks like you're checking the funding type in your code snippet
yes, I am.
but today i got this weird error, saying card funding is not 'credit'.
Then when I check this subscription on dashboard. it says it is.
can you check if this
"pm_1OpcdEChHlHBFg3wG3Bw6RZZ"
is related to this subscription?
sub_1OpcdKChHlHBFg3wstdIzTxq
cus is from same customer.
But I'm not sure if from a previous failed payment, or this active one.
did it make sense for you now @heady stump ?
pm_1OpcdEChHlHBFg3wG3Bw6RZZ
this?
i have a errorLog function:
if(paymentMethod.card?.funding !== 'credit'){
error_log(
JSON.stringify(paymentMethod),
'_createCardToPay - NOT CREDIT',
JSON.stringify({
user_email: user.profile.profile_email,
host: hostData.hostCode,
seat: hostData.hostCode == 'AEFT' ? user.profile.ae_seat : user.profile.ppro_seat
})
);
}
and this function was triggered. By this PM
cus I got this Log into my database in backend
Makes no sense for me too.
You should add the funding type to the log
That way in the future you see what it says
But that pm_ has a credit funding type
Yes, but instead of the whole paymentMethod object (as in other cases), is returning only the pm_code.
My code is JSON.stringify(paymentMethod)
my function that create a card to pay is have only this kind of return:
return result.setupIntent.payment_method as PaymentMethod | null;
Wait if you don't have the whole object how are you able to access the funding param?
How are you checking the funding param here: if(paymentMethod.card?.funding !== 'credit'){ if you don't have the whole object?
more details:
const setupIntentResponse = await createSetupIntent({ customerId });
const result = await stripe.confirmCardSetup(setupIntentResponse.client_secret, {
payment_method: {
card: cardElement,
billing_details: {
email: email,
name: name.toUpperCase(),
},
},
});
if (result.error) {
console.log('Erro na confirmação do SetupIntent:', result.error);
error_log(
JSON.stringify(result.error),
'_createCardToPay Erro na confirmação do SetupIntent',
JSON.stringify({
user_email: email,
customerId: customerId,
})
);
return null;
}
return result.setupIntent.payment_method as PaymentMethod | null;
That doesn't answer my question. That's just a different code block entirely
What I'm trying to say is...
If you try to use a debit card in my code...
it triggers the error and show the whole object.
But only at this time.
I got the pm_code instead.
It's weird for me too.
So you're saying it almost always works (ie accepts credit cards and rejects debit cards) but in this one case, the paymentMethod variable was a payment method id instead of an object?
I'll check my whole code line by line again.
YES, exactly!
I don't know why.
This is the first time the error_log trigger this condition.
Got it
Where do you set the paymentMethod variable in your code? Hard for me to debug this since I don't have access to your env
I Know... sorry to bother you.
I'll check it again line by line.
If this is a valid transaction... I'm calm now.
Just try to reach support as fast as I can, because. I lost a lot of subscriptions from debit cards from banks with different currency than my default.
That's why I was upset.
Can you please, only confirm that this subscription:
sub_1OpcdKChHlHBFg3wstdIzTxq
Is correctly setup for charging after trial period ends ??
and let me know how to check and confirm this from dashboard if possible. So I don't bother Support for this in future?
You need to see if a payment method was collected
So check if one is set as default on the Subscription or Customer. It will be default_payment_method on the subscription or invoice_settings.default_payment_method on the customer
Looks like one is set on the customer, so you're fine
However, it was created odd: https://dashboard.stripe.com/logs/req_xc0MVRqg7g9ZDy
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
You should collect payment method via the subscription's setup intent if possible
Or just any setupintent
like here?
Directly creating a payment method increases chances of declines/3ds authentication later
I'm refering to the api
I'm creating a setupIntent from my server side.
I'm referring to the payment method set as default on that sub specifically
See the request I linked above
It was not created via setupintent
mmmm
here's my current code:
`const handlerSetupIntent = async (req, res) => {
await NextCors(req, res, {
methods: ['POST'],
origin: '*',
optionsSuccessStatus: 200,
});
console.log("Requisição recebida para criar um SetupIntent.");
const { error, value } = schema.validate(req.body);
if (error) {
console.error("Erro de validação:", error.details[0].message);
res.json({ error: Validation error: ${error.details[0].message} });
return;
}
console.log("Dados validados:", value);
try {
// Crie o SetupIntent
const setupIntent = await stripe.setupIntents.create({
automatic_payment_methods: { enabled: true },
});
console.log("SetupIntent criado com sucesso:", setupIntent);
res.status(200).json(setupIntent);
} catch (error) {
console.error("Erro ao criar SetupIntent:", error.message);
res.status(400).json({ error: error.message });
}
};`
i call this back end and then i confirmCardSetup()
`
const setupIntentResponse = await createSetupIntent({ customerId });
// console.log('setupIntentResponse.client_secret', setupIntentResponse.client_secret);
//@ts-ignore
const result = await stripe.confirmCardSetup(setupIntentResponse.client_secret, {
payment_method: {
card: cardElement,
billing_details: {
email: email,
name: name.toUpperCase(),
},
},
});`
Again, see the request i linked
The payment method in question was not created via a setupintent
It was created in the frontend with the card element
ok.
So the problem is that the current pm created with cardelement is not defining as the 'default' payment method ?
"preferred": null ?
No
As I stated previously, it is set as default on the customer under invoice_settings.default_payment_method
The issue is because it wasn't created via a setupintent, payment has a higher liklihood of failing or requiring 3ds authentication in the future
ok.
So whats Wrong? Sorry If I'm dumb.
let me try to explain if I understand.
currently 'I think' I'm creating the pm_here
const { paymentMethod, error: paymentMethodError } = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
name: name,
email: email,
},
});
then I'm confirming from here.
const setupIntentResponse = await createSetupIntent({ customerId });
// console.log('setupIntentResponse.client_secret', setupIntentResponse.client_secret);
//@ts-ignore
const result = await stripe.confirmCardSetup(setupIntentResponse.client_secret, {
payment_method: {
card: cardElement,
billing_details: {
email: email,
name: name.toUpperCase(),
},
},
});
in the moment of PAY
I'm using the PM that came from.
return result.setupIntent.payment_method as PaymentMethod | null;
I know it looks confuse,
for me too...
Can you give us the exact SetupIntent id seti_123 where you collected card card with
rubens_card-3ds
looking
Okay so here's what I think you are doing
- Collect card details client-side
- Create a PaymentMethod
pm_123client-side - Server-side explicitly call the Attach PaymentMethod API to attach that pm_123 to a Customer cus_123
- Server-side create a Subscription
Can you confirm that's what you do?
yep!
O M G
follow that doc instead the flow will be this
- (client-side): Collect card details in PaymentElement
- (client-side) Create a PaymentMethod
pm_123 - (server-side) Create a Customer
- (server-side) Create a Subscription with
payment_behavior: 'default_incomplete'and properly expandpending_setup_intentandlatest_invoice.payment_intent - (server-side) Based on whether your Subscription needs a payment upfront or not, confirm the SetupIntent/PaymentIntent that was created with the
pm_123from step #1 - (client-side) if any "next action" is needed such as doing 3DS, finish this client-side
My customers is already created at this point.
I think the only difference is that I'm
const result = await stripe.confirmCardSetup(setupIntentResponse.client_secret, {
payment_method: {
card: cardElement,
billing_details: {
email: email,
name: name.toUpperCase(),
},
},
});
on client-side.
Should I do this right after createSetupIntent on server-side?
currently.
I'm only doing this from setupIntent in server side:
try {
const setupIntent = await stripe.setupIntents.create({
automatic_payment_methods: { enabled: true },
});
res.status(200).json(setupIntent);
} catch (error) {
console.error("Erro ao criar SetupIntent:", error.message);
res.status(400).json({ error: error.message });
}
Shoud I do the confirmCardSetup right after setupIntent is available?
in this same endpoint?
yeah sorry you're going too fst and mixing everything up
- do not call the Attach PaymentMethod API
- understand that you are not creating the SetupIntent yourself, it comes from your Subscription right?
no, i'm confuse
I'm doing this from my server side.
only in the moment the subscription is created
paymentMethod = await stripe.paymentMethods.attach(payment_method.id, { customer: customer })
sorry my dumbness
Do not call that method, that's wht I said. Take 10 minutes, carefully read the doc I shared earlier and start fresh and implement what I described
it's not. You start a new question and provide enough details to help you further
Really right now the thread is open. The first step is for you to pause, read the doc, and implement what's in the doc. That should take 10/15 minutes!
I'm doing this right now... but is the end of my day. you know...
maybe it's better to start this with a fresh mind.
My app is already in production....
And I can;t break anything.
Cus it's working right now.
Only failing with debit subscriptions after trial period ends.
The rest is working
Gotcha! So yeah totally fine to come back next week and ask follow up questions if needed!
new conversation, new person. Which is totally fine. We're all developers, you come back with a fresh mind and a clear new question. We don't start from this thread as you were quite thoroughly lost and have to first do the work to read the doc I shared and understand it end to end