php.de

Zurück   php.de > php.de Intern > Wiki Diskussionsforum > Tutorials

Tutorials Hier findest Du Tutorials, welche nach und nach ein fertiges Script ergeben. Sehen, lernen & verstehen!

Antwort
 
LinkBack (5) Themen-Optionen Thema bewerten
Alt 12.04.2008, 06:40  
Erfahrener Benutzer
 
Registriert seit: 21.05.2008
Beiträge: 9.937
Zergling-new wird schon bald berühmt werden
Standard PHP: Kreditkartenvalidierung

Hallo,
ich habe mir soeben eine Klasse gebastelt, mit der sich Kreditkarten-Numbern validieren lassen. Dies erfolgt ausschliesslich per Formatpruefung. Ein Modul fuer Authorize.net ist geplant, ebenso wie eine Auslagerung der Sprachen in der Exception-Klasse.

PHP-Code:
<?php
try {
    
CreditCard::SetTestMode();
    
$objCC = new CreditCard();
    
$objCC->AllowType(CreditCard::DiscoverCreditCard::MasterCard);
    
$objCC->Type CreditCard::Visa// check type
    
$objCC->Number NULL// test your credit card number here
    
$objCC->ExpirationYear 2008;
    
$objCC->ExpirationMonth 3;
    
$objCC->Check();
    
printf("Your credit card (%s) is valid."$objCC->Xnumber);
} catch (
CreditCardException $objExc) {
    
$objExc->RenderHtml();
}
// the input should be denied for multiple reasons:
// "Visa" is not allowed, no number entered, expired.
?>
Ganz laessig finde ich auch den TestMode (eigentlich dafuer gedacht um einen teuren Online-Check zu vermeiden), der entsprechend des Fehlers eine andere Ausgabe erzeugt. Beispielsweise soll der User im Livemodus keine naeheren Informationen darueber erhalten, weshalb seine Kreditkarten Nummer nicht akzeptiert wurde, um Fakes zu vermeiden. Ein Blick auf die Kreditkarte (wenn sie denn existiert) sollte dem Benutzer Klarheit verschaffen.

Ebenfalls steht die Methode GetXnumber() bzw. die Eigenschaft Xnumber zur Verfuegung, um alles bis auf die letzten 4 Zeichen der Kreditkarte durch Xe zu ersetzen.

Ich wuerde mich freuen, wenn ihr eure Kreditkarten damit testet, ich konnte bisher nur meine Visa-Karte erfolgreich testen, das ist leider etwas wenig. Postet mir dann bitte NICHT eure Kreditkarten Nummern - die Exception reicht aus (obwohl, ..)

Zur Lizenz: Ihr koennt die Klasse frei verwenden, privat oder kommerziel, ihr koennt sie auch weiterentwickeln, wuerde mich ueber Feedback freuen.
In den naechsten Tagen werde ich die Klasse um einige weitere Kreditkartentypen und Kommentare (am Ende hatte ich keine Lust mehr) erweitern.

PHP-Code:
<?php
/**
 * @desc
 * Provides a credit card checking functionality. You can check type, number and expiration date for consistency.
 * This class handles the credit card number as string, not as integer to prevent integer overflows.
 * 
 * @author Christian Reinecke <christian.reinecke@web.de>
 * @date 2008-04-11
 * @version 0.1 beta
 * 
 * @licence
 * Free for usage in any project, private or commercial. Just keep this author comments in the file.
 * 
 * @warning
 * Never checked in a real production system.
 * 
 * @example
 * <code>
 * try {
 *     CreditCard::SetTestMode(); // detailed error messages
 *     
 *     $objCC = new CreditCard();
 *     // $objCC->AllowAllTypes();
 *     $objCC->AllowType(CreditCard::Visa, CreditCard::MasterCard);
 *     $objCC->Type = "Visa";
 *     $objCC->Number = "1234-abcd-5678-9101-1121"; // your credit card here, format not important, but use a string
 *     $objCC->ExpirationYear = 12;
 *     $objCC->ExpirationMonth = 3;
 *     
 *     $objCC->Check();
 *     printf("Your credit card (%s) is valid.", $objCC->Xnumber);
 * } catch (CreditCardException $objExc) {
 *     $objExc->RenderHtml();
 * }
 * </code>
 */
