Creating a Credit Card Validation Class With PHP

Hi,
I have completed this tutorial and I keep getting this error:

Fatal error: Call to a member function Type() on a non-object in /home/content/47/4912147/html/LIYDS/orderform.php on line 172

I even copied your code exactly and when I run that I don’t get the error but it does not print out the credit card info. The information just disappears from the form fields.

Can you tell me what I am doing wrong?

Thanks!

Here is my version of your code:

<?php //Validate credit card numbers.

define(‘CARD_TYPE_MC’, 0);
define(‘CARD_TYPE_VS’, 0);
define(‘CARD_TYPE_AX’, 0);
define(‘CARD_TYPE_DC’, 0);
define(‘CARD_TYPE_DS’, 0);
define(‘CARD_TYPE_JC’, 0);

class CCreditCard { //Class members.
var $__ctype = ‘’;
var $__cname = ‘’;
var $__cnumb = ‘’;
var $__scode = 0;
var $__xmonth = 0;
var $__xyear = 0;

//Constructor
function CCreditCard ($name, $type, $numb, $expm, $expy) {
	//Set member variables
	if(!empty($name)){
		$this-&gt;__cname = $name;
	}else {
		die('Must pass a name to the constructor');
	}//end IF ELSE statement

	//Make sure card type is valid
	switch(strtolower($type)) {
		case 'mc':
		case 'mastercard':
		case 'm':
		case '1':
			$this-&gt;__ctype = CARD_TYPE_MC;
			break;
		case 'vs':
		case 'visa':
		case 'v':
		case '2':
			$this-&gt;__ctype = CARD_TYPE_VS;
			break;
		case 'ax':
		case 'americanexpress':
		case 'a':
		case '3':
			$this-&gt;__ctype = CARD_TYPE_AX;
			break;
		case 'dc':
		case 'dinersclub':
		case '4':
			$this-&gt;__ctype = CARD_TYPE_DC;
			break;
		case 'ds':
		case 'discover':
		case '5':
			$this-&gt;__ctype = CARD_TYPE_DS;
			break;
		case 'jc':
		case 'jcb':
		case '6':
			$this-&gt;__ctype = CARD_TYPE_JC;
			break;
		default:
			die('Invalid Type '.$type.' passed to constructor.');
			break;
	}//end switch

	// Don't check the number yet,
	// just kill all non numerics
	if(!empty($numb)) {
		$cardNumber = ereg_replace("[^0-9]", "", $numb);
	
		//Make sure the card number is not empty
		if(!empty($cardNumber)) {
			$this-&gt;__cnumb = $cardNumber;
		}else {
			die('Must pass number to the constructor');
		}//end nested IF statement
	}//end IF statement

	//Make sure expiration date is valid
	if(!is_numeric($expm) || $expm &lt; 1 || $expm &gt; 12) {
		die('Invalid expiration month of ' . $expm . ' passed to constructor');
	}else {
		$this-&gt;__xmonth = $expm;
	}//end IF ELSE statement

	//Get the current year
	$currentYear = date('Y');
	settype($currentYear, 'integer');

	if(!is_numeric($expy) || $expy &lt; $currentYear || $expy &gt; ($currentYear + 10)) {
		die('Invalid expiration year of ' . $expy . ' passed to constructor');
	}else {
		$this-&gt;__xyear = $expy;
	}//end IF ELSE statement
}//end function

function Name() {
	return $this-&gt;__cname;
}//end function

function Type() {
	switch($this-&gt;__ctype) {
		case CARD_TYPE_MC:
			return 'Mastercard [1]';
			break;
		case CARD_TYPE_VS:
			return 'Visa [2]';
			break;
		case CARD_TYPE_AX:
			return 'Amex [3]';
			break;
		case CARD_TYPE_DC:
			return 'Dclub [4]';
			break;
		case CARD_TYPE_DS:
			return 'Discover [5]';
			break;
		case CARD_TYPE_JC:
			return 'JCB [6]';
			break;
		default:
			return 'Unknown [-1]';
	}//end switch
}//end function

function Number() {
	return $this-&gt;__cnumb;
}//end function

function Xmonth() {
	return $this-&gt;__xmonth;
}//end function

function Xyear() {
	return $this-&gt;__xyear;
}//end function
	
function SafeNumber($char = 'x', $numToHide = 4) {
	//Return only part of the number
	if($numToHide &lt; 4) {
		$numToHide = 4;
	}//end IF statement
	
	if($numToHide &gt; 10) {
		$numToHide = 10;
	}//end IF statement
	
	$cardNumber = $this-&gt;__cnumb;
	$cardNumber = substr($cardNumber, 0, strlen($cardNumber) - $numToHide);
	
	for($i=0;$i &lt; $numToHide;$i++) {
		$cardNumber .= $char;
	}//end FOR loop
	
	return $cardNumber;
}//end function

function isValid() {
	//Not valid by default
	$validFormat = false;
	$passCheck = false;
	
	//Is the number in the correct format?
	switch($this-&gt;__ctype) {
		case CARD_TYPE_MC:
			$validFormat = ereg("^5[1-5][0-9]{14}$", $this-&gt;__cnumb);
			break;
		case CARD_TYPE_VS:
			$validFormat = ereg("^4[0-9]{12}([0-9]{3})?$", $this-&gt;__cnumb);
			break;
		case CARD_TYPE_AX:
			$validFormat = ereg("^3[47][0-9]{13}$", $this-&gt;__cnumb);
			break;
		case CARD_TYPE_DC:
			$validFormat = ereg("^3(0[0-5]|[68][0-9])[0-9]{11}$", $this-&gt;__cnumb);
			break;
		case CARD_TYPE_DS:
			$validFormat = ereg("^6011[0-9]{12}$", $this-&gt;__cnumb);
			break;
		case CARD_TYPE_JC:
			$validFormat = ereg("^(3[0-9]{4}|2131|1800)[0-9]{11}$", $this-&gt;__cnumb);
			break;
		default:
			//Should never be executed
			$validFormat = false;
	}//end switch
	
	//Is the number valid?
	$cardNumber = strrev($this-&gt;__cnumb);
	$numSum = 0;
	
	for($i=0;$i &lt; $strlen($cardNumber);$i++) {
		$currentNum = substr($cardNumber, $i, 1);
		
		//Double every second number
		if($i % 2 == 1) {
			$currentNum *= 2;
		}//end IF statement
		
		//Add digits of 2-digit numbers together
		if($currentNum &gt; 9) {
			$firstNum = $currentNum % 10;
			$secondNum = ($currentNum -  $firstNum) / 10;
			$currentNum = $firstNum + $secondNum;
		}//end IF statement
		
		$numSum += $currentSum;
	}//end FOR loop
	
	// If the total has no remainder it's OK      
	$passCheck = ($numSum % 10 == 0);
	
	if($validFormat && $passCheck) {
		return true; 
	}else {
		return false;		
	}//end IF ELSE statement
}//end function	

}//Class ends
?>

Correction! It works now, however there is still one problem. I still get the error message, it just displays before the credit card info is submitted. When the page loads its there waiting for me. lol

I tried putting this “<?=$cc->@Name(); ?>” and that does not hide the error message.

Any suggestions?

Very good article - although, I have one recommendation. I would change the SafeNumber() function to something like this:

// function SafeNumber();
function SafeNumber(){
  // mask all numbers with "x" aside from the last 4
  $cn=$this-&gt;__ccNum;
  $numLen=strlen($cn);
  $safeNumber=str_repeat("x",$numLen-4);
  $safeNumber.=$cn[$numLen-4].$cn[$numLen-3].$cn[$numLen-2].$cn[$numLen-1];
  return $safeNumber;
}

Other than that, good on ya mango pie. Enjoyed it thoroughly.