Credit card expiry date validation

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Credit card expiry date validation

Wilmar Pérez
Hi all,

I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY. So what I am doing is: 

 ---------------------------------------------------------------------------
Exported from Notepad++
-- Simple function to get current date and times function getdatetime(tz) local tz = tz or 'America/New_York'; local luatz = require 'luatz'; local function ts2tt(ts) return luatz.timetable.new_from_timestamp(ts); end local utcnow = luatz.time(); local time_zone = luatz.get_tz(tz); local datetime_raw = tostring(ts2tt(time_zone:localise(utcnow))); local year, month, day, hour, min, sec, time_reminder = string.match(datetime_raw, "^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()"); return year, month, day, hour, min, sec; end local current_year, current_month = getdatetime() -- Get current year/Month local card_expiry_date = 'YYMM'; -- In the app this actually get a value eg: 2204, 2301, 2010, etc. local card_exp_year = string.sub(card_expiry_date , 3, 4) local card_exp_month = string.sub(card_expiry_date , 1, 2) -- Extract the last two digits of the Year current_year = string.sub(current_year , 3, 4) -- Check month is valid if(card_exp_month < '01' or card_exp_month > '12')then print("This is not a valid month") else -- Check date is this month or after if((card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month))then print("Date cannot be before this month.") else print("All is good.") end end





--
-----------------------------------------------------------------------


I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).

I am very aware that me an my simple app will likely not be around by then but it bugs me to leave it like this.

Can anyone please suggest a proper way to do this validation?

Thank you!


--------------------------------------------------------
Wilmar Pérez 
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Kaj Eijlers
Calculate the delta between y1 and y2, if it's larger than 50 you want (100-delta)

99-2 = 97
100-97 = 3.

I think?

On Mon, Jun 15, 2020 at 1:15 PM Wilmar Pérez <[hidden email]> wrote:
Hi all,

I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY. So what I am doing is: 

 ---------------------------------------------------------------------------
Exported from Notepad++
-- Simple function to get current date and times function getdatetime(tz) local tz = tz or 'America/New_York'; local luatz = require 'luatz'; local function ts2tt(ts) return luatz.timetable.new_from_timestamp(ts); end local utcnow = luatz.time(); local time_zone = luatz.get_tz(tz); local datetime_raw = tostring(ts2tt(time_zone:localise(utcnow))); local year, month, day, hour, min, sec, time_reminder = string.match(datetime_raw, "^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()"); return year, month, day, hour, min, sec; end local current_year, current_month = getdatetime() -- Get current year/Month local card_expiry_date = 'YYMM'; -- In the app this actually get a value eg: 2204, 2301, 2010, etc. local card_exp_year = string.sub(card_expiry_date , 3, 4) local card_exp_month = string.sub(card_expiry_date , 1, 2) -- Extract the last two digits of the Year current_year = string.sub(current_year , 3, 4) -- Check month is valid if(card_exp_month < '01' or card_exp_month > '12')then print("This is not a valid month") else -- Check date is this month or after if((card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month))then print("Date cannot be before this month.") else print("All is good.") end end





--
-----------------------------------------------------------------------


I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).

I am very aware that me an my simple app will likely not be around by then but it bugs me to leave it like this.

Can anyone please suggest a proper way to do this validation?

Thank you!


--------------------------------------------------------
Wilmar Pérez 
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Jerome Vuarand
In reply to this post by Wilmar Pérez
On Mon, 15 Jun 2020 at 21:15, Wilmar Pérez <[hidden email]> wrote:
> I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY. So what I am doing is:

You should avoid posting HTML to this email list. I can view it OK but
others might not. And when I click reply it discards all the
formatting and put all the code on one line.

> I do not know if this is the most elegant solution but it works.

Your code is inconsistent, it reads "local card_expiry_date = 'YYMM'",
while "card_exp_year = string.sub(card_expiry_date, 3, 4)" suggests
the format is MMYY. My code belows assume YYMM.

> However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).
>
> I am very aware that me an my simple app will likely not be around by then but it bugs me to leave it like this.
>
> Can anyone please suggest a proper way to do this validation?

Here's my take at the problem:

local max_lifetime = 20 -- years (cannot be more than 50)