class CreditCard {
    
/**
     * @desc
     * The default mode provide has yet no effect to this class, but to the CreditCardException.
     */
    
const TestModeDefault true;
    
    
/**
     * @desc Abbreviations for the provided cc types.
     * @see $CreditCard->GetAllowedTypesAsOptions()
     */
    
const AmericanExpress "AmEx";
    const 
Discover        "Disc";
    const 
MasterCard      "MC";
    const 
Visa            "Visa";  
    
    
/**
     * @desc
     * Using integer constants instead of associate string keys to address key index in the $arrTypes array.
     * 
     * @warning internal use only
     */
    
const Name       0;
    const 
Abbrev     1;
    const 
Length     2;
    const 
Prefix     3;
    const 
CheckDigit 4;

    
/**
     * @desc information about credit card checks, feel free to extend the array
     * @var array
     */
    
protected $arrTypes = array(
        
self::AmericanExpress => array(self::Name       => "American Express",
                                       
self::Abbrev     => "AmEx",
                                       
self::Length     => 15
                                       
self::Prefix     => array("34""37"), // using string to prevent integer overflow
                                       
self::CheckDigit => true),
                                       
        
self::Discover        => array(self::Name       => "Discover",
                                       
self::Abbrev     => "Disc",
                                       
self::Length     => 16
                                       
self::Prefix     => "6011",
                                       
self::CheckDigit => true),
                                       
        
self::MasterCard      => array(self::Name       => "MasterCard",
                                       
self::Abbrev     => "MC",
                                       
self::Length     => 16
                                       
self::Prefix     => array("51""52""53""54""55"),
                                       
self::CheckDigit => true),
                                       
        
self::Visa            => array(self::Name       => "Visa",
                                       
self::Abbrev     => "Visa",
                                       
self::Length     => array(1316),
                                       
self::Prefix     => "4",
                                       
self::CheckDigit => true),
    );
    
    
/**
     * @desc current test mode status
     * @staticvar bool
     */
    
protected static $blnTestMode self::TestModeDefault;
    
    
/**
     * @desc each cc object has its own list of allowed cc types, because you might accept not every cc type
     * @var array
     */
    
protected $arrAllowedTypes = array();
    
    
/**
     * @desc information about the cc type, should be a value of the class constants
     * @see CreditCard::Visa, CreditCard::MasterCard, ..
     * @see $CreditCard->Type
     * @see $CreditCard->SetType()
     * @see $CreditCard->OriginalType
     * @see $CreditCard->CheckType()
     * @var string
     */
    
protected $strType;
    
    
/**
     * @desc user's cc card number, might be cleaned up, let's use string here (otherwise we get an integer overflow)
     * @see $CreditCard->Number
     * @see $CreditCard->OriginalNumber
     * @see $CreditCard->CheckNumber()
     * @var string 
     */
    
protected $strNumber;

    
/**
     * @desc
     * The user's cc card expiration full year, that means that this integer has 4 digits (f.e. 2008), even if the user
     * entered a 2-digit year (08).
     * 
     * @see $CreditCard->ExpirationFullYear
     * @see $CreditCard->OriginalExpirationYear
     * @see $CreditCard->ExpirationMonth
     * @see $CreditCard->OriginalExpirationMonth
     * @see $CreditCard->CheckExpirationDate()
     * @var int 
     */
    
protected $intExpirationFullYear;
    
    
/**
     * @desc user's cc card expiration month
     * @see $CreditCard->ExpirationMonth
     * @see $CreditCard->OriginalExpirationMonth
     * @see $CreditCard->ExpirationFullYear
     * @see $CreditCard->OriginalExpirationYear
     * @see $CreditCard->CheckExpirationDate()
     * @var int 
     */
    
protected $intExpirationMonth;
    
    
/**
     * @desc
     * The card security code is the security code on the back side of most credit cards, we are using a string
     * to loose leading zeros.
     * 
     * @warning not yet implemented
     * @todo implement
     * @see 
     * @see CreditCard::CheckCsc()
     * @var string
     */
    
protected $strCsc;
    
    
/**
     * @desc the original user-provided string (just trimmed) for his cc type, we probably don't need this
     * @warning might be removed in the next version
     * @see $CreditCard->OriginalType
     */
    
protected $strOriginalType;
    
    
/**
     * @desc
     * The original user-provided string (just trimmed) for his cc number, it's used for displaying the x-number,
     * because we want to use the user's input syntax (1235-4567-.. -> XXXX-XXXX-..) instead of using the
     * normalized cc number (12354567.. -> XXXXXXXX).
     * 
     * @see $CreditCard->OriginalNumber
     */
    
protected $strOriginalNumber
    
    
/**
     * @desc
     * The original user-provided string (just trimmed) for his expiration year, might be different from the
     * expiration *full* year (8 -> 2008).
     * 
     * @warning might be removed in the next version
     * @see $CreditCard->OriginalExpirationYear
     */
    
protected $strOriginalExpirationYear;
    
    
/**
     * @desc the original user-provided string (just trimmed) for his expiration month, we probably don't need this
     * @warning might be removed in the next version
     * @see $CreditCard->OriginalExpirationMonth
     */
    
protected $strOriginalExpirationMonth;
    
    
/**
     * @desc the original user-provided string (just trimmed) for his cc security code, we probably don't need this
     * @warning might be removed in the next version
     * @see $CreditCard->OriginalCsc
     */
    
protected $strOriginalCsc;
    
    
/**
     * @desc constructor
     * @warning the arguments may change in future versions
     * @param string optional allowed cc type (use as much arguments as you need)
     */
    
public function __construct() {
        
$arrAllowedTypes func_get_args();
        foreach (
$arrAllowedTypes as $strAllowedType) {
            
$this->AllowType($strAllowedType);
        }
    }
    
    
/**
     * @desc magic setter method
     * @see $CreditCard->GetSetterProperties()
     * @see $CreditCard->Set*()
     */
    
public function __set($strProperty$strValue) {
        if (!
in_array($strProperty$this->GetSetterProperties())) {
            throw new 
CreditCardException(CreditCardException::UndefinedSetProperty$strProperty$this->GetSetterProperties());
        }
        
$strMethod "Set$strProperty";
        if (!
method_exists($this$strMethod)) {
            throw new 
CreditCardException(CreditCardException::UndefinedSetMethod$strMethod$strProperty$strValue);
        }
        
$this->$strMethod($strValue);
    }
    
    
/**
     * @desc magic getter method
     * @see $CreditCard->GetGetterProperties()
     * @see $CreditCard->Get*()
     */
    
public function __get($strProperty) {
        if (!
in_array($strProperty$this->GetGetterProperties())) {
            throw new 
CreditCardException(CreditCardException::UndefinedGetProperty$strProperty$this->GetGetterProperties());
        }
        
$strMethod "Get$strProperty";
        if (!
method_exists($this$strMethod)) {
            throw new 
CreditCardException(CreditCardException::UndefinedGetMethod$strMethod$strProperty);
        }
        return 
$this->$strMethod();
    }
    
    
/**
     * @desc set test mode to TRUE
     * @see CreditCard::SetLiveMode()
     * @see CreditCard::IsTestMode()
     * @return void
     */
    
public static function SetTestMode() {
        
self::$blnTestMode true;
    }
    
    
/**
     * @desc set test mode to FALSE
     * @see CreditCard::SetTestMode()
     * @see CreditCard::IsLivetMode()
     * @return void
     */
    
public static function SetLiveMode() {
        
// feel free to comment the following line, but in a good live system, you shouldn't see any E_NOTICE errors
        
trigger_error(sprintf("PHP user class %s has been set to *LIVE* mode"__CLASS__), E_USER_NOTICE);
        
self::$blnTestMode false;
    }
    
    
/**
     * @desc checks your current test mode status
     * @see CreditCard::SetTestMode()
     * @see CreditCard::IsLiveMode()
     * @return bool
     */
    
public static function IsTestMode() {
        return 
self::$blnTestMode;
    }
    
    
/**
     * @desc checks your current test mode status
     * @see CreditCard::SetLiveMode()
     * @see CreditCard::IsTestMode()
     * @return bool
     */
    
public static function IsLiveMode() {
        return !
self::$blnTestMode;
    }
    
    
/**
     * @desc
     * Validate and checks the user's input. This method has no return value, it case of an error it throws an
     * exception and it is up to you to catch this exception. In case of success, nothing happens.
     * 
     * @example  
     * <code>
     * try {
     *     $objCC = new CreditCard();
     *     // set user's input
     *     $objCC->Check();
     *     $blnSuccess = true;
     * } catch (CreditCardException $objExc) {
     *     $blnSuccess = false;
     * }
     * </code>
     * 
     * @see $CreditCard->CheckType()
     * @see $CreditCard->CheckNumber()
     * @see $CreditCard->CheckExpirationDate()
     * @see $CreditCard->CheckCsc()
     * @link [url]http://php.net/exceptions[/url]
     * 
     * @param bool optional check also CSC
     * @return void
     */
    
public function Check($blnCheckCsc false) {
        
$this->CheckType();
        
$this->CheckNumber();
        
$this->CheckExpirationDate();
        if (
$blnCheckCsc) {
            
$this->CheckCsc();
        }
    }
    
    
/**
     * @desc allow public "setting" for these properties
     * @return array
     */
    
protected function GetSetterProperties() {
        return array(
"Type""Number""ExpirationYear""ExpirationMonth""Csc");
    }
    
    
/**
     * @desc allow public "getting" for these properties
     * @return array
     */
    
protected function GetGetterProperties() {
        return array(
"Type""OriginalType""Number""OriginalNumber""ExpirationFullYear""OriginalExpirationYear",
            
"ExpirationMonth""OriginalExpirationMonth""Csc""OriginalCsc""Xnumber");
    }
    
    
/**
     * @desc getter method for number
     * @see $CreditCard->Number 
     * @return string
     */
    
public function GetNumber() {
        return 
$this->strNumber;
    }
    
    
/**
     * @desc getter method for original number
     * @see $CreditCard->Number 
     * @return mix
     */
    
public function GetOriginalNumber() {
        return 
$this->strOriginalNumber;
    }
    
    
/**
     * @desc
     * Public getter method for the x-number. The x-number replaces all digits of the original number,
     * except the last 4 with an X.
     * 
     * @example XXXX-XXXX-XXXX-6789
     * @see $CreditCard->Xnumber
     * @see $CreditCard->OriginalNumber
     * @return string 
     */
    
public function GetXnumber() {
        
// x-fill credit card number left-handed except for the last 4 digits
        
$arrMatches NULL;
        if (!
preg_match("#^(.+)(([0-9][^0-9]*){4})$#"trim($this->OriginalNumber), $arrMatches)) {
            return 
preg_replace("#[0-9]#""X"$this->OriginalNumber);
        }
        
$strPrefix  $arrMatches[1];
        
$strPostfix $arrMatches[2]; 
        return 
preg_replace("#[0-9]#""X"$strPrefix) . $strPostfix;
    }
    
    
/**
     * @desc setter method for type
     * @see $CreditCard->Type
     * @return string
     */
    
public function SetType($strType) {
        
$this->strOriginalType $strType;
        
$this->strType = (string)trim($this->strOriginalType);
    }
    
    
/**
     * @desc getter method for type
     * @see $CreditCard->Type
     * @see $CreditCard->OriginalType
     * @return string
     */
    
public function GetType() {
        return 
$this->strType;
    }
    
    
/**
     * @desc getter method for expiration full year
     * @see $CreditCard->ExpirationFullYear
     * @see $CreditCard->OriginalExpirationYear
     * @return string
     */
    
public function GetExpirationFullYear() {
        return 
$this->intExpirationFullYear;
    }
    
    
/**
     * @desc getter method for expiration month
     * @see $CreditCard->ExpirationMonth
     * @see $CreditCard->OriginalExpirationMonth
     * @return string
     */
    
public function GetExpirationMonth() {
        return 
$this->intExpirationMonth;
    }
    
    
/**
     * @desc getter method for original expiration year
     * @warning might be removed in future versions
     * @see $CreditCard->OriginalExpirationYear
     * @return mix
     */
    
public function GetOriginalExpirationYear() {
        return 
$this->strOriginalExpirationYear;
    }
    
    
/**
     * @desc getter method for original expiration month
     * @warning might be removed in future versions
     * @see $CreditCard->OriginalExpirationMonth
     * @return mix
     */
    
public function GetOriginalExpirationMonth() {
        return 
$this->strOriginalExpirationMonth;
    }
    
    
/**
     * @desc getter method for cc security code
     * @see $CreditCard->Csc
     * @return string
     */
    
public function GetCsc() {
        return 
$this->strCsc;
    }
    
    
/**
     * @desc
     * You can use this method after adding the allowed types for your cc check. The return value is an array,
     * the keys are the abbreviations, the values the name of the credit card. You might use this to build
     * your html <select>/<options> formular.
     * 
     * @example
     * array("Visa" => "Visa", "MC" => "MasterCard", ..)
     * 
     * @see $CreditCard->AllowType()
     * @see $CreditCard->AllowAllTypes()
     * @return array 
     */
    
public function GetAllowedTypesAsOptions() {
        
$arrSelectOptions = array();
        foreach (
$this->GetAllowedTypes() as $strAllowedType) {
            
$arrSelectOptions[$strAllowedType] = $this->arrTypes[$strAllowedType][self::Name];
        }
        
ksort($arrSelectOptions);
        return 
$arrSelectOptions;
    }
    
    
/**
     * @desc checks your cc type and throws an exception if there has been any error found
     */
    
protected function CheckType() {
        if (
is_null($this->Type)) {
            throw new 
CreditCardException(CreditCardException::CheckFailedTypeUnset);
        }
        if (
strlen($this->Type) == 0) {
            throw new 
CreditCardException(CreditCardException::EmptyType);
        }
        if (!
$this->IsType($this->Type)) {
            throw new 
CreditCardException(CreditCardException::UnknownType$this->Type$this->GetAllTypes());
        }
        if (!
$this->IsAllowedType()) {
            throw new 
CreditCardException(CreditCardException::DisallowedType$this->GetTypeName(), $this->GetAllowedTypesNames());
        }
    }
    
