Source for file AuthorizeNet.php
Documentation is available at AuthorizeNet.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
* Authorize.Net processor
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* @package Payment_Process
* @author Joe Stump <joe@joestump.net> |
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
* @copyright 1997-2008 The PHP Group
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: AuthorizeNet.php 267241 2008-10-12 19:37:31Z jausions $
* @link http://pear.php.net/package/Payment_Process
require_once 'Payment/Process.php';
require_once 'Payment/Process/Common.php';
require_once 'Net/Curl.php';
* Defines global variables
$GLOBALS['_Payment_Process_AuthorizeNet'] = array (
* Payment_Process_AuthorizeNet
* This is a processor for Authorize.net's merchant payment gateway.
* (http://www.authorize.net/)
* This is BETA code, and has not been fully tested. It is not recommended
* that you use it in a production environment without further testing.
* @package Payment_Process
* @author Joe Stump <joe@joestump.net>
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
* @link http://www.authorize.net/
* Front-end -> back-end field map.
* This array contains the mapping from front-end fields (defined in
* the Payment_Process class) to the field names Authorize.Net requires.
'password' => 'x_password',
'invoiceNumber' => 'x_invoice_num',
'customerId' => 'x_cust_id',
'description' => 'x_description',
'company' => 'x_company',
'address' => 'x_address',
'country' => 'x_country',
* @author Joe Stump <joe@joestump.net>
'firstName' => 'x_first_name',
'lastName' => 'x_last_name',
'cardNumber' => 'x_card_num',
'expDate' => 'x_exp_date'
'routingCode' => 'x_bank_aba_code',
'accountNumber' => 'x_bank_acct_num',
'type' => 'x_bank_acct_type',
'bankName' => 'x_bank_name'
* Default options for this processor.
* @see Payment_Process::setOptions()
var $_defaultOptions = array (
'authorizeUri' => 'https://secure.authorize.net/gateway/transact.dll',
'x_delim_data' => 'TRUE',
'x_email_customer' => 'FALSE',
'x_currency_code' => 'USD',
* List of possible encapsulation characters
var $_encapChars = '|~#$^*_=+-`{}![]:";<>?/&';
* Has the transaction been processed?
* The response body sent back from the gateway.
* @param array $options Class options to set.
* @see Payment_Process::setOptions()
$this->_driver = 'AuthorizeNet';
$this->_makeRequired ('login', 'password', 'action');
* Processes the transaction.
* Success here doesn't mean the transaction was approved. It means
* the transaction was sent and processed without technical difficulties.
* @return mixed Payment_Process_Result on success, PEAR_Error on failure
if (PEAR ::isError ($result)) {
$result = $this->_prepare ();
if (PEAR ::isError ($result)) {
$fields = $this->_prepareQueryString ();
if (PEAR ::isError ($fields)) {
// Don't die partway through
PEAR ::pushErrorHandling (PEAR_ERROR_RETURN );
$curl = & new Net_Curl ($this->_options['authorizeUri']);
if (PEAR ::isError ($curl)) {
PEAR ::popErrorHandling ();
$result = $curl->create ();
if (PEAR ::isError ($result)) {
PEAR ::popErrorHandling ();
$curl->userAgent = 'PEAR Payment_Process_AuthorizeNet @package_version@';
if (isset ($this->_options['curl_options'])) {
foreach ($this->_options['curl_options'] as $key => $value) {
if (!$curl->setOption ($key, $value)) {
PEAR ::popErrorHandling ();
return PEAR ::raiseError (" Curl option ($key = $value) failed" );
$result = $curl->execute ();
if (PEAR ::isError ($result)) {
PEAR ::popErrorHandling ();
$this->_responseBody = trim($result);
$this->_processed = true;
// Restore error handling
PEAR ::popErrorHandling ();
if (!PEAR ::isError ($response)) {
$r = $response->isLegitimate ();
} elseif ($r === false ) {
return PEAR ::raiseError ('Illegitimate response from gateway');
$response->action = $this->action;
* Processes a callback from payment gateway
* Success here doesn't mean the transaction was approved. It means
* the callback was received and processed without technical difficulties.
* @return mixed Payment_Process_Result on success, PEAR_Error on failure
$this->_responseBody = $_POST;
$this->_processed = true;
if (!PEAR ::isError ($response)) {
$response->_request = & $this;
$response->parseCallback ();
$r = $response->isLegitimate ();
} elseif ($r === false ) {
return PEAR ::raiseError ('Illegitimate callback from gateway.');
* Get (completed) transaction status.
* @return string Two-digit status returned from gateway.
* Prepare the POST query string.
* You will need PHP_Compat::str_split() if you run this processor
* @return string The query string
function _prepareQueryString ()
// Set payment method to eCheck if our payment type is eCheck.
// Default is Credit Card.
$data['x_method'] = 'CC';
if ($this->_payment->getType () == 'eCheck') {
$data['x_method'] = 'ECHECK';
$data['x_bank_acct_type'] = 'CHECKING';
$data['x_bank_acct_type'] = 'SAVINGS';
// Keep a trace of characters we will get back
// so we can set an appropriate encapsulation character
foreach ($data as $key => $val) {
if (substr($key, 0 , 2 ) == 'x_'
&& $key != 'x_encap_char'
// Find an appropriate encapsulation character
$encap = $data['x_encap_char']{0 };
$this->_options['x_encap_char'] = $encap;
* If it's an eCheck we need to combine firstName and lastName into a
* @author Joe Stump <joe@joestump.net>
if ($this->_payment->getType () == 'eCheck') {
$this->_data['x_bank_acct_name'] = $this->_payment->firstName. ' '. $this->_payment->lastName;
var $_statusCodeMap = array ('1' => PAYMENT_PROCESS_RESULT_APPROVED ,
'2' => PAYMENT_PROCESS_RESULT_DECLINED ,
'3' => PAYMENT_PROCESS_RESULT_OTHER ,
'4' => PAYMENT_PROCESS_RESULT_REVIEW
* AuthorizeNet status codes
* This array holds many of the common response codes. There are over 200
* response codes - so check the AuthorizeNet manual if you get a status
* code that does not match (see "Response Reason Codes & Response
* Reason Text" in the AIM manual).
var $_statusCodeMessages = array (
'1' => 'This transaction has been approved.',
'2' => 'This transaction has been declined.',
'3' => 'This transaction has been declined.',
'4' => 'This transaction has been declined.',
'5' => 'A valid amount is required.',
'6' => 'The credit card number is invalid.',
'7' => 'The credit card expiration date is invalid.',
'8' => 'The credit card has expired.',
'9' => 'The ABA code is invalid.',
'10' => 'The account number is invalid.',
'11' => 'A duplicate transaction has been submitted.',
'12' => 'An authorization code is required but not present.',
'13' => 'The merchant Login ID is invalid or the account is inactive.',
'14' => 'The Referrer or Relay Response URL is invalid.',
'15' => 'The transaction ID is invalid.',
'16' => 'The transaction was not found.',
'17' => 'The merchant does not accept this type of credit card.',
'18' => 'ACH transactions are not accepted by this merchant.',
'19' => 'An error occurred during processing. Please try again in 5 minutes.',
'20' => 'An error occurred during processing. Please try again in 5 minutes.',
'21' => 'An error occurred during processing. Please try again in 5 minutes.',
'22' => 'An error occurred during processing. Please try again in 5 minutes.',
'23' => 'An error occurred during processing. Please try again in 5 minutes.',
'24' => 'The Nova Bank Number or Terminal ID is incorrect. Call Merchant Service Provider.',
'25' => 'An error occurred during processing. Please try again in 5 minutes.',
'26' => 'An error occurred during processing. Please try again in 5 minutes.',
'27' => 'The transaction resulted in an AVS mismatch. The address provided does not match billing address of cardholder.',
'28' => 'The merchant does not accept this type of credit card.',
'29' => 'The PaymentTech identification numbers are incorrect. Call Merchant Service Provider.',
'30' => 'The configuration with the processor is invalid. Call Merchant Service Provider.',
'31' => 'The FDC Merchant ID or Terminal ID is incorrect. Call Merchant Service Provider.',
'32' => 'The merchant password is invalid or not present.',
'33' => 'Missing required field',
'34' => 'The VITAL identification numbers are incorrect. Call Merchant Service Provider.',
'35' => 'An error occurred during processing. Call Merchant Service Provider.',
'36' => 'The authorization was approved, but settlement failed.',
'37' => 'The credit card number is invalid.',
'38' => 'The Global Payment System identification numbers are incorrect. Call Merchant Service Provider.',
'39' => 'The supplied currency code is either invalid, not supported, not allowed for this merchant or doesn\'t have an exchange rate.',
'40' => 'This transaction must be encrypted.',
'41' => 'FraudScreen.net fraud score is higher than threshold set by merchant',
'42' => 'There is missing or invalid information in a required field.',
'43' => 'The merchant was incorrectly set up at the processor. Call your Merchant Service Provider.',
'44' => 'This transaction has been declined. Card Code filter error!',
'45' => 'This transaction has been declined. Card Code / AVS filter error!',
'46' => 'Your session has expired or does not exist. You must log in to continue working.',
'47' => 'The amount requested for settlement may not be greater than the original amount authorized.',
'48' => 'This processor does not accept partial reversals.',
'49' => 'A transaction amount greater than $99,999 will not be accepted.',
'50' => 'This transaction is awaiting settlement and cannot be refunded.',
'51' => 'The sum of all credits against this transaction is greater than the original transaction amount.',
'52' => 'The transaction was authorized, but the client could not be notified; the transaction will not be settled.',
'53' => 'The transaction type was invalid for ACH transactions.',
'54' => 'The referenced transaction does not meet the criteria for issuing a credit.',
'55' => 'The sum of credits against the referenced transaction would exceed the original debit amount.',
'56' => 'This merchant accepts ACH transactions only; no credit card transactions are accepted.',
'57' => 'An error occurred in processing. Please try again in 5 minutes.',
'58' => 'An error occurred in processing. Please try again in 5 minutes.',
'59' => 'An error occurred in processing. Please try again in 5 minutes.',
'60' => 'An error occurred in processing. Please try again in 5 minutes.',
'61' => 'An error occurred in processing. Please try again in 5 minutes.',
'62' => 'An error occurred in processing. Please try again in 5 minutes.',
'63' => 'An error occurred in processing. Please try again in 5 minutes.',
'64' => 'The referenced transaction was not approved.',
'65' => 'This transaction has been declined.',
'66' => 'The transaction did not meet gateway security guidelines.',
'67' => 'The given transaction type is not supported for this merchant.',
'68' => 'The version parameter is invalid.',
'69' => 'The transaction type is invalid. The value submitted in x_type was invalid.',
'70' => 'The transaction method is invalid.',
'71' => 'The bank account type is invalid.',
'72' => 'The authorization code is invalid.',
'73' => 'The driver\'s license date of birth is invalid.',
'74' => 'The duty amount is invalid.',
'75' => 'The freight amount is invalid.',
'76' => 'The tax amount is invalid.',
'77' => 'The SSN or tax ID is invalid.',
'78' => 'The Card Code (CVV2/CVC2/CID) is invalid.',
'79' => 'The driver\'s license number is invalid.',
'80' => 'The driver\'s license state is invalid.',
'81' => 'The merchant requested an integration method not compatible with the AIM API.',
'82' => 'The system no longer supports version 2.5; requests cannot be posted to scripts.',
'83' => 'The requested script is either invalid or no longer supported.',
'84' => 'This reason code is reserved or not applicable to this API.',
'85' => 'This reason code is reserved or not applicable to this API.',
'86' => 'This reason code is reserved or not applicable to this API.',
'87' => 'This reason code is reserved or not applicable to this API.',
'88' => 'This reason code is reserved or not applicable to this API.',
'89' => 'This reason code is reserved or not applicable to this API.',
'90' => 'This reason code is reserved or not applicable to this API.',
'91' => 'Version 2.5 is no longer supported.',
'92' => 'The gateway no longer supports the requested method of integration.',
'93' => 'A valid country is required.',
'94' => 'The shipping state or country is invalid.',
'95' => 'A valid state is required.',
'96' => 'This country is not authorized for buyers.',
'97' => 'This transaction cannot be accepted.',
'98' => 'This transaction cannot be accepted.',
'99' => 'This transaction cannot be accepted.',
'100' => 'The eCheck type is invalid.',
'101' => 'The given name on the account and/or the account type does not match the actual account.',
'102' => 'This request cannot be accepted.',
'103' => 'This transaction cannot be accepted.',
'104' => 'This transaction is currently under review.',
'105' => 'This transaction is currently under review.',
'106' => 'This transaction is currently under review.',
'107' => 'This transaction is currently under review.',
'108' => 'This transaction is currently under review.',
'109' => 'This transaction is currently under review.',
'110' => 'This transaction is currently under review.',
'111' => 'A valid billing country is required.',
'112' => 'A valid billing state/provice is required.',
'116' => 'The authentication indicator is invalid.',
'117' => 'The cardholder authentication value is invalid.',
'118' => 'The combination of authentication indicator and cardholder authentication value is invalid.',
'119' => 'Transactions having cardholder authentication values cannot be marked as recurring.',
'120' => 'An error occurred during processing. Please try again.',
'121' => 'An error occurred during processing. Please try again.',
'122' => 'An error occurred during processing. Please try again.',
'127' => 'The transaction resulted in an AVS mismatch. The address provided does not match billing address of cardholder.',
'141' => 'This transaction has been declined.',
'145' => 'This transaction has been declined.',
'152' => 'The transaction was authorized, but the client could not be notified; the transaction will not be settled.',
'165' => 'This transaction has been declined.',
'170' => 'An error occurred during processing. Please contact the merchant.',
'171' => 'An error occurred during processing. Please contact the merchant.',
'172' => 'An error occurred during processing. Please contact the merchant.',
'173' => 'An error occurred during processing. Please contact the merchant.',
'174' => 'The transaction type is invalid. Please contact the merchant.',
'175' => 'The processor does not allow voiding of credits.',
'180' => 'An error occurred during processing. Please try again.',
'181' => 'An error occurred during processing. Please try again.',
'200' => 'This transaction has been declined.',
'201' => 'This transaction has been declined.',
'202' => 'This transaction has been declined.',
'203' => 'This transaction has been declined.',
'204' => 'This transaction has been declined.',
'205' => 'This transaction has been declined.',
'206' => 'This transaction has been declined.',
'207' => 'This transaction has been declined.',
'208' => 'This transaction has been declined.',
'209' => 'This transaction has been declined.',
'210' => 'This transaction has been declined.',
'211' => 'This transaction has been declined.',
'212' => 'This transaction has been declined.',
'213' => 'This transaction has been declined.',
'214' => 'This transaction has been declined.',
'215' => 'This transaction has been declined.',
'216' => 'This transaction has been declined.',
'217' => 'This transaction has been declined.',
'218' => 'This transaction has been declined.',
'219' => 'This transaction has been declined.',
'220' => 'This transaction has been declined.',
'221' => 'This transaction has been declined.',
'222' => 'This transaction has been declined.',
'223' => 'This transaction has been declined.',
'224' => 'This transaction has been declined.',
'243' => 'Recurring billing is not allowed for this eCheck.Net type',
'244' => 'This eCheck.Net type is not allowed for this Bank Account Type.',
'245' => 'This eCheck.Net type is not allowed when using the payment gateway hosted payment form.',
'246' => 'This eCheck.Net type is not allowed.',
'247' => 'This eCheck.Net type is not allowed.',
'250' => 'This transaction has been declined.',
'251' => 'This transaction has been declined.',
'252' => 'Your order has been received. Thank you for your business!',
'253' => 'Your order has been received. Thank you for your business!',
'254' => 'This transaction has been declined.',
'261' => 'An error occurred during processing. Please try again'
var $_avsCodeMap = array (
'A' => PAYMENT_PROCESS_AVS_MISMATCH ,
'B' => PAYMENT_PROCESS_AVS_ERROR ,
'E' => PAYMENT_PROCESS_AVS_ERROR ,
'G' => PAYMENT_PROCESS_AVS_NOAPPLY ,
'N' => PAYMENT_PROCESS_AVS_MISMATCH ,
'P' => PAYMENT_PROCESS_AVS_NOAPPLY ,
'R' => PAYMENT_PROCESS_AVS_ERROR ,
'S' => PAYMENT_PROCESS_AVS_ERROR ,
'U' => PAYMENT_PROCESS_AVS_ERROR ,
'W' => PAYMENT_PROCESS_AVS_MISMATCH ,
'X' => PAYMENT_PROCESS_AVS_MATCH ,
'Y' => PAYMENT_PROCESS_AVS_MATCH ,
'Z' => PAYMENT_PROCESS_AVS_MISMATCH
var $_avsCodeMessages = array (
'A' => 'Address matches, postal code does not',
'B' => 'Address information not provided',
'E' => 'Address Verification System Error',
'G' => 'Non-U.S. Card Issuing Bank',
'N' => 'No match on street address nor postal code',
'P' => 'Address Verification System not applicable',
'R' => 'Retry - System unavailable or timeout',
'S' => 'Service not supported by issuer',
'U' => 'Address information unavailable',
'W' => '9-digit postal code matches, street address does not',
'X' => 'Address and 9-digit postal code match',
'Y' => 'Address and 5-digit postal code match',
'Z' => '5-digit postal code matches, street address does not'
var $_cvvCodeMap = array ('M' => PAYMENT_PROCESS_CVV_MATCH ,
'N' => PAYMENT_PROCESS_CVV_MISMATCH ,
'P' => PAYMENT_PROCESS_CVV_ERROR ,
'S' => PAYMENT_PROCESS_CVV_ERROR ,
'U' => PAYMENT_PROCESS_CVV_ERROR
var $_cvvCodeMessages = array (
'M' => 'CVV code matches',
'N' => 'CVV code does not match',
'P' => 'CVV code was not processed',
'S' => 'CVV code should have been present',
'U' => 'Issuer unable to process request',
var $_fieldMap = array ('0' => 'code',
* To hold the MD5 hash returned
$this->Payment_Process_Response ($rawResponse);
* Parses the data received from the payment gateway
$delim = $this->_request->getOption ('x_delim_char');
$encap = $this->_request->getOption ('x_encap_char');
if ($responseArray === false ) {
$count = count($responseArray) - 1;
if ($responseArray[0 ]{0 } == $encap) {
$responseArray[0 ] = substr($responseArray[0 ], 1 );
if (substr($responseArray[$count], -1 ) == $encap) {
$responseArray[$count] = substr($responseArray[$count], 0 , -1 );
// Save some fields in private members
$this->_md5Hash = $responseArray[$map['md5Hash']];
$this->_amount = $responseArray[$map['amount']];
$this->_mapFields ($responseArray);
// Adjust result code/message if needed based on raw code
// Something is missing so we send the raw message back
$this->_statusCodeMessages[33 ] = $this->message;
// Duplicate transactions
* Parses the data received from the payment gateway callback
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
$map = array_flip($GLOBALS['_Payment_Process_AuthorizeNet']);
* Validates the legitimacy of the response
* To be able to validate the response, the md5Value option
* must have been set in the processor. If the md5Value is not set this
* function will fail gracefully, but this MAY CHANGE IN THE FUTURE!
* Check if the response is legitimate by matching MD5 hashes.
* To avoid MD5 mismatch while the key is being renewed
* the md5Value can be an array with 2 indexes: "new" and "old"
* respectively holding the new and old MD5 values.
* Note: If you're having problem passing this check: be aware that
* the login name is CASE-SENSITIVE!!! (even though you can log in
* using it all lowered case...)
* @return mixed TRUE if response is legitimate, FALSE if not, PEAR_Error on error
* @author Philippe Jausions <Philippe.Jausions@11abacus.com>
$md5Value = $this->_request->getOption ('md5Value');
// For now fail gracefully if it is not set.
if (strcasecmp($this->_md5Hash, md5($md5Value['new'] . $fields)) == 0 ||
strcasecmp($this->_md5Hash, md5($md5Value['old'] . $fields)) == 0 ) {
} elseif (strcasecmp($this->_md5Hash, md5($md5Value . $fields)) == 0 ) {
Documentation generated on Mon, 25 Oct 2010 14:30:20 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.
|