local function check(date, now)
    if not now then
        now = tonumber(os.date('!%Y%m')) -- year and month in UTC
    end
    date = date:match('^%d%d%d%d$') -- 4 digits, nothing else
    if not date then return false end
    date = assert(tonumber(date))
    if date % 100 > 12 then return false end -- reject bad month
    date = (now // 10000 + 1) * 10000 + date -- assume next (+1) century
    -- bring back all dates beyond max lifetime into the past
    local max_expiry = now + max_lifetime * 100
    while date > max_expiry do
        date = date - 10000
    end
    -- if it's still in the future, it's valid
    return date >= now
end

card_expiry_date = 'YYMM' -- replace this with four digits
print(">", check(card_expiry_date))

And here are the test cases I used (try it before the end of the month):

assert(check('2006'))
assert(check('2007'))
assert(check('2012'))
assert(check('2101'))
assert(check('4005'))
assert(check('0106', 209905)) -- check century wrap

assert(not check('2005'))
assert(not check('1907'))
assert(not check('4105')) -- beyond 20 years
assert(not check('2013')) -- invalid month
assert(not check('201231')) -- invalid format
assert(not check('20dec')) -- invalid format
assert(not check('2106', 209905)) -- check century wrap

max_lifetime = 50
assert(check('7005')) -- may 2070
assert(check('7006')) -- june 2070
assert(not check('7007')) -- july 1970
max_lifetime = 20
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Joseph C. Sible
In reply to this post by Wilmar Pérez
On Mon, Jun 15, 2020 at 4:15 PM Wilmar Pérez <[hidden email]> wrote:
>
> I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY.
>
> -- Extract the last two digits of the Year
> current_year = string.sub(current_year , 3, 4)
> (card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month)
>
> I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).
>

You need to make an assumption: one possibility is to assume that no
credit card will be valid for more than 50 years, and that nobody will
try to use a credit card that's been expired for more than 50 years.
You can then replace your "card_exp_year < current_year" check with
"(card_exp_year - current_year) % 100 < 50".

Joseph C. Sible
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Coda Highland


On Mon, Jun 15, 2020 at 4:27 PM Joseph C. Sible <[hidden email]> wrote:
On Mon, Jun 15, 2020 at 4:15 PM Wilmar Pérez <[hidden email]> wrote:
>
> I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY.
>
> -- Extract the last two digits of the Year
> current_year = string.sub(current_year , 3, 4)
> (card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month)
>
> I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).
>

You need to make an assumption: one possibility is to assume that no
credit card will be valid for more than 50 years, and that nobody will
try to use a credit card that's been expired for more than 50 years.
You can then replace your "card_exp_year < current_year" check with
"(card_exp_year - current_year) % 100 < 50".

Joseph C. Sible

I caution against a more fundamental assumption being made here: that the expiration date is, in fact, something that should be getting validated.

There is no standard specifying whether the card is considered expired during the listed month or whether it is considered valid for that month and expired after that month ends. There is also no standard specifying that a card must be rejected after the expiration date has passed, and many credit card providers will continue to honor cards for some period of time past the printed expiration date.

For what it's worth, not every credit card provider even uses expiration dates, so that's something to be careful about too.

/s/ Adam 
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Gé Weijers
In reply to this post by Wilmar Pérez



FYI: credit cards are valid through the last day of the month they expire in. A card expiring in YYMM == '2006' can still be used today.


Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Philippe Verdy-2
In reply to this post by Wilmar Pérez
No credit card expires over more than 100 years (and even, never more than 50 years; I think that most credit cards expire within 5 years at most). So convert the 2 digits by rounding to the current years +/- 50 years, and you get the implied full year of the indicated credit card.

E.g. we are in 2020, the indicated range would be between 1970 and 2069: an indicated year 70 to 99 would convert by adding 1900, an indicated year 00 to 69 would convert by adding 2000.
In 2020, the indicated range would be between 1971 and 2070: an indicated year 71 to 99 would convert by adding 1900, an indicated year 00 to 70 would convert by adding 2000.
Each year you there are two new ranges.

Anyway you can still hard code using 1970 as the starting year. Credit cards standards are very likely to change in the future and this indication will no longer be sufficient to process any payment. In fact a new system will probably exist at that time, and you'll have to change your code anyway (or your code will no longer be used at all since long) before we reach years 2060 (at which time you *may* start to see cards expiring in 2070 or later).


Le lun. 15 juin 2020 à 22:15, Wilmar Pérez <[hidden email]> a écrit :
Hi all,

I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY. So what I am doing is: 

 ---------------------------------------------------------------------------