    public function 
SetNumber($strNumber$blnIsOriginal true) {
        
$strOriginalNumber trim($strNumber);
        if (
$blnIsOriginal) {
            
$this->strOriginalNumber trim($strOriginalNumber);
        }
        
$this->strNumber = (string)trim($strOriginalNumber);
        
// do not clean up number here, we should check for bad characters first
        // it might be a feature to just ignore every non-digit, but I felt uncomfortable to accept
        // credit card numbers like these: "1234-hello-5678-91011-1213"
        // so clean it up later
    
}
    
    protected function 
CheckNumber() {
        if (
is_null($this->Number)) {
            throw new 
CreditCardException(CreditCardException::CheckFailedNumberUnset);
        }
        if (
strlen($this->strNumber) == 0) {
            throw new 
CreditCardException(CreditCardException::EmptyNumber);
        }
        if (
is_null($this->Type)) {
            throw new 
CreditCardException(CreditCardException::SetTypeFirst);
        }
        if (
preg_match("#([^0-9 \-\/\|\+])+#"$this->Number,  $arrMatch)) {
            throw new 
CreditCardException(CreditCardException::DisallowedCharacterInNumber$arrMatch[1]);
        }
        
// ok bad character test passed, let's clean it up
        
$this->SetNumber(preg_replace("#[^0-9]#"""$this->Number), false);
        
$arrAllowedLengths = (array)$this->arrTypes[$this->Type][self::Length];
        if (!
in_array(strlen($this->Number), $arrAllowedLengths)) {
            throw new 
CreditCardException(CreditCardException::WrongNumberLength$intLength$arrAllowedLengths);
        }
        
$blnPrefixFound false;
        
$arrPrefix = (array)$this->arrTypes[$this->Type][self::Prefix];
        foreach (
$arrPrefix as $strPrefix) {
            
            
$blnPrefixFound = (strpos($this->Number$strPrefix) === 0);
            if (
$blnPrefixFound) {
                break;
            }
        }
        if (!
$blnPrefixFound) {
            throw new 
CreditCardException(CreditCardException::WrongNumberPrefix$arrPrefix);
        }
        
$this->CheckDigit();
    }
    
