#rubensnobre-card-decline

1 messages · Page 1 of 1 (latest)

proper oasisBOT
summer comet
#

Hi 👋

Do you have the IDs for the payments that failed so I can check?

knotty sky
#

Sure

#

one second

#

you mean the in ?

in_1OkZ3qChHlHBFg3wfSGuK8b7

#

the other one:

in_1OjiUiChHlHBFg3wNzkA2sMf

#

@summer comet

summer comet
#

Thanks, taking a look

knotty sky
#

All direct subscriptions without trial period is ok. Charging as expected.

#

And I test it a lot when I'm in Developer Mdoe.

summer comet
#

Unfortunately this is a decline from the issuing bank

knotty sky
#

Booth?

summer comet
#

and the bank did not provide any additional details

#

Those are the errors I am seeing

knotty sky
#

Do you think the decline is because my Company is in Brazil?
But one of those is a Brazilian Customer, paying in BRL.

summer comet
#

I cannot speculate on why those cards were declined. Just that the customer should reach out to their bank to understand why.

knotty sky
#

So the best approach is to get in touch with my customer?

proper oasisBOT
#

rubensnobre-card-decline

summer comet
#

Oh!

#

Wait I'm confused. How are you saving your customers cards?

knotty sky
#

I'm not sure if its Stored.

summer comet
#

How are your customers signing up for your subscriptions?

knotty sky
#

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

summer comet
#

Are you saving the payment method configured for off-session usage?

knotty sky
#

Let me check this

#

the PM is missing for you?

summer comet
#

No

knotty sky
#

just one second.

summer comet
#

Okay I see the problem

#

You are saving payment methods using the payment method API

knotty sky
#

OMG

summer comet
#

This does not optimize the payment method for off-session usage (e.g. subscription invoices)

knotty sky
#

What must I do?

#

But it worked on tests !!!

summer comet
#

Once you have modified your integration, you will need to recollect payment methods from your customers

knotty sky
#

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?

summer comet
#

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"

knotty sky
#

I need to run fully inside my APP using Javascript and React

#

Please tell me? why this works perfect in ALL my tests?

summer comet
#

Well I recommend you change your integration to create Setup Intents and use those. You can still use JavaScript and React

knotty sky
#

Does it change in last month?

summer comet
#

No

knotty sky
#

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?

summer comet
#

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.

knotty sky
#

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];
}
summer comet
#

Where is this code running? Are you using Stripe.js or Stripe's Node library?

knotty sky
#

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'],
});
}

summer comet
#

Okay here we go!

#

So here is where you want to create the Setup Intent

#

And then confirm it on your client-side app

knotty sky
#

Please save me....

summer comet
#

I am providing you with the information I can

knotty sky
#

I know man.

summer comet
#

It's up to you to write the code and make it work

knotty sky
#

Thanks.

#

I Know

summer comet
knotty sky
#

So The problem is in Server side, correto?

summer comet
#

Now that we have your client-side and server-side identified

#

In the next snippet we show you sending the client_secret to your front-end (React)

knotty sky
#

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?

summer comet
#

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
knotty sky
#

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

summer comet
#

Unfortunately i do not.

#

However, if you were able to code this from the start, I do think you could make this work yourself.

knotty sky
#

So, sorry to bother you, But i need to understand it perfectly.
I'm from Brasil, so english is not my first langueg.

#

language.

summer comet
#

But the document localizes to Portuguese, right?

knotty sky
#

No... not all...

#

😦

summer comet
#

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

knotty sky
#

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?

summer comet
#

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,
  },
});
knotty sky
#

In Front end?

summer comet
#

Back end

knotty sky
#

But from where I get USer Card ???

summer comet
#

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'));
knotty sky
#

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';

summer comet
#

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

knotty sky
#

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?

summer comet
#

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
  });
knotty sky
#

All this will happen on server side, correct?

#

Nothing happens locally as I'm doing now?

summer comet
#

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

knotty sky
#

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?

summer comet
#

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

knotty sky
#

Then after that how I'll be able to test?

summer comet
knotty sky
#

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?

summer comet
#

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.

knotty sky
#

sure.
I'll have to use:

<SetupForm />

#

can't keep using <cardelement/>

summer comet
#

You don't have to , it's just how the information is presented.

knotty sky
#

Still make no sense to me... OMG

summer comet
#

Just start at the top and build some stuff in Test mode. It'll get easier as you go

knotty sky
#

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

summer comet
#

Okay well I think you can get it done.