Exported from Notepad++
-- Simple function to get current date and times function getdatetime(tz) local tz = tz or 'America/New_York'; local luatz = require 'luatz'; local function ts2tt(ts) return luatz.timetable.new_from_timestamp(ts); end local utcnow = luatz.time(); local time_zone = luatz.get_tz(tz); local datetime_raw = tostring(ts2tt(time_zone:localise(utcnow))); local year, month, day, hour, min, sec, time_reminder = string.match(datetime_raw, "^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()"); return year, month, day, hour, min, sec; end local current_year, current_month = getdatetime() -- Get current year/Month local card_expiry_date = 'YYMM'; -- In the app this actually get a value eg: 2204, 2301, 2010, etc. local card_exp_year = string.sub(card_expiry_date , 3, 4) local card_exp_month = string.sub(card_expiry_date , 1, 2) -- Extract the last two digits of the Year current_year = string.sub(current_year , 3, 4) -- Check month is valid if(card_exp_month < '01' or card_exp_month > '12')then print("This is not a valid month") else -- Check date is this month or after if((card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month))then print("Date cannot be before this month.") else print("All is good.") end end





--
-----------------------------------------------------------------------


I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).

I am very aware that me an my simple app will likely not be around by then but it bugs me to leave it like this.

Can anyone please suggest a proper way to do this validation?

Thank you!


--------------------------------------------------------
Wilmar Pérez 
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Coda Highland
In reply to this post by Gé Weijers
On Mon, Jun 15, 2020 at 5:05 PM Gé Weijers <[hidden email]> wrote:

FYI: credit cards are valid through the last day of the month they expire in. A card expiring in YYMM == '2006' can still be used today.


You will note that almost every source on the matter says that this is "generally" true, or true for "almost all" cards. The specific day of the month is not a requirement baked into any formal credit card specification, and most finance sites instruct you to contact your issuer if it matters to you.

Cards that expire at the beginning of the month used to be more common, but with Visa and Mastercard dominating the credit card market, other providers have had a tendency to follow their lead to avoid surprising their customers.

Still: Having spent far too long dealing with ecommerce checkout pages in the past, I advise against making expiration date validation a hard error. If you want to caution the user if it looks like it might be expired, that's up to you, but let them submit it anyway!

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Philippe Verdy-2
All my credit cards show (in French) "Expire fin YYYY-MM" (explicitly the *end* of the indicated month). I have never seen any credit card expiring at start of that month (and renewed cards are sent to customers about 2 months before the expiration, 1 month at most, so there's a delay for activating the new card).
Note however that some credit card issuers may give additional delay, if the new credit card is still not sent, received and activated by the customer. Once the customer activates the new card, the old one replaced b y the new one is desactivated within the next 24 hours, sometimes even faster for internet transactions that can use a verification process with a transaction made by Visa or MasterCard with the issuing bank, or on cash withdrawal machines that are also connected). Credit card transactions are fast to process. And anyway almost all transactions made with a credit card must first be confirmed by the credit card issuer.
The credit card number (even with the correct checksum digit), the expiration date, the CCV code, the name of the credit card holder are not enough to confirm that a card is valid or not.
So I would not say that a credit card with an expiration month is past is invalid: In fact it may still be usable, but the indicated date MUST match (if not, Visa, MascardCard will reject the transaction as invalid). Then the transaction is on hold until the payment is confirmed by a pending status. MasterCard, and Visa will both contact the bank to confirm the transaction, the bank may provide a secure form to input some confirmation code, possibly sent by SMS or a secure mobile app that the owner must confirm, the user will then have to type that confirmation code, and then the form will be accepted and will return to the merchant that will receive a notification: "transaction confirmed" or "transaction cancelled" (when it is cancelled, Visa or MasterCard don't return the cause, the credit card may still be valid, but the user could not terminate the transaction in the limited time or could not receive the SMS or use their mobile app because they don't have their smartphone, or it is out of battery).