    public function 
SetExpirationYear($strExpirationYear) {
        
$this->strOriginalExpirationYear $strExpirationYear;
        
$intExpirationYear = (int)$this->strOriginalExpirationYear;
        
$this->intExpirationFullYear = ($intExpirationYear 100) ? ($intExpirationYear 2000) : $intExpirationYear;
    }
    
    public function 
SetExpirationMonth($strExpirationMonth) {
        
$this->strOriginalExpirationMonth $strExpirationMonth;
        
$this->intExpirationMonth = (int)$this->strOriginalExpirationMonth;
    }
    
    protected function 
CheckExpirationDate() {
        if (
is_null($this->ExpirationFullYear)) {
            throw new 
CreditCardException(CreditCardException::CheckFailedExpirationFullYearUnset);
        }
        if (
is_null($this->ExpirationMonth)) {
            throw new 
CreditCardException(CreditCardException::CheckFailedExpirationMonthUnset);
        }
        if (
$this->ExpirationFullYear < @date("Y")) { // suppress E_STRICT timezone error
            
throw new CreditCardException(CreditCardException::Expired$this->ExpirationFullYear);
        }
        if (
$this->ExpirationFullYear > @date("Y") + 15) {
            throw new 
CreditCardException(CreditCardException::UnlikelyExpirationYear$this->ExpirationFullYear);
        }
        if (
$this->ExpirationMonth || $this->ExpirationMonth 12) {
            throw new 
CreditCardException(CreditCardException::InvalidExpirationMonth$this->ExpirationMonth);
        }
        if (
$this->ExpirationFullYear == @date("Y") && $this->ExpirationMonth < @date("n")) { // year check (for being smaller) is already done
            
throw new CreditCardException(CreditCardException::Expired, array($this->ExpirationFullYear$this->ExpirationMonth));
        }
    }
    
