how to mask credit card number (using regex?) |
[eluser]coolfactor[/eluser]
I'm trying to find an elegant way to turn 1234-4567-7890-4433 into xxxx-xxxx-xxxx-4433. I found this tutorial, but I'm not much of a regex person and don't know how to rewrite that for use in PHP. Here's the code from that tuturial, in Rails: Code: @card_masked = card_masked.sub(/^([0-9]+)([0-9]{4})$/) { '*' * $1.length + $2 } Which PHP function should I be using? Your help is appreciated. Thanks!
[eluser]coolfactor[/eluser]
I've managed to separate the two parts of the number. Here's my progress so far: Code: $cc = '1234-4344-2994-4394'; The result is: Code: array(3) Now, how do I use preg_replace() instead to mask element [1]?
[eluser]coolfactor[/eluser]
Got it. Here's the completed code. It accepts hyphen or space-delimited numbers, or even numbers without any delimiters. Code: function mask_cc($cc, $mask_char = 'X') Echos: ****-****-****-4394
[eluser]jupiter909[/eluser]
Hmmm the long way round. You'd much rather be using regex for things such as verifying credit-card numbers/phone numbers/postal codes. To change 1234-4567-7890-4433 into xxxx-xxxx-xxxx-4433. is as easy as Code: $last_four_digits = substr("$credit_card_number", -4); Avoid using regex when not needed.
[eluser]coolfactor[/eluser]
Why? The point was to mask the *actual* entry, not assume it's in a certain format. 234876512483211 ************2113 2348-7651-2483-2113 ****-****-****-2113 etc.
[eluser]Pygon[/eluser]
A fix note to coolfactors code: Code: return preg_replace('([0-9])', 'X', $matches[1]).$matches[2]; However -- I would do: Code: function mask_cc($cc, $mask_char='X') Honestly, I would wonder why you feel it important to return information in the same form it is input? I would have no interest in making sure that the version they see matches the format they typed in... and I expect that, when I make purchases, my card may be entered with or without spaces, or with hyphens, but that it will be displayed as ************XXXX <card type> as a result. I see no reason to adopt user-input formating as to how my system handles and displays billing information. My very personal version would be: Code: function mask_cc($cc, $mask_char='X')
[eluser]untermensch[/eluser]
Any purely regex solution to the above problem would not look very elegant. A rather simple way to achieve the desired result would be: Code: function mask_cc($cc, $mask_char='X') Which preserves the format (spaces & dashes) and leaves the last 4 digits unaltered, as per the request. Not sure why everybody is over-engineering the solutions to this problem. There are more difficult things to be worrying about!
[eluser]Pygon[/eluser]
I don't think it has to do with "over-engineering". Mine is a concern for speed and enforcing standards, while allowing user input to be anything they want while still working. Should your function encounter a trailing hyphen, it would not work properly. "Simplicity", in the form of one-line functions, doesn't necessarily mean it is the best solution. Regex is great but takes it's toll on the CPU. String manipulation uses far less CPU, and is often the same speed or faster. My function is limited in scope as to just masking any card that is entered (provided there are atleast 4 numbers). A more functional solution would be a seperate function which strips all formatting, allowing one variable (containing the card number after being stripped) to be used for multiple things like: simple form verification - strlen(16) pre-auth - no need to strip formatting, again. billing - same as above receipt(masking) - same as above One regex versus many is always better. Why waste more CPU cycles maintaining a user's input rather than spending them on something of use. Our goal, as web developers, is to unrestrict users (by not forcing them to follow standards), while enforcing standards internally for speed, maintenance and operations. Approaching anything with "just do something that works, there are more important things" breeds future problems--always. Have a read through WorseThanFailure if you think otherwise.
[eluser]untermensch[/eluser]
[quote author="Pygon" date="1194044896"]Mine is a concern for speed and enforcing standards, while allowing user input to be anything they want while still working. Should your function encounter a trailing hyphen, it would not work properly.[/quote] Mate, have you even tried running your one above? The preg_replace is superfluos, and it strips out the hyphens, and assumes all CC numbers have 16 digits (they vary between 14 and 16). Besides which, nobody asked about a CC number *validator*. It is assumed validation has already been done. The request was only to mask out all but the last 4 digits - so the trailing hyphen point is entirely moot (although your solution suffers from the same "problem"). [quote author="Pygon" date="1194044896"]"Simplicity", in the form of one-line functions, doesn't necessarily mean it is the best solution.[/quote] Simplicity is readability. [quote author="Pygon" date="1194044896"]Regex is great but takes it's toll on the CPU.[/quote] Which makes me wonder why you have a redundant preg_replace ![]() [quote author="Pygon" date="1194044896"]My function is limited in scope as to just masking any card that is entered (provided there are atleast 4 numbers)[/quote] Which is exactly what the original poster asked for... |
Welcome Guest, Not a member yet? Register Sign In |