I'm working on the AIM API method. It makes it to the process_sale page, but returns errors with no codes. Any idea where I went wrong?
www.mathcelebrity.com/checkout_form.php
response code | |
response reason code | |
response reason text |
09-26-2011 08:39 AM
Without showing us process_sale.php code, your guess is as good as our.
09-26-2011 09:07 AM
<?php
require_once 'coffee_store_settings.php';
require_once 'AuthorizeNetAIM.php';
$METHOD_TO_USE = "AIM";
if ($METHOD_TO_USE == "AIM") {
$transaction = new AuthorizeNetAIM;
$transaction->setSandbox(AUTHORIZENET_SANDBOX);
$transaction->setFields(
array(
'amount' => $amount,
'card_num' => $_POST['x_card_num'],
'exp_date' => $_POST['exp_month'].$_POST['exp_year'],
'first_name' => $_POST['x_first_name'],
'last_name' => $_POST['x_last_name'],
'address' => $_POST['x_address'],
'city' => $_POST['x_city'],
'state' => $_POST['x_state'],
'country' => $_POST['x_country'],
'zip' => $_POST['x_zip'],
'email' => $_POST['x_email'],
'card_code' => $_POST['x_card_code'],
)
);
$response = $transaction->authorizeAndCapture();
if ($response->approved) {
// Transaction approved! Do your logic here.
// generate passcode
//$passcode=generate_passcode(9,9);
header('Location: thank_you_page.php?transaction_id=' . $response->transaction_id);
} else {
header('Location: error_page.php?response_reason_code='.$response->response_reason_code.'&response_code='.$response->response_code.'&response_reason_text=' .$response->response_reason_text);
}
} elseif (count($_POST)) {
$response = new AuthorizeNetSIM;
if ($response->isAuthorizeNet()) {
if ($response->approved) {
// Transaction approved! Do your logic here.
// Redirect the user back to your site.
$return_url = $site_root . 'thank_you_page.php?transaction_id=' .$response->transaction_id;
} else {
// There was a problem. Do your logic here.
// Redirect the user back to your site.
$return_url = $site_root . 'error_page.php?response_reason_code='.$response->response_reason_code.'&response_code='.$response->response_code.'&response_reason_text=' .$response->response_reason_text;
}
echo AuthorizeNetDPM::getRelayResponseSnippet($return_url);
} else {
echo "MD5 Hash failed. Check to make sure your MD5 Setting matches the one in config.php";
}
}
09-26-2011 09:09 AM
Make a modified version of the page that on error does print_r($response); exit; Then paste us that response. Should tell us what's going on.
EDIT: Also put any code or output in a code box - see the fifth icon from the left in Rich Text mode.
09-26-2011 02:08 PM - edited 09-26-2011 02:08 PM
AuthorizeNetAIM_Response Object ( [_response_array:private] => Array ( ) [approved] => [declined] => [error] => 1 [held] => [response_code] => [response_subcode] => [response_reason_code] => [response_reason_text] => [authorization_code] => [avs_response] => [transaction_id] => [invoice_number] => [description] => [amount] => [method] => [transaction_type] => [customer_id] => [first_name] => [last_name] => [company] => [address] => [city] => [state] => [zip_code] => [country] => [phone] => [fax] => [email_address] => [ship_to_first_name] => [ship_to_last_name] => [ship_to_company] => [ship_to_address] => [ship_to_city] => [ship_to_state] => [ship_to_zip_code] => [ship_to_country] => [tax] => [duty] => [freight] => [tax_exempt] => [purchase_order_number] => [md5_hash] => [card_code_response] => [cavv_response] => [account_number] => [card_type] => [split_tender_id] => [requested_amount] => [balance_on_card] => [response] => [error_message] => Error connecting to AuthorizeNet )
I need to include AuthorizeNet.php as well as other files. Let me add this and repost after re-running this fix.
09-26-2011 02:30 PM - edited 09-26-2011 02:35 PM
Aha! Error connecting to Authorize.net. So yes, it's not the code - either the test server is down at the moment (this occasionally happens), or you're not including the correct file.
09-26-2011 02:38 PM
AuthorizeNetAIM_Response Object ( [_response_array:private] => Array ( ) [approved] => [declined] => [error] => 1 [held] => [response_code] => [response_subcode] => [response_reason_code] => [response_reason_text] => [authorization_code] => [avs_response] => [transaction_id] => [invoice_number] => [description] => [amount] => [method] => [transaction_type] => [customer_id] => [first_name] => [last_name] => [company] => [address] => [city] => [state] => [zip_code] => [country] => [phone] => [fax] => [email_address] => [ship_to_first_name] => [ship_to_last_name] => [ship_to_company] => [ship_to_address] => [ship_to_city] => [ship_to_state] => [ship_to_zip_code] => [ship_to_country] => [tax] => [duty] => [freight] => [tax_exempt] => [purchase_order_number] => [md5_hash] => [card_code_response] => [cavv_response] => [account_number] => [card_type] => [split_tender_id] => [requested_amount] => [balance_on_card] => [response] => [error_message] => Error connecting to AuthorizeNet )
My latest response is posted above. I'm not getting any include errors anymore. I see that the variables are coming down from the POST, but I think it may be going wrong on authorizeandCapture(). Any thoughts you could provide would be helpful. Below is my code for AuthorizeNetAIM.php
<?php /** * Easily interact with the Authorize.Net AIM API. * * Example Authorize and Capture Transaction against the Sandbox: * <code> * <?php require_once 'AuthorizeNet.php' * $sale = new AuthorizeNetAIM; * $sale->setFields( * array( * 'amount' => '4.99', * 'card_num' => '411111111111111', * 'exp_date' => '0515' * ) * ); * $response = $sale->authorizeAndCapture(); * if ($response->approved) { * echo "Sale successful!"; } else { * echo $response->error_message; * } * ?> * </code> * * Note: To send requests to the live gateway, either define this: * define("AUTHORIZENET_SANDBOX", false); * -- OR -- * $sale = new AuthorizeNetAIM; * $sale->setSandbox(false); * * @package AuthorizeNet * @subpackage AuthorizeNetAIM * @link http://www.authorize.net/support/AIM_guide.pdf AIM Guide */ /** * Builds and sends an AuthorizeNet AIM Request. * * @package AuthorizeNet * @subpackage AuthorizeNetAIM */ class AuthorizeNetAIM extends AuthorizeNetRequest { const LIVE_URL = 'https://secure.authorize.net/gateway/transact.dll'; const SANDBOX_URL = 'https://test.authorize.net/gateway/transact.dll'; /** * Holds all the x_* name/values that will be posted in the request. * Default values are provided for best practice fields. */ protected $_x_post_fields = array( "version" => "3.1", "delim_char" => ",", "delim_data" => "TRUE", "relay_response" => "FALSE", "encap_char" => "|", ); /** * Only used if merchant wants to send multiple line items about the charge. */ private $_additional_line_items = array(); /** * Only used if merchant wants to send custom fields. */ private $_custom_fields = array(); /** * Checks to make sure a field is actually in the API before setting. * Set to false to skip this check. */ public $verify_x_fields = true; /** * A list of all fields in the AIM API. * Used to warn user if they try to set a field not offered in the API. */ private $_all_aim_fields = array("address","allow_partial_auth","amount", "auth_code","authentication_indicator", "bank_aba_code","bank_acct_name", "bank_acct_num","bank_acct_type","bank_check_number","bank_name", "card_code","card_num","cardholder_authentication_value","city","company", "country","cust_id","customer_ip","delim_char","delim_data","description", "duplicate_window","duty","echeck_type","email","email_customer", "encap_char","exp_date","fax","first_name","footer_email_receipt", "freight","header_email_receipt","invoice_num","last_name","line_item", "login","method","phone","po_num","recurring_billing","relay_response", "ship_to_address","ship_to_city","ship_to_company","ship_to_country", "ship_to_first_name","ship_to_last_name","ship_to_state","ship_to_zip", "split_tender_id","state","tax","tax_exempt","test_request","tran_key", "trans_id","type","version","zip" ); /** * Do an AUTH_CAPTURE transaction. * * Required "x_" fields: card_num, exp_date, amount * * @param string $amount The dollar amount to charge * @param string $card_num The credit card number * @param string $exp_date CC expiration date * * @return AuthorizeNetAIM_Response */ public function authorizeAndCapture($amount = false, $card_num = false, $exp_date = false) { // ($amount ? $this->amount = $amount : null); ($card_num ? $this->card_num = $card_num : null); ($exp_date ? $this->exp_date = $exp_date : null); //$this->amount = $amount; //$this->exp_date = $exp_date; //$this->card_num = $card_num; echo "AIM amount = " .$this->x_amount."<br />"; $this->type = "AUTH_CAPTURE"; return $this->_sendRequest(); } /** * Do a PRIOR_AUTH_CAPTURE transaction. * * Required "x_" field: trans_id(The transaction id of the prior auth, unless split * tender, then set x_split_tender_id manually.) * amount (only if lesser than original auth) * * @param string $trans_id Transaction id to charge * @param string $amount Dollar amount to charge if lesser than auth * * @return AuthorizeNetAIM_Response */ public function priorAuthCapture($trans_id = false, $amount = false) { ($trans_id ? $this->trans_id = $trans_id : null); ($amount ? $this->amount = $amount : null); $this->type = "PRIOR_AUTH_CAPTURE"; return $this->_sendRequest(); } /** * Do an AUTH_ONLY transaction. * * Required "x_" fields: card_num, exp_date, amount * * @param string $amount The dollar amount to charge * @param string $card_num The credit card number * @param string $exp_date CC expiration date * * @return AuthorizeNetAIM_Response */ public function authorizeOnly($amount = false, $card_num = false, $exp_date = false) { ($amount ? $this->amount = $amount : null); ($card_num ? $this->card_num = $card_num : null); ($exp_date ? $this->exp_date = $exp_date : null); $this->type = "AUTH_ONLY"; return $this->_sendRequest(); } /** * Do a VOID transaction. * * Required "x_" field: trans_id(The transaction id of the prior auth, unless split * tender, then set x_split_tender_id manually.) * * @param string $trans_id Transaction id to void * * @return AuthorizeNetAIM_Response */ public function void($trans_id = false) { ($trans_id ? $this->trans_id = $trans_id : null); $this->type = "VOID"; return $this->_sendRequest(); } /** * Do a CAPTURE_ONLY transaction. * * Required "x_" fields: auth_code, amount, card_num , exp_date * * @param string $auth_code The auth code * @param string $amount The dollar amount to charge * @param string $card_num The last 4 of credit card number * @param string $exp_date CC expiration date * * @return AuthorizeNetAIM_Response */ public function captureOnly($auth_code = false, $amount = false, $card_num = false, $exp_date = false) { ($auth_code ? $this->auth_code = $auth_code : null); ($amount ? $this->amount = $amount : null); ($card_num ? $this->card_num = $card_num : null); ($exp_date ? $this->exp_date = $exp_date : null); $this->type = "CAPTURE_ONLY"; return $this->_sendRequest(); } /** * Do a CREDIT transaction. * * Required "x_" fields: trans_id, amount, card_num (just the last 4) * * @param string $trans_id Transaction id to credit * @param string $amount The dollar amount to credit * @param string $card_num The last 4 of credit card number * * @return AuthorizeNetAIM_Response */ public function credit($trans_id = false, $amount = false, $card_num = false) { ($trans_id ? $this->trans_id = $trans_id : null); ($amount ? $this->amount = $amount : null); ($card_num ? $this->card_num = $card_num : null); $this->type = "CREDIT"; return $this->_sendRequest(); } /** * Alternative syntax for setting x_ fields. * * Usage: $sale->method = "echeck"; * * @param string $name * @param string $value */ public function __set($name, $value) { $this->setField($name, $value); } /** * Quickly set multiple fields. * * Note: The prefix x_ will be added to all fields. If you want to set a * custom field without the x_ prefix, use setCustomField or setCustomFields. * * @param array $fields Takes an array or object. */ public function setFields($fields) { $array = (array)$fields; foreach ($array as $key => $value) { echo "key = " . $key . " and value = ".$value . "<br />"; $this->setField($key, $value); } } /** * Quickly set multiple custom fields. * * @param array $fields */ public function setCustomFields($fields) { $array = (array)$fields; foreach ($array as $key => $value) { $this->setCustomField($key, $value); } } /** * Add a line item. * * @param string $item_id * @param string $item_name * @param string $item_description * @param string $item_quantity * @param string $item_unit_price * @param string $item_taxable */ public function addLineItem($item_id, $item_name, $item_description, $item_quantity, $item_unit_price, $item_taxable) { $line_item = ""; $delimiter = ""; foreach (func_get_args() as $key => $value) { $line_item .= $delimiter . $value; $delimiter = "<|>"; } $this->_additional_line_items[] = $line_item; } /** * Use ECHECK as payment type. */ public function setECheck($bank_aba_code, $bank_acct_num, $bank_acct_type, $bank_name, $bank_acct_name, $echeck_type = 'WEB') { $this->setFields( array( 'method' => 'echeck', 'bank_aba_code' => $bank_aba_code, 'bank_acct_num' => $bank_acct_num, 'bank_acct_type' => $bank_acct_type, 'bank_name' => $bank_name, 'bank_acct_name' => $bank_acct_type, 'echeck_type' => $echeck_type, ) ); } /** * Set an individual name/value pair. This will append x_ to the name * before posting. * * @param string $name * @param string $value */ public function setField($name, $value) { if ($this->verify_x_fields) { if (in_array($name, $this->_all_aim_fields)) { $this->_x_post_fields[$name] = $value; } else { throw new AuthorizeNetException("Error: no field $name exists in the AIM API. To set a custom field use setCustomField('field','value') instead."); } } else { $this->_x_post_fields[$name] = $value; } } /** * Set a custom field. Note: the x_ prefix will not be added to * your custom field if you use this method. * * @param string $name * @param string $value */ public function setCustomField($name, $value) { $this->_custom_fields[$name] = $value; } /** * Unset an x_ field. * * @param string $name Field to unset. */ public function unsetField($name) { unset($this->_x_post_fields[$name]); } /** * * * @param string $response * * @return AuthorizeNetAIM_Response */ protected function _handleResponse($response) { return new AuthorizeNetAIM_Response($response, $this->_x_post_fields['delim_char'], $this->_x_post_fields['encap_char'], $this->_custom_fields); } /** * @return string */ protected function _getPostUrl() { return ($this->_sandbox ? self::SANDBOX_URL : self::LIVE_URL); } /** * Converts the x_post_fields array into a string suitable for posting. */ protected function _setPostString() { $this->_x_post_fields['login'] = $this->_api_login; $this->_x_post_fields['tran_key'] = $this->_transaction_key; $this->_post_string = ""; foreach ($this->_x_post_fields as $key => $value) { $this->_post_string .= "x_$key=" . urlencode($value) . "&"; } // Add line items foreach ($this->_additional_line_items as $key => $value) { $this->_post_string .= "x_line_item=" . urlencode($value) . "&"; } // Add custom fields foreach ($this->_custom_fields as $key => $value) { $this->_post_string .= "$key=" . urlencode($value) . "&"; } $this->_post_string = rtrim($this->_post_string, "& "); } } /** * Parses an AuthorizeNet AIM Response. * * @package AuthorizeNet * @subpackage AuthorizeNetAIM */ class AuthorizeNetAIM_Response extends AuthorizeNetResponse { private $_response_array = array(); // An array with the split response. /** * Constructor. Parses the AuthorizeNet response string. * * @param string $response The response from the AuthNet server. * @param string $delimiter The delimiter used (default is ",") * @param string $encap_char The encap_char used (default is "|") * @param array $custom_fields Any custom fields set in the request. */ public function __construct($response, $delimiter, $encap_char, $custom_fields) { if ($response) { // Split Array $this->response = $response; if ($encap_char) { $this->_response_array = explode($encap_char.$delimiter.$encap_char, substr($response, 1, -1)); } else { $this->_response_array = explode($delimiter, $response); } /** * If AuthorizeNet doesn't return a delimited response. */ if (count($this->_response_array) < 10) { $this->approved = false; $this->error = true; $this->error_message = "Unrecognized response from AuthorizeNet: $response"; return; } // Set all fields $this->response_code = $this->_response_array[0]; $this->response_subcode = $this->_response_array[1]; $this->response_reason_code = $this->_response_array[2]; $this->response_reason_text = $this->_response_array[3]; $this->authorization_code = $this->_response_array[4]; $this->avs_response = $this->_response_array[5]; $this->transaction_id = $this->_response_array[6]; $this->invoice_number = $this->_response_array[7]; $this->description = $this->_response_array[8]; $this->amount = $this->_response_array[9]; $this->method = $this->_response_array[10]; $this->transaction_type = $this->_response_array[11]; $this->customer_id = $this->_response_array[12]; $this->first_name = $this->_response_array[13]; $this->last_name = $this->_response_array[14]; $this->company = $this->_response_array[15]; $this->address = $this->_response_array[16]; $this->city = $this->_response_array[17]; $this->state = $this->_response_array[18]; $this->zip_code = $this->_response_array[19]; $this->country = $this->_response_array[20]; $this->phone = $this->_response_array[21]; $this->fax = $this->_response_array[22]; $this->email_address = $this->_response_array[23]; $this->ship_to_first_name = $this->_response_array[24]; $this->ship_to_last_name = $this->_response_array[25]; $this->ship_to_company = $this->_response_array[26]; $this->ship_to_address = $this->_response_array[27]; $this->ship_to_city = $this->_response_array[28]; $this->ship_to_state = $this->_response_array[29]; $this->ship_to_zip_code = $this->_response_array[30]; $this->ship_to_country = $this->_response_array[31]; $this->tax = $this->_response_array[32]; $this->duty = $this->_response_array[33]; $this->freight = $this->_response_array[34]; $this->tax_exempt = $this->_response_array[35]; $this->purchase_order_number= $this->_response_array[36]; $this->md5_hash = $this->_response_array[37]; $this->card_code_response = $this->_response_array[38]; $this->cavv_response = $this->_response_array[39]; $this->account_number = $this->_response_array[50]; $this->card_type = $this->_response_array[51]; $this->split_tender_id = $this->_response_array[52]; $this->requested_amount = $this->_response_array[53]; $this->balance_on_card = $this->_response_array[54]; $this->approved = ($this->response_code == self::APPROVED); $this->declined = ($this->response_code == self::DECLINED); $this->error = ($this->response_code == self::ERROR); $this->held = ($this->response_code == self::HELD); // Set custom fields if ($count = count($custom_fields)) { $custom_fields_response = array_slice($this->_response_array, -$count, $count); $i = 0; foreach ($custom_fields as $key => $value) { $this->$key = $custom_fields_response[$i]; $i++; } } if ($this->error) { $this->error_message = "AuthorizeNet Error: Response Code: ".$this->response_code." Response Subcode: ".$this->response_subcode." Response Reason Code: ".$this->response_reason_code." Response Reason Text: ".$this->response_reason_text." "; } } else { $this->approved = false; $this->error = true; $this->error_message = "Error connecting to AuthorizeNet"; } } }
09-26-2011 06:14 PM
Not going to read the huge wall of code. Here's my implementation for AIM, should work with the SDK right out of the box unless they made some major changes in the last few months.
NOTE: This is for the production server. If using with sandbox, set sandbox to true and use a CCV of 900.
require_once($_SERVER['DOCUMENT_ROOT'] . '/library/globals.php'); // Includes my Authorize.net ID and key require_once($_SERVER['DOCUMENT_ROOT'] . '/library/anet_php_sdk/AuthorizeNet.php'); // Path to main file of Authorize.net PHP SDK
$authorize = new AuthorizeNetAIM( $GLOBALS['_authorize_id'], $GLOBALS['_authorize_key']); $authorize->setSandbox(false); $fields = array( 'first_name' => $_POST['first'], 'last_name' => $_POST['last'], 'company' => $_POST['company'], 'address' => $_POST['address'], 'city' => $_POST['city'], 'state' => $_POST['state'], 'zip' => $_POST['zip'], 'country' => 'US', 'phone' => $_POST['phone'], 'email' => $_POST['email'], 'customer_ip' => $_SERVER['REMOTE_ADDR'], 'description' => "{$_POST['type']} initial fee for " . count($_POST['zips']) . " zip codes with {$population} total estimated population", 'amount' => $_POST['initial_payment'], 'card_num' => $_POST['card_number'], 'exp_date' => sprintf('%02d%02d', $_POST['card_exp_month'], ($_POST['card_exp_year'] % 1000)), 'card_code' => $_POST['card_ccv'] ); $authorize->setFields($fields); $result = $authorize->authorizeAndCapture(); if ($result->error || $result->{'response_code'} != 1) $errors[] = "Initial charge declined - {$result->response_reason_text}";
09-26-2011 11:40 PM - edited 09-26-2011 11:41 PM
I had to set VERIFY_PEER = false. Do I need an SSL cert when it's time to go live?
Also, I now get this response after doing that:
Response Code: 3 Response Subcode: 2 Response Reason Code: 13 Response Reason Text: The merchant login ID or password is invalid or the account is inactive
09-27-2011 08:19 AM
I found this documentation for reason code 13:
http://developer.authorize.net/tools/responsereasoncode/
Do I need to point to the live url? I have sandbox set to true right now.
09-27-2011 09:20 AM