#Srujan-Error

1 messages · Page 1 of 1 (latest)

neat sierra
#

Hi there

drowsy fossil
#

Hello Jack!

neat sierra
drowsy fossil
#

The error object I receive back from stripe is error: code: "invalid_expiry_month_past" message: "Your card's expiration date is in the past." type: "validation_error"

#

This is if I input 01/22

neat sierra
drowsy fossil
#

I believe this is it

#

req_TtggqdINEMsXAa

neat sierra
#

I don't see a card error here

#

Maybe it's a different payment?

drowsy fossil
#

Hmm that's weird, that is definitely the payment. Not sure how Stripe is handling behind the scenes but the timing corresponds to when I hit the submit button. Just made a new payment with the 01/22 expiry date and the timing of this request req_oBXwWmX2uRWnfb is the same (12:16) but the status says 200 ok. In my console though if I print the response from confirmCardPayment I get the error object error: code: "invalid_expiry_month_past" message: "Your card's expiration date is in the past." type: "validation_error"

#

I'm using the CardElement for input and it does show a red text in the expiration month input but doesn't block me from submitting, unless that's something I need to handle?

neat sierra
#

Or can you send me the payment intent ID where you get the invalid_expiry_month_past error?

drowsy fossil
#

Sure

#

Well actually paymentIntent is undefined when this goes through

#

the response from calling confirmCardPayment doesn't give me a payment intent back

neat sierra
#

Or show me the code?

drowsy fossil
#
  const { t } = useTranslation();
  const navigate = useNavigate();

  const elements = useElements();
  const stripe = useStripe();

  const cart = useCart();
  const {
    stripeAmount,
    userInfo,
    setPaymentScreen,
    setErrorDialogText,
    setOpenPaymentsDrawer
  } = cart;

  const { setOpenOrderModal, orderDispatch } = useOrder();

  const { currentRestaurant } = useRestaurant();

  const redirectToOrder = () => {
    setOpenOrderModal(true);
    navigate(`/r/${currentRestaurant.restaurantId}`);
  };

  const getTranslatedError = (error: string) => {
    const errorResponse = getErrorDialogText(error);
    setErrorDialogText({
      title: t(errorResponse.title),
      description: t(errorResponse.description)
    });
  };

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!stripe || !elements) {
      return;
    }

    try {
      const clientSecret = await fetchClientSecret(stripeAmount);
      const cardElement = elements.getElement(CardElement);
      if (cardElement) {
        if (typeof clientSecret === 'string') {
          const confirmPaymentResponse = await stripe.confirmCardPayment(
            clientSecret,
            {
              payment_method: {
                card: cardElement
              },
              receipt_email: userInfo.email
            }
          );
          const paymentIntent = confirmPaymentResponse.paymentIntent;
          if (paymentIntent && paymentIntent.status === 'succeeded') {
            const newOrder: Order = {
              orderNum: 1,
              orderItem: cart,
              orderStatus: OrderStatus.PENDING
            };
            orderDispatch({ type: 'add_order', payload: newOrder });
            window.sessionStorage.removeItem('cart');
            cart.cartDispatch({
              type: 'clear_storage'
            });
            redirectToOrder();
          }
          console.log(confirmPaymentResponse, 'confirmPaymentResponse');
          const stripeError = confirmPaymentResponse?.error?.code;
          if (
            confirmPaymentResponse.error?.decline_code &&
            confirmPaymentResponse.error.decline_code === 'insufficient_funds'
          ) {
            getTranslatedError(confirmPaymentResponse.error.decline_code);
          } else {
            if (stripeError) {
              getTranslatedError(stripeError);
            }
          }
        } else {
          getTranslatedError('processing_error');
        }
      }
      setOpenPaymentsDrawer(false);
    } catch (error) {
      console.error(error); // TODO: replace with logging service
    }
  };
  return (
    <Container>
      <TitleContainer>
        <BackButton onClick={() => setPaymentScreen('PAYMENT_OPTIONS')}>
          <ArrowBackIosNewIcon />
        </BackButton>
        <Title variant="body1">{t('restaurant.checkout.addCCInfo')}</Title>
        <Filler />
      </TitleContainer>
      <TitleDivider />
      {stripe ? (
        <CardContainer>
          <form id="payment-form" onSubmit={handleSubmit}>
            <StripeInput id="card-element" />
            <PayWithCreditCard type="submit">
              {t('restaurant.checkout.payWithCC').toUpperCase()}
            </PayWithCreditCard>
          </form>
        </CardContainer>
      ) : (
        <CardNotAvailable>
          <Typography variant="body2">
            {t('restaurant.checkout.cardNotAvailable')}
          </Typography>
          <Typography>{t('restaurant.checkout.tryAgainLater')}</Typography>
        </CardNotAvailable>
      )}
    </Container>
  );
};
#

I'm in the middle of refactoring too, sorry if it's messy. Let me know if you have questions. Definitely could use some suggestions for optimization and cleanliness. These if else statements are awful right now

neat sierra
#

It's strange to me that you don't have a paymentIntent (undefined) and yet you are able to call stripe.confirmCardPayment

drowsy fossil
#

I have a client secret coming from the backend

neat sierra
#

Anyway the error code invalid_expiry_month_past is coming from the frontend Stripe.js, and there's no document about frontend error codes

drowsy fossil
#

Ah I see

#

Do you know if there's a way to block submission or display the front end error codes when the text is red inside of CardElement?

neat sierra
#

And I believe the error message Your card's expiration date is in the past is quite clear

drowsy fossil
#

Yeah, that's not the issue. It's more so that I'm trying to create a map of error codes to display, and we're dealing with localization as well. Not doing all of them but for the most common use cases.

neat sierra
#

The Stripe.js has built-in localization, so it will display error message in other languages

drowsy fossil
#

Ah I see so I should just pass the error message straight?

#

from the object I receive back

neat sierra
drowsy fossil
#

Thank you!

neat sierra
drowsy fossil
#

Ah that's good to know