#Srujan-Error
1 messages · Page 1 of 1 (latest)
Hello Jack!
Do you mean invalid_expiry_month ? this is a card decline code, and the list of decline codes is here https://stripe.com/docs/declines/codes
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
Can you share the request ID (req_xxx)? Here's how you can find it: https://support.stripe.com/questions/finding-the-id-for-an-api-request
Find help and support for Stripe. Our support center provides answers on all types of situations, including account information, charges and refunds, and subscriptions information. Get your questions answered and find international support for Stripe.
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?
Or can you send me the payment intent ID where you get the invalid_expiry_month_past error?
Sure
Well actually paymentIntent is undefined when this goes through
the response from calling confirmCardPayment doesn't give me a payment intent back
Or show me the code?
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
It's strange to me that you don't have a paymentIntent (undefined) and yet you are able to call stripe.confirmCardPayment
I have a client secret coming from the backend
Anyway the error code invalid_expiry_month_past is coming from the frontend Stripe.js, and there's no document about frontend error codes
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?
And I believe the error message Your card's expiration date is in the past is quite clear
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.
The Stripe.js has built-in localization, so it will display error message in other languages
Ah I see so I should just pass the error message straight?
from the object I receive back
You can listen to this event https://stripe.com/docs/js/element/events/on_change?type=cardElement#element_on_change-handler-error and disable the submit button if there's an error
Thank you!
No problem. You can also pass a locale (https://stripe.com/docs/js/initializing#init_stripe_js-options-locale) when initializing Stripe.js for so that Stripe.js will display localized error strings
Ah that's good to know