    public function 
SetCsc($strCsc) {
        
$this->strOriginalCsc $strCsc;
        
$this->strCsc = (string)trim($this->strOriginalCsc);
    }
    
    protected function 
CheckCsc() {
        throw new 
CreditCardException(CreditCardException::NotYetImplemented__METHOD__);
    }
    
    protected function 
CheckDigit() {
        
// external code
        
$checksum 0;                                  // running checksum total
        
$mychar "";                                   // next char to process
        
$j 1;                                         // takes value of 1 or 2
        
        // Process each digit one by one starting at the right
        
for ($i strlen($this->Number) - 1$i >= 0$i--) {
        
          
// Extract the next digit and multiply by 1 or 2 on alternative digits.      
          
$calc $this->Number{$i} * $j;
        
          
// If the result is in two digits add 1 to the checksum total
          
if ($calc 9) {
            
$checksum $checksum 1;
            
$calc $calc 10;
          }
        
          
// Add the units element to the checksum total
          
$checksum $checksum $calc;
        
          
// Switch the value of j
          
if ($j ==1) {$j 2;} else {$j 1;};
        } 
        
        
// All done - if checksum is divisible by 10, it is a valid modulus 10.
        // If not, report an error.
        
if ($checksum 10 != 0) {
         throw new 
CreditCardException(CreditCardException::CheckDigitFailed$checksum);
        }
    }
    
    protected function 
IsType($strType) {
        return 
in_array($strType$this->GetAllTypes());
    }
    
    protected function 
GetAllTypes() {
        if (empty(
$this->arrTypes)) {
            throw new 
CreditCardException(CreditCardException::NoTypesDefined);
        }
        
$arrTypesAbbrev = array();
        foreach (
$this->arrTypes as $arrType) {
            
$arrTypesAbbrev[] = $arrType[self::Abbrev];
        }
        return 
$arrTypesAbbrev;
    }
    
    protected function 
GetAllTypesNames() {
        
$arrNames = array();
        foreach (
$this->arrTypes as $arrType) {
            
$arrNames[] = $arrType[self::Name];
        }
        return 
$arrNames;
    }
    
    public function 
AllowAllTypes() {
        
$this->arrAllowedTypes array_keys($this->arrTypes);
    }
    
    public function 
AllowType() {
        
$arrArg func_get_args();
        for (
$i 0$x func_num_args(); $i $x; ++$i) {
            if (!
$this->IsType($arrArg[$i])) {
                throw new 
CreditCardException(CreditCardException::AllowingUnknownType$arrArg[$i], $this->GetAllTypes());
            }
            
$this->arrAllowedTypes[] = $arrArg[$i];
        }
    }
    
    public function 
GetTypeName() {
        return 
$this->arrTypes[$this->Type][self::Name];
    }
    
    protected function 
IsAllowedType() {
        return 
in_array($this->Type$this->GetAllowedTypes());
    }
    
    protected function 
GetAllowedTypes() {
        if (empty(
$this->arrAllowedTypes)) {
            throw new 
CreditCardException(CreditCardException::NoAllowedTypesDefined$this->GetAllTypes());
        }
        return 
$this->arrAllowedTypes;
    }
    
    protected function 
GetAllowedTypesNames() {
        
$arrNames = array();
        foreach (
$this->arrAllowedTypes as $strType) {
            
$arrNames[] = $this->arrTypes[$strType][self::Name];
        }
        return 
$arrNames;
    }
}

