Demo for Luhn algorithm in PHP

If you have a number that adheres to the Luhn algorithm for validation, you may check it easily with this short PHP snippet.

<?php
function luhn($str) {
        $odd = !strlen($str)%2;
        $sum = 0;
        for($i=0;$i<strlen($str);++$i) {
            $n=0+$str&#91;$i&#93;;
            $odd=!$odd;
            if($odd) {
                $sum+=$n;
            } else {
                $x=2*$n;
                $sum+=$x>9?$x-9:$x;
            }
        }
        return(($sum%10)==0);
}
$num = $_GET['number'];
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Online Luhn algorithm test</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
</head>
<body>
<?php if($num) { ?>
<?php   if(luhn($num)) { ?>
<div style="background:#ddffdd;border:1px solid #004400;">
<?=htmlspecialchars($num)?> is valid
</div>
<?php   } else { ?>
<div style="background:#ffdddd;border:1px solid #880000;">
<?=htmlspecialchars($num)?> is NOT valid
</div>
<?php   } ?>
<?php } ?>
<form action="luhn.php" method="GET">
<div>
Number: <input type="text" name="number" value="<?=urlencode($num)?>" size="40"/>
<input type="button" name="btSend" value="Check"/>
</div>
</form>
</body>

(Download)
You may test this script at https://javier.rodriguez.org.mx/code/luhn-test.php.
Please consider that this is a demo, so please do not use this to check credit card numbers unless you send me an expiry date. CCV2 has taken over as the preferred method for credit card number validation anyway.

Posted in Code, General, PHP
7 comments on “Demo for Luhn algorithm in PHP
  1. Pablo says:

    Amigo: a ese ejemplo ponele un submit, pone en lugar de : name=”num” y saca el ACTION que esta de mas y confunde, porque de lo contrario, ese ejemplo no va a funcionar en la puta vida. Un fuerte a abrazo, y de todos modos: GRACIAS!

  2. Pablo says:

    Un agregado, para que aclare mi mensaje anterior: la linea
    $num = $_GET[‘number’];
    no esta funcionando correctamente, de hecho, en tu ejemplo web no funciona.
    Nos vemos, amigo.

  3. Lawrence says:

    I don’t think your algorithm is correct. Among others, it fails on the test Visa number: 4111111111111111.

    -L

  4. I agree with Lawrence your algorithm doesn’t validate

    Thanks,

    Mike

  5. dbl says:

    Here is a (RIGHT-CODED & STRICT) Algorithm … ( do not delete my postings =/ ) it’s your content. But may if you do not want to have qualitiv content – delete it. For German Bankaccounts see the national bank (Deutsche Bundesbank)

    … think big ppl ;)

    /**
    * Luhn-Algorithm for Creditcards an Bankaccounts
    * Creditcards exposure is everytime 1212… in length of the cardnumber
    * Banknumbers will have for each bank a own exposure.
    * I hope all Verificationnumbers will be calculatet for Bankaccounts with this algorithm.
    * In Some Cases the modulo have to be changed. On Creditcards the module everytime is 10.
    * Please report bugs to doubleatdumpitde.
    *
    * @param string $nb have to be string and numeric because double is to small
    * @param string $exp have to be string and numeric because double is to small
    * @param int $mod used modulo
    * @return boolean
    */
    function _luhn( $nb, $exp = ‘1212121212121212’, $mod = 10 )
    {
    // first validate parameters
    if( !is_string( $nb ) )
    return PEAR::raiseError( ‘given parameter nb (number) is not a string’, null );
    if( !is_string( $exp ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not a string’, null );
    if( !is_numeric( $nb ) )
    return PEAR::raiseError( ‘given parameter nb (number) is not numeric’, null );
    if( !is_numeric( $exp ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not numeric’, null );
    if( !is_integer( $mod ) )
    return PEAR::raiseError( ‘given parameter mod (modulo) is not numeric’, null );
    if( 0 >= $int )
    return PEAR::raiseError( ‘given parameter nb (number) could not be lower than or zero’, null );
    if( strlen($exp) != strlen( $int ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not in characterlength of nb (number)’, null );

    // lets do the calculation
    for( $sum = 0, $pos = 0; $pos = $x ? $x : $x[0]+$x[1];
    }

    return(0==$sum%$mod);
    }

  6. dbl says:

    ??

  7. dbl says:

    Ok, Sry ppl, here is the debuged (working) version … a new try to post.
    Maybe the calculation have to be done recursive (see wikipedia)

    /**
    * Luhn-Algorithm for Creditcards an Bankaccounts
    * Creditcards exposure is everytime 2121… in length of the cardnumber
    * Banknumbers will have for each bank a own exposure.
    * I hope all Verificationnumbers will be calculatet for Bankaccounts with this algorithm.
    * In Some Cases the modulo have to be changed. On Creditcards the module everytime is 10.
    * Please report bugs to doubleatdumpitde
    *
    * @param string $nb have to be string and numeric because double is to small
    * @param string $exp have to be string and numeric because double is to small
    * @param int $mod used modulo
    * @return boolean
    */
    function _luhn( $nb, $exp = ‘2121212121212121’, $mod = 10 )
    {
    // first validate parameters
    if( !is_string( $nb ) )
    return PEAR::raiseError( ‘given parameter nb (number) is not a string’, null );
    if( !is_string( $exp ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not a string’, null );
    if( !is_numeric( $nb ) )
    return PEAR::raiseError( ‘given parameter nb (number) is not numeric’, null );
    if( !is_numeric( $exp ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not numeric’, null );
    if( !is_integer( $mod ) )
    return PEAR::raiseError( ‘given parameter mod (modulo) is not numeric’, null );
    if( 0 >= $nb )
    return PEAR::raiseError( ‘given parameter nb (number) could not be lower than or zero’, null );
    if( strlen($exp) != strlen( $nb ) )
    return PEAR::raiseError( ‘given parameter exp (exposure) is not in characterlength of nb (number)’, null );

    // lets do the calculation
    for( $sum = 0, $pos = 0; $pos < strlen( $nb ); $pos++ )
    {
    $x = $exp[$pos]*$nb[$pos];
    $sum += 9 > $x ? $x : substr($x,0,1)+substr($x,1,1);
    }
    return(0<$sum&&0==$sum%$mod);
    }

    isn’t it easy ;)