In summary, credit card transactions are not automatically renewable, and collecting and storing credit card numbers or info (expiry, owner, CCV) is not something that is sufficient (it worked in the past, but credit cards info were stolen on so many websites that most cards now no longer work with a transaction by transaction authorization. In addition, even if a transaction is accepted, it may be cancelled within the next 3 months if the customers signals the card being stolen (the customer gets a full refund by the bank, the merchant will have its account debited if it was credited earlier, so the merchant must keep a way to contact the customer and get enough info from him, but keeping the credit card info is useless and merchants should never store them longer than the time to process the single initial transaction: once the transaction has been confirmed, it is the transaction ID that the merchant must keep in case it gets cancelled: the merchant's bank will debit the merchant's account by providing this transaction ID which is what is needed to recover the unpaid product or service by other mean with the customer).

For recurrent payments, there's no warranty that it will work after the 1st transaction succeeded (in fact Visa or MasterCard do not offer such warranty, recurrent payments should be made only by another system). This is at least what is needed in Europe. US may have more "permissive" rules (but there's less protection in US for customers than those that exist in Europe, where all abused transactions are refundable: the customer just has to certify legally to his bank (sometimes as well to the police, but this is no longer necessary) that his credit card was lost or stolen, and the credit card will be blacklisted for all further transactions; the customer gets his money back, but no longer has a credit card, and must purchase a new one, or must pay an insurance to cover this cost and get a new one for free). It's up to merchants to pay an insurance if some of their paid transactions were cancelled, and to pay the recovery process for any unpaid billing (such recovery is generally hard and fails more than half the time).

But at least this system allows collecting statistics about abuses, and investigations on where the money was used. Banks, Visa, Mastercard, and insurance companies cooperate for these investigations and if needed they'll do the legal procedures themselves after isolating some hotspots of abusers. One example: if the "stolen or lost" card is inserted in any ATM, the user will be photographed by the machine. Many shops also have recording cameras that take photos of all those using their payment system (these are archived and usable for a few months, to allow judiciary or police procedures). But it is more difficult to track an abuser on the Internet (the IP address would reveal nothing if the IP was abused or if it was a mobile internet access on a phone with a "disposable" SIM that costs very little and whose owner's identity is not identifiable, of if this was using a public Wifi hotspot). For this reason, all internet transactions should be secured and not delayed, using the two-factor authentication procedure required by the credit card processor (use its API on your server or application!)





Le mar. 16 juin 2020 à 20:41, Coda Highland <[hidden email]> a écrit :
On Mon, Jun 15, 2020 at 5:05 PM Gé Weijers <[hidden email]> wrote:

FYI: credit cards are valid through the last day of the month they expire in. A card expiring in YYMM == '2006' can still be used today.


You will note that almost every source on the matter says that this is "generally" true, or true for "almost all" cards. The specific day of the month is not a requirement baked into any formal credit card specification, and most finance sites instruct you to contact your issuer if it matters to you.

Cards that expire at the beginning of the month used to be more common, but with Visa and Mastercard dominating the credit card market, other providers have had a tendency to follow their lead to avoid surprising their customers.

Still: Having spent far too long dealing with ecommerce checkout pages in the past, I advise against making expiration date validation a hard error. If you want to caution the user if it looks like it might be expired, that's up to you, but let them submit it anyway!

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Wilmar Pérez
Hello,

Sorry for the late reply and thank you very much all for your responses. They are very much appreciated. My use case is not general, it is for a specific customer which requires checking expiration dates. I think you have given me good material to work with. A lot more that I would have possibly hoped for! 

My application is an IVR, so my role is to do some level of checking before sending the transaction request to the payment gateway - e.g. credit card number is between 15 to 17 digits, exp date is not a passed date, ccv is three digits. They do the heavy lifting of actually checking everything in detail. They charge my customer every time we send a request, so the less trash we send out the better. 

@Jerome, thank you for the function, I am borrowing some of your ideas! By the way, I am not sure what I am doing to send the email in HTML, I am sending it out directly from my gmail account. 

Thanks again. Have a great day.

Wilmar 


Le jeu. 18 juin 2020 à 20:03, Philippe Verdy <[hidden email]> a écrit :
All my credit cards show (in French) "Expire fin YYYY-MM" (explicitly the *end* of the indicated month). I have never seen any credit card expiring at start of that month (and renewed cards are sent to customers about 2 months before the expiration, 1 month at most, so there's a delay for activating the new card).
Note however that some credit card issuers may give additional delay, if the new credit card is still not sent, received and activated by the customer. Once the customer activates the new card, the old one replaced b y the new one is desactivated within the next 24 hours, sometimes even faster for internet transactions that can use a verification process with a transaction made by Visa or MasterCard with the issuing bank, or on cash withdrawal machines that are also connected). Credit card transactions are fast to process. And anyway almost all transactions made with a credit card must first be confirmed by the credit card issuer.
The credit card number (even with the correct checksum digit), the expiration date, the CCV code, the name of the credit card holder are not enough to confirm that a card is valid or not.
So I would not say that a credit card with an expiration month is past is invalid: In fact it may still be usable, but the indicated date MUST match (if not, Visa, MascardCard will reject the transaction as invalid). Then the transaction is on hold until the payment is confirmed by a pending status. MasterCard, and Visa will both contact the bank to confirm the transaction, the bank may provide a secure form to input some confirmation code, possibly sent by SMS or a secure mobile app that the owner must confirm, the user will then have to type that confirmation code, and then the form will be accepted and will return to the merchant that will receive a notification: "transaction confirmed" or "transaction cancelled" (when it is cancelled, Visa or MasterCard don't return the cause, the credit card may still be valid, but the user could not terminate the transaction in the limited time or could not receive the SMS or use their mobile app because they don't have their smartphone, or it is out of battery).

