Avec Posted October 23, 2012 Share Posted October 23, 2012 When there is a problem with credit card validation, such as incorrect number (check sum), there is supposed to be a general error message and a detail message based on what shows up in the URL. Here is the code from includes/modules/payment/cc_cvv2.php function get_error() { $error = array('title' => MODULE_PAYMENT_CC_CVV2_TEXT_ERROR, 'error' => stripslashes(urldecode($_GET['error']))); The title portion works, pulling the text as prescribed. The error part does not work. An example of the URL is: https://www.mysite.com/checkout_payment.php?payment_error=cc&error=Unable+to+match+the+credit+card+number+given+with+any+known+type+of+credit+card.&cc_owner=Tom+Synder&cc_expires_month=01&cc_expires_year=13 Any help appreciated. Quote Link to comment Share on other sites More sharing options...
♥14steve14 Posted October 23, 2012 Share Posted October 23, 2012 Best to bin the module and use one from your card processor. Quote REMEMBER BACKUP, BACKUP AND BACKUP Link to comment Share on other sites More sharing options...
Avec Posted October 23, 2012 Author Share Posted October 23, 2012 Best to bin the module and use one from your card processor. Do to the nature of the some of the sales, cards are not processed immediately, so that side is done "off-line" Quote Link to comment Share on other sites More sharing options...
Guest Posted October 23, 2012 Share Posted October 23, 2012 @@Avec You should check PCI DSS Compliance laws and policies in your state. In most of North America, it is illegal to process credit cards directly on your website and to process them 'off-line'. Chris Quote Link to comment Share on other sites More sharing options...
Avec Posted October 23, 2012 Author Share Posted October 23, 2012 @@Avec You should check PCI DSS Compliance laws and policies in your state. In most of North America, it is illegal to process credit cards directly on your website and to process them 'off-line'. Chris Thank you for your concern, but our method does not differ from any other site that does not use a gateway which I image is not a small percentage. Based on the compliance information I have, we are compliant. In looking for an answer to this question on this board, I have seen that many, many legitimate coding questions almost instantly is side-tracked into a discussion (or more adversarial) about PCI compliance. Again, thank you for your concern, but if we can keep the thread on topic, it would be appreciated. Quote Link to comment Share on other sites More sharing options...
Guest Posted October 23, 2012 Share Posted October 23, 2012 @@Avec The reason most manual credit card processing questions become discussions is because website designer / developers/ friends helping friends are being charged and convicted of installing credit card modules that are not PCI DSS compliant. The modules on this website ARE NOT compliant and the module that was bundled with v2.2 RC2a was NOT compliant. In fact, even the core code of v2.3.3 has to be changed when a compliant module is installed to ensure the transaction is processed within compliance. So your statement that "our method does not differ from any other site that does not use a gateway which I image is not a small percentage" is incorrect and as enforcement increases and fines and criminal action is taken against store owners and 'website creators' you will find more and more becoming certified. Chris ps. Even those who may seek to help you on this forum with your question could be held liable. Quote Link to comment Share on other sites More sharing options...
Avec Posted October 24, 2012 Author Share Posted October 24, 2012 So, do you have an answer to my original question? I think I was clear about my question - which was about an error message. Either you know or don't. Again, I appreciate the concern, but please stick to the original topic Quote Link to comment Share on other sites More sharing options...
♥14steve14 Posted October 24, 2012 Share Posted October 24, 2012 You will get very little help, due to PCI DSS compliance rules. Like I said, ditch the module and do it correctly. Sorry. Quote REMEMBER BACKUP, BACKUP AND BACKUP Link to comment Share on other sites More sharing options...
Bob Terveuren Posted October 25, 2012 Share Posted October 25, 2012 The url shows & when it should be & Maybe that's your trouble BT Quote Link to comment Share on other sites More sharing options...
veritas219 Posted October 29, 2012 Share Posted October 29, 2012 I am having the same problem with the "This transaction has been declined" message not showing up to let the customer know that his card did not go through. It just redirects them to the check out options page with no error message telling them that the order was not processed. I am using Authorize.net payment module. Cards are processed or declined normally otherwise but it just will not show the the error message like it should when a card is declined. I was told by my host provider that it could that I need a private ssl instead of a shared ssl and that will cost extra money. Why would my shared ssl be a problem all of a sudden when it worked before? Quote Link to comment Share on other sites More sharing options...
Bob Terveuren Posted November 1, 2012 Share Posted November 1, 2012 Hi Your SSL would not affect this. Have a look at http://www.oscommerce.com/community/contributions,4091 there's a change in there that may help you (if you look at the file includes/modules/payment/authorizenet_aim.php there's a point in there where the response from AuthNet gets split up into an array - about line 733 - and it's sending the fourth element in the array back to checkout_payment using the error function which is just below it. Maybe that'll help? Bob Quote Link to comment Share on other sites More sharing options...
veritas219 Posted December 11, 2012 Share Posted December 11, 2012 Bob, My authorizenet_aim.php doeen't have a line 733, it only goes to 389. but I did see this in the code I hightlighted in bold below: // Evaluates the Credit Card Type for acceptance and validity of the Credit Card Number and Expiry Date function pre_confirmation_check() { global $_POST; include(DIR_WS_CLASSES . 'cc_validation.php'); $cc_validation = new cc_validation(); $result = $cc_validation->validate($_POST['authorizenet_aim_cc_number'], $_POST['authorizenet_aim_cc_expires_month'], $_POST['authorizenet_aim_cc_expires_year'], $_POST['authorizenet_aim_cc_cvv']); $error = ''; switch ($result) { case -1: $error = sprintf(TEXT_CCVAL_ERROR_UNKNOWN_CARD, substr($cc_validation->cc_number, 0, 4)); break; case -2: case -3: case -4: $error = TEXT_CCVAL_ERROR_INVALID_DATE; break; case false: $error = TEXT_CCVAL_ERROR_INVALID_NUMBER; break; } if ( ($result == false) || ($result < 1) ) { $payment_error_return = 'payment_error=' . $this->code . '&error=' . urlencode($error) . '&authorizenet_aim_cc_owner=' . urlencode($_POST['authorizenet_aim_cc_owner']) . '&authorizenet_aim_cc_expires_month=' . $_POST['authorizenet_aim_cc_expires_month'] . '&authorizenet_aim_cc_expires_year=' . $_POST['authorizenet_aim_cc_expires_year']; tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false)); } $this->cc_card_type = $cc_validation->cc_type; $this->cc_card_number = $cc_validation->cc_number; $this->cc_expiry_month = $cc_validation->cc_expiry_month; $this->cc_expiry_year = $cc_validation->cc_expiry_year; } // Display Credit Card Information on the Checkout Confirmation Page function confirmation() { global $_POST; if (MODULE_PAYMENT_AUTHORIZENET_AIM_USE_CVV == 'True') { $confirmation = array(//'title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CATALOG_TITLE, // Redundant 'fields' => array(array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_TYPE, 'field' => $this->cc_card_type), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_OWNER, 'field' => $_POST['authorizenet_aim_cc_owner']), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_NUMBER, 'field' => substr($this->cc_card_number, 0, 4) . str_repeat('X', (strlen($this->cc_card_number) - 8)) . substr($this->cc_card_number, -4)), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_EXPIRES, 'field' => strftime('%B, %Y', mktime(0,0,0,$_POST['authorizenet_aim_cc_expires_month'], 1, '20' . $_POST['authorizenet_aim_cc_expires_year']))), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CVV, 'field' => $_POST['authorizenet_aim_cc_cvv']))); } else { $confirmation = array(//'title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CATALOG_TITLE, // Redundant 'fields' => array(array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_TYPE, 'field' => $this->cc_card_type), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_OWNER, 'field' => $_POST['authorizenet_aim_cc_owner']), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_NUMBER, 'field' => substr($this->cc_card_number, 0, 4) . str_repeat('X', (strlen($this->cc_card_number) - 8)) . substr($this->cc_card_number, -4)), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_EXPIRES, 'field' => strftime('%B, %Y', mktime(0,0,0,$_POST['authorizenet_aim_cc_expires_month'], 1, '20' . $_POST['authorizenet_aim_cc_expires_year']))))); } return $confirmation; } Quote Link to comment Share on other sites More sharing options...
Bob Terveuren Posted December 12, 2012 Share Posted December 12, 2012 Hi there - the line you've found is in the pre_confirmation_check() function so it's designed to sit before the checkout_confirmation page and run through the card numbers etc using the built in .js checking system) and chuck the customer back to the payment page if it finds a basic error (the javascript runs through the Luhn formula as applies to CC numbers so will pick up a miss-typed number). Have a look here - this looks like your module http://addons.oscommerce.com/info/4091 Maybe the last update would help? Basically from reading through the modules there it seems that Authorize.net change the response delimeters from time to time - the code you need is in the function before_process() which is called into play in the checkout_process.php file before the order gets written to the database - in there you'll see this (or similar) if ($this->response[0] != '1') { tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . urlencode($this->response[3]) . ' - ' . urlencode(MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_DECLINED_MESSAGE), 'SSL', true, false)); } That's looking at the return message from Auth.net and if the first chunk is not equal to 1 is returning you to the payment page with the error message being equal to the fourth chunk of the return plus the text held in MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_DECLINED_MESSAGE. If you have no text defined as MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_DECLINED_MESSAGE then try defining some and see if that shows up - if it does then urlencode($this->response[3]) is empty - if nothing shows up then it looks like the error handling side of things is stuffed Quote Link to comment Share on other sites More sharing options...
veritas219 Posted December 15, 2012 Share Posted December 15, 2012 Thanks for the response. I found two groups of code that are related to what you wrote below.. The second group which is closest to what you mentioned looks like it is commented out with a // before it. if ( ($result == false) || ($result < 1) ) { $payment_error_return = 'payment_error=' . $this->code . '&error=' . urlencode($error) . '&authorizenet_aim_cc_owner=' . urlencode($_POST['authorizenet_aim_cc_owner']) . '&authorizenet_aim_cc_expires_month=' . $_POST['authorizenet_aim_cc_expires_month'] . '&authorizenet_aim_cc_expires_year=' . $_POST['authorizenet_aim_cc_expires_year']; tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false)); } $this->cc_card_type = $cc_validation->cc_type; $this->cc_card_number = $cc_validation->cc_number; $this->cc_expiry_month = $cc_validation->cc_expiry_month; $this->cc_expiry_year = $cc_validation->cc_expiry_year; } // Display Credit Card Information on the Checkout Confirmation Page function confirmation() { global $_POST; if (MODULE_PAYMENT_AUTHORIZENET_AIM_USE_CVV == 'True') { $confirmation = array(//'title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CATALOG_TITLE, // Redundant 'fields' => array(array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_TYPE, 'field' => $this->cc_card_type), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_OWNER, 'field' => $_POST['authorizenet_aim_cc_owner']), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_NUMBER, 'field' => substr($this->cc_card_number, 0, 4) . str_repeat('X', (strlen($this->cc_card_number) - 8)) . substr($this->cc_card_number, -4)), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_EXPIRES, 'field' => strftime('%B, %Y', mktime(0,0,0,$_POST['authorizenet_aim_cc_expires_month'], 1, '20' . $_POST['authorizenet_aim_cc_expires_year']))), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CVV, 'field' => $_POST['authorizenet_aim_cc_cvv']))); } else { $confirmation = array(//'title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CATALOG_TITLE, // Redundant 'fields' => array(array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_TYPE, 'field' => $this->cc_card_type), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_OWNER, 'field' => $_POST['authorizenet_aim_cc_owner']), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_NUMBER, 'field' => substr($this->cc_card_number, 0, 4) . str_repeat('X', (strlen($this->cc_card_number) - 8)) . substr($this->cc_card_number, -4)), array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_CREDIT_CARD_EXPIRES, 'field' => strftime('%B, %Y', mktime(0,0,0,$_POST['authorizenet_aim_cc_expires_month'], 1, '20' . $_POST['authorizenet_aim_cc_expires_year']))))); } return $confirmation; } function process_button() { // Hidden fields on the checkout confirmation page $process_button_string = tep_draw_hidden_field('cc_owner', $_POST['authorizenet_aim_cc_owner']) . tep_draw_hidden_field('cc_expires', $this->cc_expiry_month . substr($this->cc_expiry_year, -2)) . tep_draw_hidden_field('cc_type', $this->cc_card_type) . tep_draw_hidden_field('cc_number', $this->cc_card_number); if (MODULE_PAYMENT_AUTHORIZENET_AIM_USE_CVV == 'True') { $process_button_string .= tep_draw_hidden_field('cc_cvv', $_POST['authorizenet_aim_cc_cvv']); } $process_button_string .= tep_draw_hidden_field(tep_session_name(), tep_session_id()); return $process_button_string; return false; } function before_process() { global $_POST, $response, $db, $order; // DATA PREPARATION SECTION unset($submit_data); // Cleans out any previous data stored in the variable // Create a string that contains a listing of products ordered for the description field $description = ''; for ($i=0; $i<sizeof($order->products); $i++) { $description .= $order->products[$i]['name'] . '(qty: ' . $order->products[$i]['qty'] . ') + '; } // Strip the last "\n" from the string $description = substr($description, 0, -2); // Create a variable that holds the order time $order_time = date("F j, Y, g:i a"); // Calculate the next expected order id $last_order_id = tep_db_query("select * from " . TABLE_ORDERS . " order by orders_id desc limit 1"); $new_order_id = $last_order_id->fields['orders_id']; $new_order_id = ($new_order_id + 1); // Populate an array that contains all of the data to be submitted $submit_data = array( x_login => MODULE_PAYMENT_AUTHORIZENET_AIM_LOGIN, // The login name as assigned to you by authorize.net x_tran_key => MODULE_PAYMENT_AUTHORIZENET_AIM_TXNKEY, // The Transaction Key (16 digits) is generated through the merchant interface x_relay_response => 'FALSE', // AIM uses direct response, not relay response x_delim_data => 'TRUE', // The default delimiter is a comma x_version => '3.1', // 3.1 is required to use CVV codes x_type => MODULE_PAYMENT_AUTHORIZENET_AIM_AUTHORIZATION_TYPE == 'Authorize' ? 'AUTH_ONLY': 'AUTH_CAPTURE', x_method => 'CC', //MODULE_PAYMENT_AUTHORIZENET_AIM_METHOD == 'Credit Card' ? 'CC' : 'ECHECK', x_amount => number_format($order->info['total'], 2), x_card_num => $_POST['cc_number'], x_exp_date => $_POST['cc_expires'], x_card_code => $_POST['cc_cvv'], x_email_customer => MODULE_PAYMENT_AUTHORIZENET_AIM_EMAIL_CUSTOMER == 'True' ? 'TRUE': 'FALSE', x_email_merchant => MODULE_PAYMENT_AUTHORIZENET_AIM_EMAIL_MERCHANT == 'True' ? 'TRUE': 'FALSE', x_cust_id => $_SESSION['customer_id'], x_invoice_num => $new_order_id, x_first_name => $order->billing['firstname'], x_last_name => $order->billing['lastname'], x_company => $order->billing['company'], x_address => $order->billing['street_address'], x_city => $order->billing['city'], x_state => $order->billing['state'], x_zip => $order->billing['postcode'], x_country => $order->billing['country']['title'], x_phone => $order->customer['telephone'], x_email => $order->customer['email_address'], x_ship_to_first_name => $order->delivery['firstname'], x_ship_to_last_name => $order->delivery['lastname'], x_ship_to_address => $order->delivery['street_address'], x_ship_to_city => $order->delivery['city'], x_ship_to_state => $order->delivery['state'], x_ship_to_zip => $order->delivery['postcode'], x_ship_to_country => $order->delivery['country']['title'], x_description => $description, // Merchant defined variables go here Date => $order_time, IP => $_SERVER['REMOTE_ADDR'], Session => tep_session_id()); if(MODULE_PAYMENT_AUTHORIZENET_AIM_TESTMODE == 'Test') { $submit_data['x_test_request'] = 'TRUE'; } else { $submit_data['x_test_request'] = 'FALSE'; } // concatenate the submission data and put into variable $data while(list($key, $value) = each($submit_data)) { $data .= $key . '=' . urlencode(ereg_replace(',', '', $value)) . '&'; } // Remove the last "&" from the string $data = substr($data, 0, -1); // Post order info data to Authorize.net // cURL must be compiled into PHP // Connection must be https // Test or Live Server address set // using 'Test' or 'Live' mode in // osCommerce admin panel unset($response); if (MODULE_PAYMENT_AUTHORIZENET_AIM_TESTMODE == 'Test') { $url = 'https://secure.authorize.net/gateway/transact.dll'; // If this does not work then change 'secure' to 'certification' on this line } else { $url = 'https://secure.authorize.net/gateway/transact.dll'; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_VERBOSE, 0); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); if(MODULE_PAYMENT_AUTHORIZENET_AIM_CURL_PROXY != 'none') { curl_setopt ($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); curl_setopt ($ch, CURLOPT_PROXY,MODULE_PAYMENT_AUTHORIZENET_AIM_CURL_PROXY); } $authorize = curl_exec($ch); curl_close ($ch); $response = split('\,', $authorize); // Parse the response code and text for custom error display $response_code = explode(',', $response[0]); $response_text = explode(',', $response[3]); $x_response_code = $response_code[0]; $x_response_text = $response_text[0]; // If the response code is not 1 (approved) then redirect back to the payment page with the appropriate error message if ($x_response_code != '1') { tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, 'error_message=' . $x_response_text . ' - ' . urlencode(MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_DECLINED_MESSAGE), 'SSL', true, false)); } } function after_process() { return false; } function get_error() { global $_GET; $error = array('title' => MODULE_PAYMENT_AUTHORIZENET_AIM_TEXT_ERROR, 'error' => stripslashes(urldecode($_GET['error']))); return $error; } function check() { if (!isset($this->_check)) { $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_PAYMENT_AUTHORIZENET_AIM_STATUS'"); $this->_check = tep_db_num_rows($check_query); Quote Link to comment Share on other sites More sharing options...
veritas219 Posted December 15, 2012 Share Posted December 15, 2012 I don't think it's the Authorize.net aim module because when I tested it with the regular non-authorize.net aim cc module(The generic cc module), I didn't get a declined message with that one either. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.