class 
CreditCardException extends Exception {
    const 
UndefinedSetProperty 1001;
    const 
UndefinedGetProperty 1002;
    const 
EmptyType 3;
    const 
UnknownType 4;
    const 
DisallowedType 5;
    const 
EmptyNumber 6;
    const 
SetTypeFirst 1007;
    const 
ValidateNumberMethodNotFound 1008;
    const 
Expired 9;
    const 
UnlikelyExpirationYear 10;
    const 
InvalidExpirationMonth 11;
    
//const SetExpirationYearFirst = 1012;
    
const EmptyCsc 13;
    const 
SetNumberFirst 1014;
    const 
ValidateCscMethodNotFound 1015;
    const 
NoTypesDefined 1016;
    const 
AllowingUnknownType 1017;
    const 
NoAllowedTypesDefined 1018;
    const 
UndefinedSetMethod 1019;
    const 
UndefinedGetMethod 1020;
    const 
NotYetImplemented 1021;
    const 
CheckFailedTypeUnset 1022;
    const 
CheckDigitFailed 23;
    const 
CheckFailedExpirationMonthUnset 1024;
    const 
CheckFailedExpirationFullYearUnset 1025;
    const 
WrongNumberPrefix 26;
    const 
WrongNumberLength 27;
    const 
CheckFailedNumberUnset 1028;
    const 
DisallowedCharacterInNumber 29;
    
    const 
NumberError 999;
    const 
DevelopmentError 1000// any error greater than this is an development error
    
    
protected $arrMessages = array(
        
self::UndefinedSetProperty => "Trying to set undefined property (%s), should be one of these: %s.",
        
self::UndefinedSetMethod => "Trying to call undefined setter method (%s) for property (%s), value (%s).",
        
self::UndefinedGetProperty => "Trying to get undefined property (%s), should be one of these: %s.",
        
self::UndefinedGetMethod => "Trying to call undefined getter method (%s) for property (%s).",
        
self::EmptyType => "The given credit card type must not be empty.",
        
self::UnknownType => "The given credit card type (%s) is unknown, only these are allowed: %s.",
        
self::DisallowedType => "The given credit card type (%s) is unfortunatelly not allowed, please choose one of these: %s.",
        
self::EmptyNumber => "The given credit card number must not be empty.",
        
self::SetTypeFirst => "Please set the credit card type first.",
        
self::ValidateNumberMethodNotFound => "Trying to call non-existing method (%s) to validate the credit card number by its credit card type (%s).",
        
self::Expired => "The given credit card expiration date (%s) has already been expired.",
        
self::UnlikelyExpirationYear => "The given credit card expiration year seem to be unlikely high and could not be accepted; please contact the support.",
        
self::InvalidExpirationMonth => "The given credit card expiration month (%s) is not valid (must be between 1 and 12).",
        
self::EmptyCsc => "The given card security code (CSC) must not be empty.",
        
self::SetNumberFirst => "Please set the credit card number first.",
        
self::ValidateCscMethodNotFound => "Trying to call non-existing method (%s) to validate the card's security code (CSC) by its credit card type (%s) and number (%s).",
        
self::NoTypesDefined => "There are no credit card types defined.",
        
self::AllowingUnknownType => "Trying to allow unknown credit card type (%s), please choose one of these: %s.",
        
self::NoAllowedTypesDefined => "There are no allowed credit card types defined, please choose at least one of these: %s.",
        
self::NotYetImplemented => "Trying to call not yet implemented method (%s).",
        
self::CheckFailedTypeUnset => "Checking credit card type failed, type is not set.",
        
self::CheckDigitFailed => "Checking credit card digit failed.",
        
self::CheckFailedExpirationMonthUnset => "Checking credit card month failed, month is not set.",
        
self::CheckFailedExpirationFullYearUnset => "Checking credit card year failed, year is not set.",
        
self::WrongNumberPrefix => "Checking prefix of credit card number failed, prefix is wrong, should be one of these: %s.",
        
self::WrongNumberLength => "Checking length of credit card number (%s) failed, should be this/one of these: %s)",
        
self::CheckFailedNumberUnset => "Checking credit card number failed, number is not set.",
        
self::DisallowedCharacterInNumber => "There are characters in your credit card number (%s) which are not allowed.",
        
        
self::NumberError => "The credit card number is not valid.",
        
self::DevelopmentError => "We are sorry - but an unexpected error occured while checking the credit card information; please contact the support.",
    );
    
    public function 
__construct($intCode) {
        
$arrArgs func_get_args();
        
array_shift($arrArgs); // remove first argument, $intCode
        
if (!empty($arrArgs)) {
            
// convert arrays into comma-separated string
            
foreach ($arrArgs as $i => $mixArg) {
                if (
is_array($mixArg)) {
                    
$arrArgs[$i] = implode(", "$mixArg);
                }
            }
            
$arrArgs array_merge($arrArgs); // reset array indexes
        
}
        
$strMessage vsprintf($this->arrMessages[$intCode], $arrArgs);
        
parent::__construct($strMessage$intCode);
    }
    
    public function 
__toString() {
        
$strMessage $this->GetMessage();
        if (
CreditCard::IsLiveMode()) {
            if (
$this->GetCode() > self::DevelopmentError) {
                
// don't show any development errors in live mode
                // please have a look at the error code, it still tells you what error occured
                
$strMessage $this->arrMessages[self::DevelopmentError]; // correct now
            
} else if (in_array($this->GetCode(), $this->GetCodesToMergeNumber())) {
                
$strMessage $this->arrMessages[self::NumberError];
            }
        } else {
            
$strMessage .= "\n\n" $this->GetTraceAsString();
        }
        return 
sprintf("(%u) %s"$this->GetCode(), $strMessage);
    }
    
    public function 
RenderHtml() {
        
printf('<div class="error-message">%s</div>'nl2br($this->__toString()));
    }
    
    protected function 
GetCodesToMergeNumber() {
        return array(
self::CheckDigitFailedself::WrongNumberPrefixself::WrongNumberLength);
    }
}
?>
Edit OK auch hier die Klassenkonstante umbenannt, sollte richtig sein.
Zergling-new ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 12.04.2008, 14:46  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 34.241
PHP-Kenntnisse:
Fortgeschritten
nikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz sein
Standard

Zitat:
habe mir soeben eine Klasse gebastelt
Reines understatement
nikosch ist offline   Mit Zitat antworten
Alt 09.05.2008, 07:15  
Erfahrener Benutzer
 
