From: | David Fetter <david(at)fetter(dot)org> |
---|---|
To: | SF Postgres <sfpug(at)postgresql(dot)org> |
Subject: | [cool hack] Credit Card validator |
Date: | 2003-10-30 21:17:42 |
Message-ID: | 20031030211742.GV10904@fetter.org |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | sfpug |
Kind people,
I know it's not the cleanest or efficientest, but I've ported part of
Business::CreditCard into PL/PgSQL. Assuming it passes muster, where
should I put it? Is there a CPAN-type thingy for PL/PgSQL? Should
there be?
Cheers,
D
CREATE OR REPLACE FUNCTION cc_check (VARCHAR) RETURNS BOOLEAN AS '
DECLARE
cc_num ALIAS FOR $1;
i INTEGER;
d VARCHAR;
weight INTEGER;
checksum INTEGER := 0;
oddness INTEGER;
num INTEGER;
tempstring VARCHAR;
BEGIN
-- Strip out non-digits. Oh, for an s/// construct! :)
tempstring := '''';
FOR i IN 1 .. length(cc_num)
LOOP
d := SUBSTRING(cc_num, i, 1);
IF d ~ ''[0-9]''
THEN
tempstring := tempstring || d;
END IF;
END LOOP;
-- Check length for reasonableness.
IF (length(tempstring) < 13)
THEN
RAISE NOTICE ''% is too short to be a credit card number.'', cc_num;
RETURN FALSE;
END IF;
-- Do a Luhn checksum.
oddness := length(tempstring) % 2;
FOR i IN 1 .. length(tempstring)
LOOP
num := SUBSTRING(tempstring, i, 1)::integer;
IF (oddness = 0 AND i % 2 = 1)
THEN
num := num * 2;
ELSIF (oddness = 1 AND i%2 = 0)
THEN
num := num * 2;
END IF;
IF num > 9
THEN
num := num - 9;
END IF;
checksum := checksum + num;
END LOOP;
IF checksum % 10 <> 0
THEN
RAISE NOTICE ''% does not have a valid checksum.'', cc_num;
RETURN FALSE;
END IF;
IF tempstring ~ ''^3[47][0-9]{13}$''
THEN
RAISE NOTICE ''% is an American Express card.'', cc_num;
ELSIF tempstring ~ ''^4[0-9]{12}([0-9]{3})?$''
THEN
RAISE NOTICE ''% is a VISA card.'', cc_num;
ELSIF tempstring ~ ''^5[1-5][0-9]{14}$''
THEN
RAISE NOTICE ''% is a MasterCard.'', cc_num;
ELSIF tempstring ~ ''^6011[0-9]{12}$''
THEN
RAISE NOTICE ''% is a Discover card.'', cc_num;
ELSIF tempstring ~ ''^3(0[0-5]|[68][0-9])[0-9]{11}$''
THEN
RAISE NOTICE ''% is a Diners Club/Carte Blanche.'', cc_num;
ELSIF tempstring ~ ''^2(014|149)\d{11}$''
THEN
RAISE NOTICE ''% is an enRoute card.'', cc_num;
ELSIF tempstring ~ ''^(3\d{4}|2131|1800)\d{11}$''
THEN
RAISE NOTICE ''% is a JCB card.'', cc_num;
ELSIF tempstring ~ ''^56(10\d\d|022[1-5])\d{10}$''
THEN
RAISE NOTICE ''% is a BankCard.'', cc_num;
END IF;
RETURN TRUE;
END;
' LANGUAGE 'plpgsql';
--
David Fetter david(at)fetter(dot)org http://fetter.org/
phone: +1 510 893 6100 cell: +1 415 235 3778
From | Date | Subject | |
---|---|---|---|
Next Message | Dror Matalon | 2003-10-30 21:37:58 | [support@bloki.com: Fastbuzz a new service from the Bloki team] |
Previous Message | elein | 2003-10-30 21:17:26 | Re: [cool hack] Credit Card validator |