Files
IPB/applications/nexus/sources/CreditCard/CreditCard.php
T
2025-12-19 05:38:56 -08:00

177 lines
4.0 KiB
PHP

<?php
/**
* @brief Credit card object
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Community Suite
* @subpackage Nexus
* @since 10 Mar 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\nexus;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Credit card object
*/
class _CreditCard
{
/**
* @brief Card Number
*/
public $number;
/**
* @brief Last 4 numbers
*/
public $lastFour;
/**
* @brief Type
*/
const TYPE_VISA = 'visa';
const TYPE_MASTERCARD = 'mastercard';
const TYPE_DISCOVER = 'discover';
const TYPE_AMERICAN_EXPRESS = 'american_express';
const TYPE_DINERS_CLUB = 'diners_club';
const TYPE_JCB = 'jcb';
public $type;
/**
* @brief Expire Month
*/
public $expMonth;
/**
* @brief Expire Year
*/
public $expYear;
/**
* @brief Security Code
*/
public $ccv;
/**
* @brief Save
*/
public $save;
/**
* Constructor
*
* @return void
*/
public function __construct() {}
/**
* Create object
*
* @param string $cardNumber Card Number
* @param int|string $expMonth Expire month
* @param int|string $expYear Expire year
* @param int|string $ccv Security Code
* @param bool $save If the card should be saved
* @return void
* @throws \InvalidArgumentException Card number or expiry date is invalid
* @throws \DomainException Expire date is in the past
*/
public static function build( $cardNumber, $expMonth, $expYear, $ccv, $save=FALSE )
{
$obj = new static;
/* Work out card type */
$cardNumber = str_replace( array( ' ', '-' ), '', $cardNumber );
$obj->number = $cardNumber;
if ( preg_match( '/^4[0-9]{12}(?:[0-9]{3})?$/', $cardNumber ) )
{
$obj->type = static::TYPE_VISA;
}
elseif ( preg_match( '/^5[1-5][0-9]{14}$/', $cardNumber ) or /* Maestro */ preg_match( '/^(?:5[0678]\d\d|6304|6390|67\d\d)\d{8,15}$/', $cardNumber ) )
{
$obj->type = static::TYPE_MASTERCARD;
}
elseif ( preg_match( '/^3[47][0-9]{13}$/', $cardNumber ) )
{
$obj->type = static::TYPE_AMERICAN_EXPRESS;
}
elseif ( preg_match( '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', $cardNumber ) )
{
$obj->type = static::TYPE_DINERS_CLUB;
}
elseif ( preg_match( '/^6(?:011|5[0-9]{2})[0-9]{12}$/', $cardNumber ) )
{
$obj->type = static::TYPE_DISCOVER;
}
elseif ( preg_match( '/^(?:2131|1800|35\d{3})\d{11}$/', $cardNumber ) )
{
$obj->type = static::TYPE_JCB;
}
else
{
throw new \InvalidArgumentException('card_number_invalid');
}
$obj->lastFour = mb_substr( $cardNumber, -4 );
/* Check it with the Luhn algorithm */
$sumTable = array(
array(0,1,2,3,4,5,6,7,8,9),
array(0,2,4,6,8,1,3,5,7,9)
);
$sum = 0;
$flip = 0;
$cardNumberLength = \strlen( $cardNumber );
for ($i = $cardNumberLength - 1; $i >= 0; $i--)
{
$sum += $sumTable[ $flip++ & 0x1 ][ $cardNumber[ $i ] ];
}
if( $sum % 10 !== 0 )
{
throw new \InvalidArgumentException('card_number_invalid');
}
/* Check the expiry date */
$expMonth = intval( $expMonth );
if ( $expMonth < 0 or $expMonth > 12 )
{
throw new \InvalidArgumentException('card_month_invalid');
}
$obj->expMonth = str_pad( $expMonth, 2, '0', STR_PAD_LEFT );
$obj->expYear = intval( $expYear );
if ( mktime( 0, 0, 0, $expMonth, 1, $expYear ) < time() )
{
throw new \DomainException;
}
/* Check the security code */
$obj->ccv = $ccv;
if ( $obj->type === static::TYPE_AMERICAN_EXPRESS )
{
if ( mb_strlen( $ccv ) !== 4 )
{
throw new \InvalidArgumentException('ccv_invalid_4');
}
}
elseif ( mb_strlen( $ccv ) !== 3 )
{
throw new \InvalidArgumentException('ccv_invalid_3');
}
/* Should it be saved? */
if ( $save )
{
$obj->save = $save;
}
return $obj;
}
}