Registriert seit: 21.05.2008
Beiträge: 9.937
Zergling-new wird schon bald berühmt werden
Standard

Die Zeile scheint mir falsch zu sein:
PHP-Code:
<?php
$strMessage 
$this->arrMessages[self::DevelopError];
?>
Es muss wohl $this->arrMessages[self:evelopmentError]; heissen. Komisch, ich hatte die Methode eigentlich im Live und Test Status getestet.


Uebrigens kann man mit QCodo z.B. Kreditkarteninformationen super transparent verschluesseln:

Zitat:
Additionally, if you want to encrypt the credit card information in the database as well, just use these magic methods in your DataClass (not the generated one), f.e. UserBilling.class.php:

PHP-Code:
<?php
       
protected function getMcryptFields() {
           return array(
"CreditCardType""CreditCardNo""CreditCardExptDateTo");
       }

       public function 
__set($strProperty$strValue) {
           if (
in_array($strProperty$this->getMcryptFields()) && is_string($strValue)) {
                
$objMcrypt = new Mcrypt(__MCRYPT_SALT__);
                
$strValue $objMcrypt->encrypt($strValue);
           }
           return 
parent::__set($strProperty$strValue);
       }

       public function 
__get($strProperty) {
           if (
in_array($strProperty$this->getMcryptFields())) {
               
$strValue parent::__get($strProperty);
               if (
is_string($strValue)) {
                   
$objMcrypt = new Mcrypt(__MCRYPT_SALT__);
                   return 
$objMcrypt->decrypt($strValue);
               }
               return 
$strValue;
           }
           return 
parent::__get($strProperty);
       }
?>
Encrypting/Decrypting is now done implicitly. Please define the __MCRYPT_SALT__ in the configuration.inc.php and don't change it, otherwise you can not recover the data. Mcrypt uses the mcrypt php extension and I think Blowfish as algorithm.
Die Mcrypt-Klasse findet sich hier (ich find sie hier im Forum leider nicht mehr):
PHP-Code:
<?php
/** 
 * @desc
 * This class provides encrypting and decrypting functionality using the mcrypt extension of php. 
 * 
 * @author     Christian Reinecke <christian.reinecke@web.de>
 * @version    1.0
 * @see        [url]http://php.net/mcrypt[/url]
 * 
 * @example
 * <code>
 * define("MY_PRIVATE_KEY", "V^U^&Kbvw5ywcWHkjKkcw32");
 * $mcrypt = new Mcrypt(MY_PRIVATE_KEY);
 * 
 * $plainCreditCardNo = "Did you know my credit card number? It's 1234-5678-9010-1112!";
 * printf("Plain: %s
", $plainCreditCardNo);
 * 
 * $encryCreditCardNo = $mcrypt->encrypt($plainCreditCardNo);
 * printf("Encrypted: %s
", $encryCreditCardNo);
 * 
 * $decryCreditCardNo = $mcrypt->decrypt($encryCreditCardNo);
 * printf("Decrypted: %s
", $decryCreditCardNo);
 *
 * printf("Restored: %u
", strcasecmp($plainCreditCardNo, $decryCreditCardNo) === 0);
 * printf("Data amount: +%d%%
", (strlen($encryCreditCardNo)/strlen($plainCreditCardNo)) * 100 - 100);
 * </code>
 */ 
class Mcrypt
{
    
/**
     * @desc maximum key (or salt) length for the private key
     * @var int
     */
    
const KeyMinLength 10;
    const 
KeyMaxLength 56// mcrypt demand
    
