Skip site navigation (1) Skip section navigation (2)

Re: [cool hack] Credit Card validator

From: elein <elein(at)varlena(dot)com>
To: David Fetter <david(at)fetter(dot)org>
Cc: SF Postgres <sfpug(at)postgresql(dot)org>
Subject: Re: [cool hack] Credit Card validator
Date: 2003-10-30 21:17:26
Message-ID: 20031030131726.A8206@cookie.varlena.com (view raw or flat)
Thread:
Lists: sfpug
Let me publish it in general bits.  
Why didn't you write it in plperl?

elein

On Thu, Oct 30, 2003 at 01:17:42PM -0800, David Fetter wrote:
> 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

In response to

Responses

sfpug by date

Next:From: David FetterDate: 2003-10-30 21:17:42
Subject: [cool hack] Credit Card validator
Previous:From: Josh BerkusDate: 2003-10-30 20:30:47
Subject: Re: AIX

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group