In summary, credit card transactions are not automatically renewable, and collecting and storing credit card numbers or info (expiry, owner, CCV) is not something that is sufficient (it worked in the past, but credit cards info were stolen on so many websites that most cards now no longer work with a transaction by transaction authorization. In addition, even if a transaction is accepted, it may be cancelled within the next 3 months if the customers signals the card being stolen (the customer gets a full refund by the bank, the merchant will have its account debited if it was credited earlier, so the merchant must keep a way to contact the customer and get enough info from him, but keeping the credit card info is useless and merchants should never store them longer than the time to process the single initial transaction: once the transaction has been confirmed, it is the transaction ID that the merchant must keep in case it gets cancelled: the merchant's bank will debit the merchant's account by providing this transaction ID which is what is needed to recover the unpaid product or service by other mean with the customer).

For recurrent payments, there's no warranty that it will work after the 1st transaction succeeded (in fact Visa or MasterCard do not offer such warranty, recurrent payments should be made only by another system). This is at least what is needed in Europe. US may have more "permissive" rules (but there's less protection in US for customers than those that exist in Europe, where all abused transactions are refundable: the customer just has to certify legally to his bank (sometimes as well to the police, but this is no longer necessary) that his credit card was lost or stolen, and the credit card will be blacklisted for all further transactions; the customer gets his money back, but no longer has a credit card, and must purchase a new one, or must pay an insurance to cover this cost and get a new one for free). It's up to merchants to pay an insurance if some of their paid transactions were cancelled, and to pay the recovery process for any unpaid billing (such recovery is generally hard and fails more than half the time).

But at least this system allows collecting statistics about abuses, and investigations on where the money was used. Banks, Visa, Mastercard, and insurance companies cooperate for these investigations and if needed they'll do the legal procedures themselves after isolating some hotspots of abusers. One example: if the "stolen or lost" card is inserted in any ATM, the user will be photographed by the machine. Many shops also have recording cameras that take photos of all those using their payment system (these are archived and usable for a few months, to allow judiciary or police procedures). But it is more difficult to track an abuser on the Internet (the IP address would reveal nothing if the IP was abused or if it was a mobile internet access on a phone with a "disposable" SIM that costs very little and whose owner's identity is not identifiable, of if this was using a public Wifi hotspot). For this reason, all internet transactions should be secured and not delayed, using the two-factor authentication procedure required by the credit card processor (use its API on your server or application!)





Le mar. 16 juin 2020 à 20:41, Coda Highland <[hidden email]> a écrit :
On Mon, Jun 15, 2020 at 5:05 PM Gé Weijers <[hidden email]> wrote:

FYI: credit cards are valid through the last day of the month they expire in. A card expiring in YYMM == '2006' can still be used today.


You will note that almost every source on the matter says that this is "generally" true, or true for "almost all" cards. The specific day of the month is not a requirement baked into any formal credit card specification, and most finance sites instruct you to contact your issuer if it matters to you.

Cards that expire at the beginning of the month used to be more common, but with Visa and Mastercard dominating the credit card market, other providers have had a tendency to follow their lead to avoid surprising their customers.

Still: Having spent far too long dealing with ecommerce checkout pages in the past, I advise against making expiration date validation a hard error. If you want to caution the user if it looks like it might be expired, that's up to you, but let them submit it anyway!

/s/ Adam


--
--------------------------------------------------------
Wilmar Pérez 
Reply | Threaded
Open this post in threaded view
|

Re: Credit card expiry date validation

Jerome Vuarand
On Fri, 19 Jun 2020 at 12:52, Wilmar Pérez <[hidden email]> wrote:
> @Jerome, thank you for the function, I am borrowing some of your ideas! By the way, I am not sure what I am doing to send the email in HTML, I am sending it out directly from my gmail account.

From gmail, when you write an email, à the bottom right near the bin,
click the three vertical dots and select "Plain text mode".