    /**
     * @desc salt used to fill the private key to a total length of 56 characters (if necessary)
     * @var string
     * @warning
     * - NEVER CHANGE THIS VALUE ON A RUNNING SYSTEM,
     *   because it's part of the encryption key and if changed, old data can not be restored.
     * - Also make sure to store this key in another place, f.e. dotProject.
     * - Do not use special chars here, US-ANSI (ASCII 128) only (to avoid problems on charset conversions) 
     */
    
const SaltPad '#89767bgxdrfpn4^N%KBRVJH$#%I ^N:LM(){NV CQX-][":.7n36F;-';
    
    
/**
     * @desc some mcrypt required variable
     */
    
private $_td;
    
/**
     * @desc some mcrypt required variables
     * @warning
     * NEVER CHANGE THIS VALUES ON A RUNNING SYSTEM,
     * because the encryption key is based on these information snf if changed, old data can not be restored.
     */
    
private $_cypher MCRYPT_BLOWFISH;
    private 
$_mode   MCRYPT_MODE_CFB;
    
    
/**
     * @desc private key for your application
     */
    
private $_key null;
    

    
/**
     * constructor which expects the private key as first parameter
     * @throws McryptException
     * @params $key string private key 
     */
    
public function __construct($key)
    {
        if (!
extension_loaded("mcrypt")) {
            throw new 
McryptException(McryptException::McryptExtensionNotFound);
        }
        
$this->_td mcrypt_module_open($this->_cypher''$this->_mode'');
        
$this->_setKey($key);
    }

    
/**
     * @desc enrypt your plaintext with this method, the return value is the encrypted string
     * @throws McryptException
     * @param $plaintext string plaintext value
     * @return string encrypted, base64-encoded data (increases the data amount, but uses ASCII charachters)
     */
    
public function encrypt($plaintext)
    {
        if (
is_null($this->_key)) {
            throw new 
McryptException(McryptException::NoKeySet);
        }
        
$iv mcrypt_create_iv(mcrypt_enc_get_iv_size($this->_td), MCRYPT_RAND);
        
mcrypt_generic_init($this->_td$this->_key$iv);
        
$crypttext mcrypt_generic($this->_td$plaintext);
        
mcrypt_generic_deinit($this->_td);
        return 
base64_encode($iv $crypttext);
    }

    
/**
     * @desc decrypt your encrypted data with this method, the return value is the plaintext string
     * @throws McryptException
     * @param $crypttext string encrypted value
     * @return string plaintext
     */
    
public function decrypt($crypttext)
    {
        if (
is_null($this->_key)) {
            throw new 
McryptException(McryptException::NoKeySet);
        }
        
$crypttext base64_decode($crypttext);
        
$ivsize mcrypt_get_iv_size($this->_cypher$this->_mode);
        
$iv substr($crypttext0$ivsize);
        
$crypttext substr($crypttext$ivsize);
        
mcrypt_generic_init($this->_td$this->_key$iv);
        
$plaintext mdecrypt_generic($this->_td$crypttext);
        
mcrypt_generic_deinit($this->_td);
        return 
$plaintext;
    }

    
/**
     * @desc close mcrypt module, do not call manually
     */
    
public function __destruct()
    {
        
mcrypt_module_close($this->_td);
    }
    
    
/**
     * @param $key string private key
     */
    
private function _setKey($key)
    {
        if (
strlen($key) < self::KeyMinLength) {
            throw new 
McryptException(McryptException::KeyTooShort, array(self::KeyMinLengthstrlen($key)));
        } else if (
strlen($key) > self::KeyMaxLength) {
            throw new 
McryptException(McryptException::KeyTooLong, array(self::KeyMaxLengthstrlen($key)));
        }
        
$this->_key substr($key self::SaltPad0self::KeyMaxLength);
    }
}

/** 
 * @desc
 * This class is the exception class for the Mcrypt class. 
 * 
 * @author     Christian Reinecke <christian.reinecke@web.de>
 * @version    1.0
 * @see        [url]http://php.net/mcrypt[/url]
 * @see        [url]http://php.net/exceptions[/url]
 */ 
class McryptException extends Exception {
    const 
NoKeySet 1;
    const 
KeyTooShort 2;
    const 
KeyTooLong 3;
    const 
McryptExtensionNotFound 4;
    
    protected 
$messages = array(
        
self::NoKeySet => "You must set the private key before encrypting or decrypting data.",
        
self::KeyTooShort => "The private key must have a minimum of %u characters (the given one has just %u).",
        
self::KeyTooLong => "The private key must have a maximum of %u characters (the given one has %u).",
        
self::McryptExtensionNotFound => "The mcrypt extension is not installed on this system.");
    
    public function 
__construct($intCode$variables = array()) {
        
$message vsprintf($this->messages[$intCode], $variables);
        
parent::__construct($message$intCode);
    }
    
    public function 
IsCode($intCode) {
        return 
$this->GetCode() == $intCode;
    }
}
?>
Edit OK die Bedingung konnte nie wahr sein, die extension_loaded() Abfrage ist jetzt korrigiert und funktioniert auch.
Zergling-new ist offline   Mit Zitat antworten
Alt 18.05.2011, 11:15  
Neuer Benutzer
 
Registriert seit: 18.05.2011
Beiträge: 8
PHP-Kenntnisse:
Anfänger
erdbeereis6 ist zur Zeit noch ein unbeschriebenes Blatt
Standard

Suche so etwas auch. Aber funktioniert das nun oder nicht?

Geändert von Asipak (24.05.2011 um 17:17 Uhr). Grund: Signatur entfernt (unerwünschte Werbung)
erdbeereis6 ist offline   Mit Zitat antworten
Alt 18.05.2011, 11:48  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.069
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Probiers aus
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

LinkBacks (?)
LinkBack to this Thread: http://www.php.de/tutorials/45785-php-kreditkartenvalidierung.html
Erstellt von For Type Datum
Visa Kreditkartennummer - (blumenstrauss.de) This thread Refback 16.04.2010 01:45
mycrypt fehlerzeichen - Forum: phpforum.de This thread Refback 14.03.2009 21:09
mycrypt fehlerzeichen - Forum: phpforum.de This thread Refback 14.03.2009 18:34
xml mit php verschluesseln? - Forum: phpforum.de This thread Refback 21.01.2009 22:21
xml mit php verschluesseln? - Forum: phpforum.de This thread Refback 21.01.2009 21:43

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
kreditkartenvalidierung, kreditkarte validieren, prüfsumme kreditkarte, kreditkartennummer validieren php, kreditkarte prüfsumme, kreditkartennummer validieren, kreditkarten validierung php, kreditkarte validieren php, prüfsumme mastercard, kreditkarten prüfsumme, php kreditkarten-check, http://www.php.de/tutorials/45785-php-kreditkartenvalidierung.html, kreditkartenvalidierung php, mc card security code, kreditkarten validierung, info.de@mccardsecurity.com, php kreditkartennummer check, kreditkarte php validierung, php kreditkarte, cannot set property \'value\' of undefined

Alle Zeitangaben in WEZ +1. Es ist jetzt 11:12 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum

Creative Commons License
Dieser Inhalt ist unter einer Creative Commons-Lizenz lizenziert.