Build a Basic Authorize.net Payment Form
Getting a payment form that works can be tricky. But once you figure it out, you have the form as a reference forever. I’d like to show you how to build a basic Authorize.net payment form using HTML and PHP.
Luckily, Authorize.net does a very good job providing documentation to web developers, making this form creation process very easy.
This form is for Authorize.Net’s Advanced Integrated Method, the recommended connection method that offers the most security and flexibility.
The whole point of secure online transactions is that sensative information, especially credit card information, should never be stored in a database. That information should be used to handle a payment then immediately forgotten. Some online retailers save the last 4 digits of a credit card but only for recipt purposes. The form I will help you build will forget the credit card info, making it ultra safe. I will also show you how to log this form data in a database.
Step 1: Database
First we need a database. Here is a little SQL to get you going:
CREATE TABLE IF NOT EXISTS `transaction_log` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `pid` INT(11) NOT NULL, `response_code` INT(11) NOT NULL, `payment_data` text NOT NULL, `response_data` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
The record keeping system I use serializes data, which is very basic. This works to keep you out of tax problems (because you have a complete payment record) but it isn’t the best for a direct download because the data has to be un-serialized.
Step 2: The HTML Form
Now on the the HTML. I am going to append a little bit of Javascript and a touch of PHP into this HTML form.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?php if(isset($_POST['run'])) { include('payment_validation.php'); } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Payment gateway Form</title> </head> <body> <form name="payment" action="" method="post" onsubmit="document.getElementById('submit_button').disabled = 1;"> <p><input type="hidden" name="page_id" value="4"></p> <p><label>First Name</label><input type="text" name="first_name"></p> <p><label>Last Name</label><input type="text" name="last_name"></p> <p><label>Comments</label><textarea name="comments"></textarea></p> <p><label>Card Num</label><input type="text" name="cc_card_num"></p> <p><label>Expiration Date</label><input type="text" name="cc_exp_date"></p> <p><label>Amount</label><input type="text" name="cc_amount"></p> <p><label>Description</label><input type="text" name="cc_description"></p> <p><input name="submit" id="submit_button" type="submit"></p> <p><input type="hidden" name="run" value="true"></p> </form> </body> </html>
It is good to take special note of the “onsubmit” attribute I’ve added to the form tag. This little snippet of Javascript prevents someone from accidentally clicking the submit button twice, thereby avoiding doubled transactions. The PHP at the top of the example HTML includes our payment validation script once the form is submitted. The “payment_validation.php” script it includes validates whether or not we have filled out all the form’s required fields. Now, some of these fields must be required because Authorize.net has a set of required information that they use for payment processing, including name, card number, etc. The PHP below just makes sure we have all that information.
Step 3: Validation
I am not going to go into to much more detail about form validation with PHP. That’s a topic for another tutorial. I will warn you, though, that the validation I use in this script is very basic. You should spend time making it stronger.
<?php $required_fields = array( 'page_id' => 'page_id', 'Amount' => 'cc_amount', 'Credit Card Number' => 'cc_card_num', 'Credit Card Expiration Date' => 'cc_exp_date', 'Description' => 'cc_description' ); function verify_data_present($required_fields) { $errors = array(); if(empty($_POST)) { // Ensure we have some data die("<strong>No Post! Nothing to send to Authorize.net</strong>"); } // Make sure that all of the required fields exist as keys in the post array foreach($required_fields as $key => $value) { if(!in_array($value, array_keys($_POST))) { $errors[] = $value . " does not exist in post data and is required!"; } else { if(empty($_POST[$value])) { $errors[] = $key . " is a required field."; } } } if(!is_numeric($_POST['cc_card_num'])) $errors[] = "Card number must be numeric!"; if(!is_numeric($_POST['cc_amount'])) $errors[] = "Amount must be a decimal of form x.xx without the dollar sign!"; if(!empty($errors)) { echo "<div><ul>"; foreach($errors as $value) { echo "<li>" . $value . "</li>"; } echo "</ul></div>"; return false; } else { return true; } } // Verifty Required POST data isn't empty if(!verify_data_present($required_fields)) { die(); } else { include('gateway.php'); echo "<div class="approved">Your transaction has been approved.</div>"; } ?>
Step 4: The Gateway
Near the end of this PHP script, you will see this line: include('gateway.php');. That is the magic PHP include that sends along the payment information to Authorize.net and, even if the payment fails, adds the transaction details to your database. Let’s take a look at that script now. I warn you, though, this PHP is intimidating at first glance.
<?php // Settings $post_url = "https://test.authorize.net/gateway/transact.dll"; $db_host = "localhost"; $db_user = "root"; $db_pass = ""; $db_name = "payments"; $db_table = "transaction_log"; // Setup the array with data to post to authorize.net $post_values = array( "x_login" => "********", // Given to you by Authorize.net (make sure you replace!) "x_tran_key" => "****************", // Given to you by Authorize.net (make sure you replace!) "x_version" => "3.1", "x_delim_data" => "TRUE", "x_delim_char" => "|", "x_relay_response" => "FALSE", "x_type" => "AUTH_CAPTURE", "x_method" => "CC", "x_card_num" => $_POST['cc_card_num'], "x_exp_date" => $_POST['cc_exp_date'], "x_amount" => $_POST['cc_amount'], "x_description" => $_POST['cc_description'], // The Values Below are Optional "x_first_name" => "John", "x_last_name" => "Doe", "x_address" => "1234 Street", "x_state" => "CA", "x_zip" => "90210" ); // This section takes the input fields and converts them to the proper format // for an http post. For example: "x_login=username&x_tran_key=a1B2c3D4" $post_string = ""; foreach( $post_values as $key => $value ) { $post_string .= "$key=" . urlencode( $value ) . "&"; } $post_string = rtrim( $post_string, "& " ); // This sample code uses the CURL library for php to establish a connection, // submit the post, and record the response. // If you receive an error, you may want to ensure that you have the curl // library enabled in your php configuration $request = curl_init($post_url); // initiate curl object curl_setopt($request, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response curl_setopt($request, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1) curl_setopt($request, CURLOPT_POSTFIELDS, $post_string); // use HTTP POST to send form data curl_setopt($request, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. $post_response = curl_exec($request); // execute curl post and store results in $post_response // additional options may be required depending upon your server configuration // you can find documentation on curl options at http://www.php.net/curl_setopt curl_close ($request); // close curl object // This line takes the response and breaks it into an array using the specified delimiting character $response_array = explode($post_values["x_delim_char"],$post_response); /* * Before we allow the system to do anything with the * rest of the form data we need to make sure that the * credit card number gets removed to prevent sensitive * information from getting out just in case we are * compromised. */ unset($_POST['cc_card_num']); // remove the credit card info print_r($response_array); // ********************************************** // NOW WE CAN DO STUFF WITH THE RESPONSE // ********************************************** // Connect to the database $mysqli = new mysqli($db_host,$db_user,$db_pass,$db_name); // Check db connection if(mysqli_connect_errno()) die(mysqli_connect_error()); // Store the form info $query = "INSERT INTO ".$db_table." SET pid = '".$_POST['page_id']."', response_code = '".$response_array[0]."', payment_data = '".serialize($_POST)."', response_data = '".serialize($response_array)."'"; if(!$mysqli->query($query)) { echo $mysqli->error; } unset($_POST); ?>
This script looks scary but it is quite straight forward. It starts with some basic variable declarations, which consist of database connection variables and a very important $post_url. This defines the URL we will use to POST data to Authorize.net. It is currently set to the default Authorize.net test environment. That way we don’t have to worry about actually spending money to experiment with this payment form.
The next part of this “gateway.php” script is an array of data called $post_values. This is the actual array of data that gets sent to Authorize.net. Notice the POST data we are adding from our form. That’s the real bread and butter of the whole process! More importantly, though, are two parts of this array that identify who you are to Authorize.net. They are the x_login and x_tran_key. I think of these as my username and password to Authorize.net. Make sure that when you get your login and key from Authorize.net (after your account setup) to keep them safe. You will have to add your login and key to this form. You can request a test account from Authorize.net.
After the $post_values array you’ll begin to see more complicated PHP. You do not need to edit this data. Whet you see is the initialization of a CURL object which handles the POST of our data to Authorize.net. It also handles the response we get, which tells us whether or not our payment was approved. That response gets added the $post_response array defined on line 55 of the “gateway.php” script.
After this CURL object (in the PHP) you’ll see a few lines of code that add the serialized POST data to our database, sans any credit card information. The credit card is stripped from our data on line 71 of the “gateway.php” script with the unset($_POST['cc_card_num']); command.
Finished
That’s it! Please take note that I echo the response array after the form is submitted. Interpreting this response can be challenging, but you can do it with help from the Authorize.net Developer’s Guide. This form is available for download.
Thanks
Thanks to Ben Lobaugh for his help with this script.

Hey!
Googling my name and what do I find but a post mentioning me! Woot.
Great job on the tutorial. It’s very clear and easy to follow.
Thanks for the credit as well. :D
This is useful for countries which do not accept payments or receiving of money via PayPal. So simple yet effective.
I couldn’t get the values to be posted into the submittal. It returned cc_description and 0.0 for amount etc. It looks like some kind of php is required either in the referring page or the final page.
hello. would you be interested in developing this as a wordpress plugin?
Yes, I would.
great tutorial, the only thing i ran into problems with was:
echo “Your transaction has been approved.”;
I needed to edit “approved” to either \”approved\” or ‘approved’
Dude, code helped lot for integrating authorize.net however below problem took away more than my four precious hours… (“” The following errors have occurred.—- (13) The merchant login ID or password is invalid or the account is inactive. —– “”) by your code until we relace “”"” & by & “”"” (foreach( $post_values as $key => $value ){ $post_string .= “$key=” . urlencode( $value ) . “&”; }
$post_string = rtrim( $post_string, “& ” );)
Hope this will help you to rectify code.
:)