Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/mvc/components/cc

[return to app]
1 <?php
2
/**
3  * Credit Card functions
4  */
5
class ccComponent {
6     
/**
7      * These properties store the response from AuthorizeNet after a charge
8      *
9      * @var string
10      */
11     
public $authnetResponse$authnetResponseText$authnetApprovalCode$authnetTransactionId;
12
13     
/**
14      * Every second digit in the Mod 10 (Luhn) algorithm gets doubled and then the resulting digit(s) are added
 
together
15      
This array maps the orignal number to the digit after the Mod 10 equation
16      
*/
17     protected 
$_mod10digits = array(=> 0=> 2=> 4=> 6=> 8=> 1=> 3=> 5=> 7=>
 
9);
18
19     
/**
20      * Standard credit card test numbers; these will validate Mod 10 but are never valid credit card accounts
21      *
22      * @var array
23      */
24     
public $ccTestNumbers = array(5105105105105100555555555555444442222222222224111111111111111,
25                                   
4012888888881881378282246310005371449635398431378734493671000,
26                                   
385200000232373056930902590460111111111111176011000990139424,
27                                   
35301113333000003566002020360505);
28
29     
/**
30      * Credit card types; keys mapped to the AuthorizeNet card type response
31      *
32      * @var array
33      */
34     
public $cardTypes = array(=> 'Visa'=> 'MasterCard'=> 'American Express'=> 'Discover Card',
35                               
=> 'Diners Club'=> 'JCB (Japanese Credit Bureau)'=> 'Australian
 BankCard'
,
36                               
=> 'enRoute');
37
38     
/**
39      * Validates the length of credit card number is correct for the card type
40      *
41      * @param int $cc
42      * @param int $cardType This must match the key from the $this->cardTypes array
43      * @return boolean
44      */
45     
public function isValidCcLength($cc$cardType) {
46         
$length[16] = array(14567); //JCB, Visa, MasterCard, Discover Card, Australian BankCard
47         
$length[15] = array(123); //JCB, enRoute, American Express
48         
$length[14] = array(8); //Diners Club
49         
$length[13] = array(4); //Visa
50         
$ccLength strlen($cc);
51         return (isset(
$length[$ccLength]) && in_array($cardType$length[$ccLength]));
52     }
53
54     
/**
55      * Flag set by $this->getCardType() if a Diners Club card is a CarteBlanch card
56      *
57      * @var boolean
58      */
59     
public $isCarteBlanch;
60
61     
/**
62      * Determines credit card type by the credit card number
63      *
64      * @param int $cc Can be the first four digits of the credit card number, the entire number or anything in
 
between
65      
* @return int Matches the keys in $this->cardTypes
66      
*/
67     public function 
getCardType($cc$returnHumanReadable true) {
68         
$cardType 0;
69         
$prefix substr($cc04);
70         if (
$prefix >= 4000 && $prefix <= 4999) {
71            
$cardType 4//Visa
72         
} else if ($prefix >= 5100 && $prefix <= 5599) {
73            
$cardType 5//MasterCard
74         
} else if (($prefix >= 3400 && $prefix <= 3499) || ($prefix >= 3700 && $prefix <= 3799)) {
75            
$cardType 3//American Express
76         
} else if (($prefix >= 3000 && $prefix <= 3059) || ($prefix >= 3600 && $prefix <= 3699)
77                    || (
$prefix >= 3800 && $prefix <= 3899)) {
78            
$cardType 8//Diners Club
79            
$this->isCarteBlanch = ($prefix >= 3890 && $prefix <= 3899);
80         } else if (
$prefix >= 3528 && $prefix <= 3589) {
81            
$cardType 1//JCB
82         
} else {
83             switch (
$prefix) {
84                 case 
6011:
85                     
$cardType 6//Discover Card
86                     
break;
87                 case 
1800:
88                 case 
2131:
89                     
$cardType 1//JCB
90                     
break;
91                 case 
2014:
92                 case 
2149:
93                     
$cardType 2//enRoute
94                     
break;
95                 case 
5610:
96                     
$cardType 7//Australian BankCard
97                     
break;
98             }
99         }
100         if (
$cardType && $returnHumanReadable && isset($this->cardTypes[$cardType])) {
101             
$cardType $this->cardTypes[$cardType];
102         }
103         return 
$cardType;
104     }
105
106     
/**
107      * Verifies if a credit card number passes the Mod 10 specification
108      *
109      * @param int $cc
110      * @return boolean
111      */
112     
public function isMod10Valid($cc) {
113         
$cclen strlen($cc);
114         if (
$cclen 16 || $cclen 13 || !is_numeric($cc)) {
115             return 
false;
116         }
117         
$digitsum 0;
118         
$currentbit 1;
119         
$startbit = ($cclen 2);
120             for (
$x 0$x $cclen$x++) {
121                 
$currentbit =! $currentbit;
122                 if (
$currentbit == $startbit) {
123                     
$cc[$x] = $this->_mod10digits[$cc[$x]];
124                 }
125                 
$digitsum += $cc[$x];
126             }
127         return (boolean) !(
$digitsum 10);
128     }
129
130     
/**
131      * Charges a credit card through AuthorizeNet and records meta data in properties:
132      * $this->authnetResponse, $this->authnetResponseText, $this->authnetApprovalCode and
 
$this->authnetTransactionId
133      
*
134      * 
Requires AUTHNET_LOGIN and AUTHNET_PASSWORD to be set in the .config
135      
*
136      * @
param float $amount
137      
* @param int $cc
138      
* @param string $exp
139      
* @return int 1=approved2=declined3=error
140      
*/
141     public function 
chargeAuthNet($amount$cc$exp) {
142         
$postfields = array('x_login' => get::$config->AUTHNET_LOGIN,
143                             
'x_password' => get::$config->AUTHNET_PASSWORD,
144                             
'x_version' => '3.1',
145                             
'x_delim_data' => 'TRUE',
146                             
'x_method' => 'CC',
147                             
'x_type' => 'AUTH_CAPTURE',
148                             
'x_customer_ip' => $_SERVER['REMOTE_ADDR'],
149                             
'x_amount' => $amount,
150                             
'x_card_num' => $cc,
151                             
'x_exp_date' => $exp);
152
153         
$postdata http_build_query($postfields);
154         
$sockheader 'POST /gateway/transact.dll HTTP/1.0' PHP_EOL
155                     
'Host: secure.authorize.net' PHP_EOL
156                     
'Content-type: application/x-www-form-urlencoded' PHP_EOL
157                     
'Content-length: ' strlen($postdata) . PHP_EOL
158                     
'Accept: */*';
159
160         
$fp stream_socket_client('ssl://secure.authorize.net:443'$errno$errstr30);
161         
fwrite($fp$sockheader PHP_EOL PHP_EOL $postdata PHP_EOL PHP_EOL);
162         while(
trim(fgets($fp128)));
163         
//error-suppression is needed for connecting to older IIS servers that do not close the connection
 properly
164         
$responsestring = @fgets($fp);
165         
fclose($fp);
166
167         
$this->authnetResponse explode(','$responsestring);
168         
$this->authnetResponseText $this->authnetResponse[3];
169         
$this->authnetApprovalCode $this->authnetResponse[4];
170         
$this->authnetTransactionId $this->authnetResponse[6];
171         return 
$this->authnetResponse[0];
172     }
173
174     
/**
175      * Redirect a user to a Google Payment checkout prepopulated with their order (& directing payment to your
 
account)
176      *
177      * @
param array $items
178      
*/
179     public function 
redirectToGoogleCheckout(array $items) {
180         
$data '<?xml version="1.0" encoding="UTF-8"?>
181 <checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">
182     <shopping-cart>
183         <items>'
;
184         foreach (
$items as $item) {
185             
$currency = (!isset($item['currency']) ? 'USD' $item['currency']);
186             
$data .= '
187             <item>
188                 <item-name>' 
$item['name'] . '</item-name>
189                 <item-description>' 
$item['description'] . '</item-description>
190                 <unit-price currency="' 
$currency '">' $item['price'] . '</unit-price>
191                 <quantity>' 
. (!isset($item['quantity']) ? $item['quantity']) . '</quantity>
192             </item>'
;
193         }
194         
$data .= '
195         </items>
196     </shopping-cart>
197     <checkout-flow-support>
198         <merchant-checkout-flow-support/>
199     </checkout-flow-support>
200 </checkout-shopping-cart>
201 '
;
202         if (!
get::$config->GOOGLE_CHECKOUT['useSandbox']) {
203             
$credentials get::$config->GOOGLE_CHECKOUT['live'];
204             
$url 'checkout.google.com/api/checkout/v2/request/Merchant/';
205         } else {
206             
$credentials get::$config->GOOGLE_CHECKOUT['sandbox'];
207             
$url 'sandbox.google.com/checkout/api/checkout/v2/request/Merchant/';
208         }
209         
$url 'https://' $credentials['id'] . ':' $credentials['key'] . '@' $url $credentials['id'];
210         
$errorLevel error_reporting(E_ERROR);
211         
$xml get::component('post')->postRequest($url$data);
212         
error_reporting($errorLevel);
213         if (
$xml) {
214             
$url trim(html_entity_decode(strip_tags($xml)));
215             
load::redirect($url);
216         } else {
217             
error_log('No Google Payment URL returned from: ' $data);
218         }
219     }
220 }