#rubensnobre-card-decline
1 messages · Page 1 of 1 (latest)
Hi 👋
Do you have the IDs for the payments that failed so I can check?
Sure
one second
you mean the in ?
in_1OkZ3qChHlHBFg3wfSGuK8b7
the other one:
in_1OjiUiChHlHBFg3wNzkA2sMf
@summer comet
Thanks, taking a look
All direct subscriptions without trial period is ok. Charging as expected.
And I test it a lot when I'm in Developer Mdoe.
Unfortunately this is a decline from the issuing bank
Booth?
and the bank did not provide any additional details
Those are the errors I am seeing
Do you think the decline is because my Company is in Brazil?
But one of those is a Brazilian Customer, paying in BRL.
I cannot speculate on why those cards were declined. Just that the customer should reach out to their bank to understand why.
So the best approach is to get in touch with my customer?
rubensnobre-card-decline
I'm not sure if its Stored.
How are your customers signing up for your subscriptions?
they put their cards into Card element from Stripe inside my desktop app
then I hear a webhook to finalize payment
when Free trial ends
Are you saving the payment method configured for off-session usage?
No
just one second.
Okay I see the problem
You are saving payment methods using the payment method API
Like this request: https://dashboard.stripe.com/logs/req_aw3GeJ1suvLROF
OMG
This does not optimize the payment method for off-session usage (e.g. subscription invoices)
I recommend you first change your integration to use Setup Intents to save the cards in a way that is configured for off-session usage. Here is our doc on it: https://docs.stripe.com/payments/save-and-reuse?platform=web&ui=elements
Once you have modified your integration, you will need to recollect payment methods from your customers
But I'm not using a WEBpayment.
I'm running inside my desktop app
To do not lose momentum of purchase
is it safe for me to share a part of my code, here?
so you can understand exaclty how I'm creating the Payment?
The request that I shared was created by a web app using Stripe js
So no, that doesn't match what you are telling me
payment_user_agent: "stripe.js/e9b38bb73a; stripe-js-v3/e9b38bb73a; card-element"
I need to run fully inside my APP using Javascript and React
Please tell me? why this works perfect in ALL my tests?
Well I recommend you change your integration to create Setup Intents and use those. You can still use JavaScript and React
Does it change in last month?
No
I think I'm already doing this
can you check part of my code?
const createCardToPay = async () => {
if (!stripe || !elements) {
console.log('STRIPE ERROR');
return;
}
const cardElement = elements.getElement(CardElement);
if (cardElement) {
const NEWCARD = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
email: user.profile.email,
name: name.toUpperCase(),
},
});
if (NEWCARD.error) {
WM_TOAST('error', JSON.stringify(NEWCARD.error.message));
console.log('ERROR MESSAGE', NEWCARD.error.message);
return false;
} else {
setCurPaymenthMethod(NEWCARD);
return NEWCARD;
}
}
};
This is the part I must change?
No, that is front-end code
You need to be creating Setup Intents on the server-side
I realize this may be a big switch and that it can be stressful
I'm just trying to make it clear why I think these payments are failing
Also this isn't something you could verify in Test mode since these kinds of declines would only occur when you attempt to charge real cards and the banks for those cards decline them.
You mean here:
const paymentMethods = await stripe.customers.listPaymentMethods(customer, { type: 'card' });
const filteredPaymentMethods = paymentMethods.data.filter(item => item.card.fingerprint === payment_method.card.fingerprint)
let paymentMethod;
if (filteredPaymentMethods.length === 0) {
paymentMethod = await stripe.paymentMethods.attach(payment_method.id, { customer: customer })
await createOrUpdateCustomer(customer, paymentMethod.id, username, name, affiliate);
} else {
await createOrUpdateCustomer(customer, filteredPaymentMethods[0].id, username, name, affiliate);
paymentMethod = filteredPaymentMethods[0];
}
Where is this code running? Are you using Stripe.js or Stripe's Node library?
mmm In my Next.js Vercel 'api'
import initStripe from "stripe";
import { supabase } from "../../utils/supabase";
const stripe = initStripe(process.env.STRIPE_SECRET_KEY);
I have this 2 fuctions too:
async function createOrUpdateCustomer(customer, paymentMethodId, username, name, affiliate) {
const updateData = {
name: username,
invoice_settings: { default_payment_method: paymentMethodId },
metadata: { fullname: name }
};
if (affiliate) {
updateData.metadata.tolt_referral = affiliate;
}
return await stripe.customers.update(customer, updateData);
}
async function createSubscription(customer, price_id, coupon, curTrialDays) {
return await stripe.subscriptions.create({
customer: ${customer},
items: [
{ price: price_id },
],
coupon: coupon,
trial_period_days: curTrialDays,
expand: ['latest_invoice.payment_intent'],
});
}
Okay here we go!
So here is where you want to create the Setup Intent
And then confirm it on your client-side app
Please save me....
I am providing you with the information I can
I know man.
It's up to you to write the code and make it work
But let's go back to this integration: https://docs.stripe.com/payments/save-and-reuse
So The problem is in Server side, correto?
Now that we have your client-side and server-side identified
So right here: https://docs.stripe.com/payments/save-and-reuse?platform=web&ui=elements&lang=node#create-intent is where we show you function to create the Setup Intent
In the next snippet we show you sending the client_secret to your front-end (React)
You mean use this instead of my current method?
const setupIntent = await stripe.setupIntents.create({
customer: '{{CUSTOMER_ID}}',
automatic_payment_methods: {
enabled: true,
},
});
I don't need to pass the Payment Method that I sent from Front end?
No. In this flow you would create the setup intent first and send it to the front-end
It goes like this
- Create customer <- server
- Create setup intent <- server
- Create Payment Method <- client
So the customer, type his card number and name etc.
I send this to my server.
create the setup intent
send the payment methdo to client>
Do you know a Stripe Expert that can help me as a freelancer?
This is an emergency
Unfortunately i do not.
However, if you were able to code this from the start, I do think you could make this work yourself.
The front-end side is also available using React: https://docs.stripe.com/payments/save-and-reuse?platform=web&ui=elements&lang=node&client=react#create-intent
So, sorry to bother you, But i need to understand it perfectly.
I'm from Brasil, so english is not my first langueg.
language.
But the document localizes to Portuguese, right?
I know it can be hard, especially when you are stressed, but I think you need to carefully read through the doc I shared and try to understand each part
currently I'm creating a payment method like this, ok?
const NEWCARD = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
email: user.profile.email,
name: name.toUpperCase(),
},
});
I'll still use this?
No
First you would create the customer
const customer = await stripe.customers.create();
Then create the Setup Intent
const setupIntent = await stripe.setupIntents.create({
customer: '{{CUSTOMER_ID}}',
automatic_payment_methods: {
enabled: true,
},
});
In Front end?
Back end
But from where I get USer Card ???
We're getting there. Just wait a sec
Then you send the Setup Intent client_secret to your front-end
app.get('/secret', async (req, res) => {
const intent = await stripe.setupIntents.create({
customer: '{{CUSTOMER_ID}}',
automatic_payment_methods: {
enabled: true,
},
});
res.json({client_secret: intent.client_secret});
});
On the front-end, you use the client secret when you create the form to collect the card information
import React from 'react';
import ReactDOM from 'react-dom';
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
import SetupForm from './SetupForm';
// Make sure to call `loadStripe` outside of a component’s render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('PUBLISHABLE_KEY');
function App() {
const options = {
// passing the SetupIntent's client secret
clientSecret: '{{CLIENT_SECRET}}',
// Fully customizable with appearance API.
appearance: {/*...*/},
};
return (
<Elements stripe={stripePromise} options={options}>
<SetupForm />
</Elements>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
But I'm getting user Card data from a Stripe Element.
I don;t need to pass it?
Sorry if I sound a stupid.
this is my card element
import { CardElement } from '@stripe/react-stripe-js';
import React from 'react';
const CARD_ELEMENT_OPTIONS: any = {
style: {
base: {
color: '#fff',
fontFamily: '"Montserrat", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '12px',
iconColor: '#fff',
'::placeholder': {
color: 'var(--white)',
},
},
invalid: {
color: '#f84a4b',
iconColor: '#f84a4b',
},
},
hidePostalCode: true,
iconStyle: 'solid',
};
const CardInput: React.FC = () => {
return (
<div
style={{
width: 'calc(100% - 18px)',
backgroundColor: 'var(--darker)',
padding: '9px 0px 9px 12px ',
margin: '9px',
borderRadius: '9px',
border: '1px solid var(--menuborder)',
}}
>
<CardElement options={CARD_ELEMENT_OPTIONS} />
</div>
);
};
export default CardInput;
this
import { CardElement } from '@stripe/react-stripe-js';
Instead what you do is call await stripe.confirmCardSetup() on your front-end
That uses both the cardElement and the client_secret and creates the Payment Method
Ok. You're.
I'll take a deep breath...
and read ALL docs.
than I return with a new approach if i Need help ok?
may I count on you?
So your customer fills out their info and you followed the steps I outlined (create Customer, & Setup Intent first)
Once they fill out the form and click a Submit button, you call this function
stripe
.confirmCardSetup('{SETUP_INTENT_CLIENT_SECRET}', {
payment_method: {
card: cardElement,
billing_details: {
name: 'Jenny Rosen',
},
},
})
.then(function(result) {
// Handle result.error or result.setupIntent
});
All this will happen on server side, correct?
Nothing happens locally as I'm doing now?
Sorry no, the part where they fill out the card information AND where you submit it does happen locally
But instead of using the createPaymentMethod, you use confirmCardSetup
sure
can you please...
Just send me the DOCS links again.
in order I must read and inplement?
So I can have it all in one place...
Cus I made a mess asking you so much things at same time?
But I agree. Take some deep breaths. Maybe code a few pieces at a time carefully to make sure you understand. It will all work in Test mode
Then after that how I'll be able to test?
Okay
- Overall doc: https://docs.stripe.com/payments/save-and-reuse?platform=web&ui=elements&lang=node&client=react#set-up-stripe
- Specific method for Card Element: https://docs.stripe.com/js/setup_intents/payment_method
You will check the Setup Intents you create and make sure they have a status of succeeded and a a Payment Method ID
https://docs.stripe.com/api/setup_intents/object#setup_intent_object-status
Just another important point.
The stripe customer is already created after user confirm his email...
Each one of my users have a stripe_id.
So I'll have to match this same customer_id right?
Perfect. Then you don't need to create them, just use their ID when creating the Setup Intent
So I'll have to match this same customer_id right?
Yes, you got it!
Okay I think next steps are to take some deep breaths. Read the documents, and test out some things.
You don't have to , it's just how the information is presented.
Still make no sense to me... OMG
Just start at the top and build some stuff in Test mode. It'll get easier as you go
ok.
Let me drink some water...
I'm freaking out
I work 2 years in this project
500 Users in first week.
And lot of them will going to fail.
Sent 150k newsletter to old users today
I NEED to fix this. Live or Dead.
I mean, Dead or Alive kkk
Okay well I think you can get it done.