#paulc7053_code

1 messages ¡ Page 1 of 1 (latest)

summer pythonBOT
#

👋 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/1217873911006625833

📝 Have more to share? Add more details, code, screenshots, videos, etc. below.

midnight cypressBOT
#

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.

rustic plover
#

Hey!

wet portal
#

Hello

#

Was that error cut off a bit in your first message? Our discord form is a bit restrictive on character length

rustic plover
#

yep

#

I didnt have enough space

#

Error: Element confirming payment is "expressCheckout", but stripe.confirmPayment() was not called within the "confirm" event. Please call stripe.confirmPayment() in the "confirm"

#

There you go

wet portal
#

Sounds good, I am finding the doc for this either way

#

Awesome thank you

rustic plover
#

np

wet portal
#

Can you show me your current code for submitting this payment with the ECE?

rustic plover
#

`const handlePaymentButtonClick = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
return;
};

    const { error: submitError } = await elements.submit();
    if (submitError) {
        // setErrorMessage(submitError.message);
        return;
    };

    // create the customer
    const stripeCustomerIdRes = await fetch('/api/stripe/findOrCreateCustomer', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            email: 'test@test.com',
        }),
    });
    const stripeCustomerId = (await stripeCustomerIdRes.json()).stripeCustomerId;

    // create the subscription
    const subscriptionRes = await fetch('/api/stripe/createSubscription', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            priceId: 'price_1OuGSLJ4ILijjURSgay6C1iI',
            stripeCustomerId: stripeCustomerId
        }),
    });
    const clientSecret = (await subscriptionRes.json()).clientSecret;

    // confirm the payment
    const { error } = await stripe.confirmPayment({
        elements,
        clientSecret,
        confirmParams: {
            return_url: `${process.env.NEXT_PUBLIC_HOST}/payment-successful`,
        },
    });
    
    console.log('error', error);
};`
wet portal
#

And how are you calling handlePaymentButtonClick? From our express checkout element doc we show that you should do this inside an event for the element

  const {error: submitError} = await elements.submit();
  if (submitError) {
    handleError(submitError);
    return;
  }

  // Create the PaymentIntent and obtain clientSecret
  ...

  const {error} = await stripe.confirmPayment({
    // `elements` instance used to create the Express Checkout Element
    elements,
    // `clientSecret` from the created PaymentIntent
    clientSecret,
    confirmParams: {
      return_url: 'https://example.com/order/123/complete',
    },
  });
  ...
});```
Which is the event that the error is referencing
https://docs.stripe.com/elements/express-checkout-element/accept-a-payment?client=html

Learn how to accept payments with the Express Checkout Element.

#

So are you maybe calling that in an onclick function rather than the event?

rustic plover
#

like this <Button className="w-[80%] bg-soft-green h-12 rounded-2xl hover:bg-soft-green/80 text-white font-semibold text-lg 2xl:text-2xl" size="large" isDisabled={!showCheckout || !creditCardComplete || !cardExpirationComplete} onClick={(e) => handlePaymentButtonClick(e)} > PURCHASE {getCurrencySymbol(currency)}{totalPrice} </Button>

#

But this is not the ECE

#

This is using the elements

#

(although I have the same implementation for onConfirm for the express checkout)

wet portal
rustic plover
#

Sorry, to be more specivic CreditCardElements

#

<CardNumberElement options={{ style: { base: { fontSize: windowSize.width > 375 ? '18px' : "16px", }, }, }} onChange={handleChange} /> <CardExpiryElement options={{ style: { base: { fontSize: windowSize.width > 375 ? '18px' : "16px", }, }, }} onChange={handleChange} />

wet portal
#

Ah gotcha. Do you also have the express checkout element on the page? I see the error message mentions it. You should be able to have both on the page, just want to make sure I understand what you have here

rustic plover
#

Yes, I also got that on the page

wet portal
#

For the card element, I think you are supposed to use confirmCardPayment. confirmPayment is for the PaymentElement or the Express Checkout Element. So I think when you call confirmPayment, Stripe.js is reaching for both but only finds the express checkout element.
Can you try updating your code to use confirmCardPayment instead and see if that helps? https://docs.stripe.com/js/payment_intents/confirm_card_payment

rustic plover
#

yes 1 sec

#

where cardElement is import {CardElement } from '@stripe/react-stripe-js'; const cardElement = elements.getElement(CardElement); ?

#

Because that throws Uncaught (in promise) IntegrationError: Invalid value for confirmCardPayment: payment_method.card should be an object or element. You specified: null.

#

// confirm the payment const cardElement = elements.getElement(CardElement); const { error } = await stripe.confirmCardPayment(clientSecret,{ payment_method: { card: cardElement, billing_details: { name: 'Jenny Rosen', }, }, });

wet portal
#

IIRC you can pass in any of the pieces of the split card element

#

So you can pass in just the CardExpiryElement and we will find the other two and pull their data

rustic plover
#

using only the card number element throws "You must collect the security code (CVC) for this card from the cardholder before you can use it. For more information, see https://support.stripe.com/questions/cvc-collection-requirements"

#

okay, that's weird

wet portal
#

Interesting, and I assume that that is despite the CVC being filled out?

rustic plover
#

that cardElement is always null

#

yes

#

Here's the entire event handler, iv it helps you

wet portal
#

Sorry, to be clear that method does not need a card element specifically. If you are using split elements any of the individual elements can go where the card element is expected

rustic plover
#

I also tried with split elements (tried with the card number element), but it also threw an error

#

Thsi is the error object

#

{ "type": "invalid_request_error", "message": "You must collect the security code (CVC) for this card from the cardholder before you can use it. For more information, see https://support.stripe.com/questions/cvc-collection-requirements", "payment_intent": { "id": "pi_3OuHmvJ4ILijjURS14QFjw5S", "object": "payment_intent", "amount": 4900, "amount_details": { "tip": {} }, "automatic_payment_methods": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "client_secret": "pi_3OuHmvJ4ILijjURS14QFjw5S_secret_McT92qMAbTQuUQ6ZNCZmQKH6E", "confirmation_method": "automatic", "created": 1710436193, "currency": "gbp", "description": "Subscription creation", "last_payment_error": null, "livemode": false, "next_action": null, "payment_method": "pm_1OuHmwJ4ILijjURSThleig3f", "payment_method_configuration_details": null, "payment_method_types": [ "bacs_debit", "card", "link", "paypal" ], "processing": null, "receipt_email": null, "setup_future_usage": "off_session", "shipping": null, "source": null, "status": "requires_confirmation" }, "request_log_url": "https://dashboard.stripe.com/test/logs/req_IHMRGdS3P1d7MM?t=1710436194", "shouldRetry": false }

#

also the CVV is always valid

#

o wow...

#

I was confusing the expiry with CVV

#

So sorry for that!

summer pythonBOT
rustic plover
#

Thnaks a lot for the help!