#rahul_api

1 messages ยท Page 1 of 1 (latest)

flat valeBOT
#

๐Ÿ‘‹ 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/1267531190848454758

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

cinder hawk
#

For context,

   <Elements
                            stripe={stripePromise}
                            options={{
                                clientSecret: paymentResponse!.paymentIntentClientSecret,
                                customerSessionClientSecret: paymentResponse!.customerSessionClientSecret,
oblique jetty
cinder hawk
#

I don't think we are

#

Essentially on web, we're offboarding the entire payment flow to stripe's sdk

oblique jetty
#

You can't pass raw card details to Stripe

cinder hawk
#

the bottom screen is stripe's sdk

#

not our ui

#

when customer enters details -> purchase tickets:
works as intended, charges card

#

when customer enters details -> checks the save box -> purchase tickets

#

the error above surfaces

#

if you look at the request req_FOpnnXwBDbyWOj, you see that the origin is https://js.stripe.com/

oblique jetty
#

What version of the SDK are you using though?

cinder hawk
#

4.1.0

oblique jetty
#

Can you copy/paste all the relevant code for that? Including any back-end calls?

cinder hawk
#

tagging in our web guy

unkempt dune
#

I'm with rahul

React Elements component (paymentResponse is returned from the backend,

                        <Elements
                            stripe={stripePromise}
                            options={{
                                clientSecret: paymentResponse!.paymentIntentClientSecret,
                                customerSessionClientSecret: paymentResponse!.customerSessionClientSecret,```

export interface InitiatePaymentResponse {
transactionId: string;
paymentIntentClientSecret: string;
setupIntentClientSecret: string;
customerSessionClientSecret: string;
}

// submitting the form
const { error: submitError } = await elements.submit();
if (submitError) {
console.error(submitError);
toast.error("Sorry, something went wrong! Please try again.");
setLoading(false);
return;
}

cinder hawk
#

On the backend side

// Payment intent
paymentIntent, pErr := stripe.SetupCheckout(stripe.SetupCheckoutRequest{
            PaymentSummary:   transaction.Checkout.Payment,
            Currency:         "usd",
            Customer:         *user.FirestoreUser.StripeCustomerId,
            EventName:        event.FirestoreEvent.Name,
            ConnectAccountID: *transaction.Payments.Destination,
            Details: stripe.CreatePaymentIntentRequestDetails{
                TransactionId: transaction.Id,
                EventId:       event.FirestoreEvent.Id,
                Version:       os.Getenv("VERSION"),
            },
            PaymentMethod: nil,
        })
        if pErr != nil {
            api.HandleAPIError(w, http.StatusInternalServerError, errorhandling.CreateErrorDefault(pErr))
            return
        }
        if paymentIntent.PaymentIntent != nil {
            err = transaction.UpdateTransactionWithAutomaticApprovalPaymentIntent(paymentIntent.PaymentIntent.ID)
            if err != nil {
                api.HandleAPIError(w, http.StatusInternalServerError, errorhandling.CreateErrorDefault(err))
                return
            }
        }
        response.EphemeralKey = paymentIntent.EphemeralKey.ID
        response.CustomerId = paymentIntent.CustomerID
        response.PaymentIntentClientSecret = paymentIntent.PaymentIntent.ClientSecret
// Setup intent
        si, siErr := stripe.CreateSetupIntent(stripe.CreateSetupIntentRequest{
            Currency: "usd",
            Customer: user.FirestoreUser.StripeCustomerId,
        })
        if siErr != nil {
            api.HandleAPIError(w, http.StatusBadRequest, errorhandling.CreateErrorDefault(siErr))
            return
        }
        response.SetupIntentClientSecret = si.Intent.ClientSecret
        response.CustomerSessionClientSecret = si.CustomerSession.ClientSecret
#
func SetupCheckout(request SetupCheckoutRequest) (r *SetupCheckoutResponse, error error) {

    response := SetupCheckoutResponse{}

    stripe.Key = os.Getenv("STRIPE_SECRET_KEY")

    request.EventName = stripAndMax(request.EventName)

    if request.PaymentSummary.AutomaticApprovalTotal > 0 {

        params := &stripe.PaymentIntentParams{
            Metadata:             lib.StructToMapStrStr(request.Details),
            Amount:               stripe.Int64(int64(request.PaymentSummary.AutomaticApprovalTotal)),
            ApplicationFeeAmount: stripe.Int64(int64(request.PaymentSummary.AutomaticApprovalUserFee)),
            CaptureMethod:        stripe.String(string(stripe.PaymentIntentCaptureMethodAutomatic)),
            Currency:             &request.Currency,
            Customer:             &request.Customer,
            Description:          stripe.String(request.Details.TransactionId),
            PaymentMethodTypes: stripe.StringSlice([]string{
                "card",
            }),
            StatementDescriptorSuffix: &request.EventName,
            TransferData: &stripe.PaymentIntentTransferDataParams{
                Destination: &request.ConnectAccountID,
            },
            TransferGroup: stripe.String(request.Details.EventId),
        }

        if request.PaymentMethod != nil {
            params.PaymentMethod = request.PaymentMethod
        }

        pi, err := paymentintent.New(params)
        if err != nil {
            return nil, err
        }
        response.PaymentIntent = pi

    }

    epparams := &stripe.EphemeralKeyParams{
        Customer:            &request.Customer,
        IssuingCard:         nil,
        VerificationSession: nil,
        StripeVersion:       stripe.String("2024-04-10"),
    }

    key, err := ephemeralkey.New(epparams)
    if err != nil {
        return nil, err
    }
    response.EphemeralKey = key
    response.CustomerID = request.Customer
    return &response, nil

}
#

sorry for the code spam ๐Ÿ’€

oblique jetty
#

All good. Taking a look now and will circle back

unkempt dune
#

by the way, it was all working previously, but after last week it stopped working, even after upgrading stripe js to 4.1.0

oblique jetty
#

When did you upgrade?

#

What version were you using before?

unkempt dune
#

upgraded today from "@stripe/stripe-js": "^1.54.2" --> "@stripe/stripe-js": "^4.1.0"
it stopped working last week on Thursday (before we upgraded)

oblique jetty
#

Ahhhh, wait. This is a Firestore web app?

#

I was confused for a second, becausethese fucntions didn't sound familiar --> SetupCheckoutRequest and UpdateTransactionWithAutomaticApprovalPaymentIntent

#

As far as I can tell, there aren't really any Stripe method calls in your code. It might be worth reaching out to Firestore support to see what's causing them to send the payment_method_data.card parameter

cinder hawk
#

oh those are our internal funcs on the backend

oblique jetty
#

Ahhhh, okay got it. Are you able to step through your code and discern where the parameters for the Setup Intent Confirm API call are being set?

I see the Setup Intent creation, but I don't see the confirmation in your code.

cinder hawk
#

the confirmation is being done on the frontend

unkempt dune
#
const elements = useElements();

///////

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    ///// validation
    const { error: submitError } = await elements.submit();
    if (submitError) {
        console.error(submitError);
        toast.error("Sorry, something went wrong! Please try again.");
        setLoading(false);
        return;
    }

    const { error: stripeConfirmError } = await stripe.confirmSetup({
        clientSecret: paymentResponse.setupIntentClientSecret,
        elements,
        confirmParams: {
            return_url: getPaymentReturnURL(event.id),
        },
    });

#

this is the frontend code for submitting

oblique jetty
#

Is there a URL I can visit to see this error reproduced?

unkempt dune
#

yeah give me a few minutes

flat valeBOT
unkempt dune
#

hey, sorry for the delay

https://dev.joinpoppin.com/stripeBugRepro

auth token: ```
eyJhbGciOiJSUzI1NiIsImtpZCI6IjBjYjQyNzQyYWU1OGY0ZGE0NjdiY2RhZWE0Yjk1YTI5ZmJhMGM1ZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZGV2LXBvcHBpbiIsImF1ZCI6ImRldi1wb3BwaW4iLCJhdXRoX3RpbWUiOjE3MjA1NjUyNDgsInVzZXJfaWQiOiJES0xUTExYSG9SYnNIbFhSOG80c0ZnNkljS3gxIiwic3ViIjoiREtMVExMWEhvUmJzSGxYUjhvNHNGZzZJY0t4MSIsImlhdCI6MTcyMjI3NjU5OSwiZXhwIjoxNzIyMjgwMTk5LCJwaG9uZV9udW1iZXIiOiIrMTU1NTU1NTU1NTUiLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7InBob25lIjpbIisxNTU1NTU1NTU1NSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBob25lIn19.LoM8IWQkeUNkrPVPMaqFmYRumd7aveAhNHz_514s7Q64cRkVZ0L8qk0smR-w060Uhi5tbICNVbdox5kWqSMrhg5beJMLpC-iytfzhgiiStiiTo5sshiBLN_UvIbn11n7PRt83V8QQoMYAfA7sGcgyOHogE0BtydtGDasxAAS1C_oghip1wR5COKBfd_G5aSkFUzqff9hoXkho01dSVh9EmJEPe54QktoqNFiq3hoTIXdckMFHokZAkysXidpXCAsldOuiEKM-ihlqC2LHkBvrJBntSpMD6vdoAw8R6oNGchfC1TFoR26TBJ6diexH1hicsE1tfrlH_jEQCFIgAFMYw

#

this is a repro of the purchase flow, you should be able to copy the auth token above and then click proceed, then enter the 4242... card and click purchase

#

and then in the console you should see the error from stripe

#

also make sure to check the "save payment info for Poppin" button to see the error

#

also if you're not doing this right now ping me and i can refresh the auth token

spice pendant
#

Hi, I'm stepping in and taking over. Let me catch up

cinder hawk
#

thanks - lmk if you need anything else from us

spice pendant
#

Are you able to create another auth token for me please? I tested and I see this 'ID token has expired at: 1722280199','

unkempt dune
#
eyJhbGciOiJSUzI1NiIsImtpZCI6IjBjYjQyNzQyYWU1OGY0ZGE0NjdiY2RhZWE0Yjk1YTI5ZmJhMGM1ZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZGV2LXBvcHBpbiIsImF1ZCI6ImRldi1wb3BwaW4iLCJhdXRoX3RpbWUiOjE3MjA1NjUyNDgsInVzZXJfaWQiOiJES0xUTExYSG9SYnNIbFhSOG80c0ZnNkljS3gxIiwic3ViIjoiREtMVExMWEhvUmJzSGxYUjhvNHNGZzZJY0t4MSIsImlhdCI6MTcyMjI4MDM3MCwiZXhwIjoxNzIyMjgzOTcwLCJwaG9uZV9udW1iZXIiOiIrMTU1NTU1NTU1NTUiLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7InBob25lIjpbIisxNTU1NTU1NTU1NSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBob25lIn19.swbw7aZMHqjcKJZqjeTcTkoL7LiSTokdoLgkMIGBRfBOyr5BDI6WtuYl22sy8v-af4xfYTYWZRdNO4IUZR79WPkD8LhP3o-OvS4cIgXZdV4ToD4CPyUswveco2HPKxYp6NRDKpoVdFCxROBjRuhc_z_JKaaRlArd24z8tglxEKSZPTrMJ0HPDUrK2SDrX9kuLYSJIbU3DeVZrFKbkWyE-9P5o7AKPvFrD817ZxJjDc9d5s7cuuPygKT9jDv5VYRM09BcAP5gfpfPo76HjcQEurJFR0ySMC0IQ-vdgvseOZBRqZnw_b6tI9EycpbgQxaRgYRYx2MWKji6ytmej7-NFw
#

here you go!

spice pendant
#

Thank you, looking

cinder hawk
#

I've been trying to debug for a bit and the error seems to be:

the post request to confirm setup intent includes the below:

"payment_method_options": {
    "card": {
      "setup_future_usage": "off_session"
    }
  },
#

and to my understanding it's triggered by the sdk

spice pendant
#

I'm trying to spin up a full integration on my end but it is just taking some time.

cinder hawk
#

absolutely - i'll update that on the backend and deploy - i'll ping you when live?

spice pendant
#

Sure!

cinder hawk
#

ok so just to check

#

we need to remove the off_session from ONLY the setup intent and not the customerSession right

spice pendant
#

Not remove but change them to 'on_session'.. trying to debug if that is culprit. To me, it sounds like a bug but my environment is spinning up very slowly to test all this on my end.

cinder hawk
#

ah gotcha

#

ok should be live

#

new auth token

eyJhbGciOiJSUzI1NiIsImtpZCI6IjBjYjQyNzQyYWU1OGY0ZGE0NjdiY2RhZWE0Yjk1YTI5ZmJhMGM1ZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZGV2LXBvcHBpbiIsImF1ZCI6ImRldi1wb3BwaW4iLCJhdXRoX3RpbWUiOjE3MjIyODE3MTAsInVzZXJfaWQiOiJES0xUTExYSG9SYnNIbFhSOG80c0ZnNkljS3gxIiwic3ViIjoiREtMVExMWEhvUmJzSGxYUjhvNHNGZzZJY0t4MSIsImlhdCI6MTcyMjI4MTcxMCwiZXhwIjoxNzIyMjg1MzEwLCJwaG9uZV9udW1iZXIiOiIrMTU1NTU1NTU1NTUiLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7InBob25lIjpbIisxNTU1NTU1NTU1NSJdfSwic2lnbl9pbl9wcm92aWRlciI6InBob25lIn19.RfwUhNY7reEzV-lLztBuhLFQa89MIJuPIPQiRkXRuNPEzADhy7329NpT1zSPX-mR0jM6qzhH00u1YAycybRzR8UwWZNY3pndZAn31AzDIKvwBGOcN1u6Oeyad5r196U6DZdBnah1Tfw1StV7-Cs23Onlm0ltejq6DiZLSH7_jQlRBQFleJC3lzGBcN5otljYV5MgWJmf27ELiFsgiogryX5c47x46pPkv0W5PK85eKynHZCFr10w1aUofup7OGRyVPBQ4O4IeSmc7Fvyby8ipDXyWFHk-p-HwqY3ouejWAU5TC7yn8rqlvRDzDxlXZ1W-LGsExxTYC5W7DyVeqmyBA
#

@spice pendant

spice pendant
#

Looking, I'm also talking to my teammate about this. Thank you for your patience

cinder hawk
#

sounds good - take your time! appreciate the help

spice pendant
#

We're trying to reproduce this on our test environment as this seems pretty buggy. I will share more updates here as soon as I can.

flat valeBOT
steel cedar
#

Was the element originally mounted with a payment intent?

#

We're seeing some odd things in the analytics events

cinder hawk
#

yes

#

actually that might be it - we're also testing rn

steel cedar
#

Yep that's it

#

I just talked with the owning team on this. You need to make sure the intent you mount the element with is the one you're confirming with

#

The error message is a bit cryptic here though

cinder hawk
#

ah damn it - that's what i was missing

steel cedar
#

The team will work on a better way to handle this in the future

#

But for now, you just need to make sure the above

cinder hawk
#

let us just test to make sure, but that should be it

#

Ok firstly @steel cedar @spice pendant @oblique jetty thank you all so much - can't believe i didn't see it until now

sorry for taking up so much time

#

the save card is finally working

#

if any of you are at sessions or st next year i def owe you a drink

steel cedar
#

Happy you got it working!

cinder hawk
#

One last q on this

Is there any way to extract the paymentMethodId from the successful setupintent on the frontend?

gloomy ridge