Forums

How to use Authorize.net with SIM

DarksteelBlade 05 Oct, 2010
I'm building an online payment system. One of the requirements is that the system must integrate into authorize.net's server integration method. I've ruled out using the authorize.net plugin because it uses the advanced integration method.

Authorize.net's server integration method allows a form on the merchants website to post information to a secure payment form hosted by authorize.net. To accomplish this I plan to use the Redirect plugin in concert with snippets of authorize.net's sample code.

Authorize.net's sample code is as follows:
<!--
This sample code is designed to connect to Authorize.net using the SIM method.
For API documentation or additional sample code, please visit:
http://developer.authorize.net

Most of this page can be modified using any standard html. The parts of the
page that cannot be modified are noted in the comments.  This file can be
renamed as long as the file extension remains .php
-->

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
  "http://www.w3.org/TR/html4/loose.dtd">
<HTML lang='en'>
<HEAD>
    <TITLE> Sample SIM Implementation </TITLE>
</HEAD>
<BODY>

<!-- This section generates the "Submit Payment" button using PHP           -->
<?PHP
// This sample code requires the mhash library for PHP versions older than
// 5.1.2 - http://hmhash.sourceforge.net/
    
// the parameters for the payment can be configured here
// the API Login ID and Transaction Key must be replaced with valid values
$loginID        = "API_LOGIN_ID";
$transactionKey = "TRANSACTION_KEY";
$amount         = "19.99";
$description     = "Sample Transaction";
$label             = "Submit Payment"; // The is the label on the 'submit' button
$testMode        = "false";
// By default, this sample code is designed to post to our test server for
// developer accounts: https://test.authorize.net/gateway/transact.dll
// for real accounts (even in test mode), please make sure that you are
// posting to: https://secure.authorize.net/gateway/transact.dll
$url            = "https://test.authorize.net/gateway/transact.dll";

// If an amount or description were posted to this page, the defaults are overidden
if ($_REQUEST["amount"])
    { $amount = $_REQUEST["amount"]; }
if ($_REQUEST["description"])
    { $description = $_REQUEST["description"]; }

// an invoice is generated using the date and time
$invoice    = date(YmdHis);
// a sequence number is randomly generated
$sequence    = rand(1, 1000);
// a timestamp is generated
$timeStamp    = time ();

// The following lines generate the SIM fingerprint.  PHP versions 5.1.2 and
// newer have the necessary hmac function built in.  For older versions, it
// will try to use the mhash library.
if( phpversion() >= '5.1.2' )
{    $fingerprint = hash_hmac("md5", $loginID . "^" . $sequence . "^" . $timeStamp . "^" . $amount . "^", $transactionKey); }
else 
{ $fingerprint = bin2hex(mhash(MHASH_MD5, $loginID . "^" . $sequence . "^" . $timeStamp . "^" . $amount . "^", $transactionKey)); }

// Print the Amount and Description to the screen.
echo "Amount: $amount <br />";
echo "Description: $description <br />";

// Create the HTML form containing necessary SIM post values
echo "<FORM method='post' action='$url' >";
// Additional fields can be added here as outlined in the SIM integration guide
// at: http://developer.authorize.net
echo "    <INPUT type='hidden' name='x_login' value='$loginID' />";
echo "    <INPUT type='hidden' name='x_amount' value='$amount' />";
echo "    <INPUT type='hidden' name='x_description' value='$description' />";
echo "    <INPUT type='hidden' name='x_invoice_num' value='$invoice' />";
echo "    <INPUT type='hidden' name='x_fp_sequence' value='$sequence' />";
echo "    <INPUT type='hidden' name='x_fp_timestamp' value='$timeStamp' />";
echo "    <INPUT type='hidden' name='x_fp_hash' value='$fingerprint' />";
echo "    <INPUT type='hidden' name='x_test_request' value='$testMode' />";
echo "    <INPUT type='hidden' name='x_show_form' value='PAYMENT_FORM' />";
echo "    <input type='submit' value='$label' />";
echo "</FORM>";
?>
<!-- This is the end of the code generating the "submit payment" button.    -->

</BODY>
</HTML>


This code does several things:
-Stores the API and Transaction keys
-Stores the total cost
-Generates a unique fingerprint for the transaction
-Posts the information to authorize.net

We will still need the sample code to store the api info and generate the fingerprint. However we can get the redirect plugin to do the posting for us. We just put the url for authorize.net's gateway in the target URL box.

Next we need use some of the sample code to load the keys and generate a transaction fingerprint. So we do a little snippy-snip on the sample code:

<?PHP
// This sample code requires the mhash library for PHP versions older than
// 5.1.2 - http://hmhash.sourceforge.net/
    
// the parameters for the payment can be configured here
// the API Login ID and Transaction Key must be replaced with valid values
$loginID        = "API_LOGIN_ID";
$transactionKey = "TRANSACTION_KEY";
$amount         = "19.99";
$description     = "Sample Transaction";
$label             = "Submit Payment"; // The is the label on the 'submit' button
$testMode        = "false";
// By default, this sample code is designed to post to our test server for
// developer accounts: https://test.authorize.net/gateway/transact.dll
// for real accounts (even in test mode), please make sure that you are
// posting to: https://secure.authorize.net/gateway/transact.dll

// If an amount or description were posted to this page, the defaults are overidden
if ($_REQUEST["amount"])
    { $amount = $_REQUEST["amount"]; }
if ($_REQUEST["description"])
    { $description = $_REQUEST["description"]; }

// an invoice is generated using the date and time
$invoice    = date(YmdHis);
// a sequence number is randomly generated
$sequence    = rand(1, 1000);
// a timestamp is generated
$timeStamp    = time ();

// The following lines generate the SIM fingerprint.  PHP versions 5.1.2 and
// newer have the necessary hmac function built in.  For older versions, it
// will try to use the mhash library.
if( phpversion() >= '5.1.2' )
{    $fingerprint = hash_hmac("md5", $loginID . "^" . $sequence . "^" . $timeStamp . "^" . $amount . "^", $transactionKey); }
else 
{ $fingerprint = bin2hex(mhash(MHASH_MD5, $loginID . "^" . $sequence . "^" . $timeStamp . "^" . $amount . "^", $transactionKey)); }



// Additional fields can be added here as outlined in the SIM integration guide
// at: http://developer.authorize.net
echo "    <INPUT type='hidden' name='x_login' value='$loginID' />";
echo "    <INPUT type='hidden' name='x_amount' value='$amount' />";
echo "    <INPUT type='hidden' name='x_description' value='$description' />";
echo "    <INPUT type='hidden' name='x_invoice_num' value='$invoice' />";
echo "    <INPUT type='hidden' name='x_fp_sequence' value='$sequence' />";
echo "    <INPUT type='hidden' name='x_fp_timestamp' value='$timeStamp' />";
echo "    <INPUT type='hidden' name='x_fp_hash' value='$fingerprint' />";
echo "    <INPUT type='hidden' name='x_test_request' value='$testMode' />";
echo "    <INPUT type='hidden' name='x_show_form' value='PAYMENT_FORM' />";
echo "    <input type='submit' value='$label' />";
echo "</FORM>";
?>


This is then put into the extra code field of the redirect plugin. The code hasn't changed much. All we did was snip out the html head and body tags, the submit button code, and the form declaration.

This is where my understanding of the process gets hazy and I need some input on how to complete this task. Can the redirect plugin take PHP variables (IE x_field=$Foo)? If not will declaring hidden fields in the extra code section as above allow me to pass them to the extra fields section? If not will having one of the child forms store the hidden fields work?

In exchange for everyone's help I plan on immediately editing this thread to be a proper tutorial on how to pull this trick off.
DarksteelBlade 06 Oct, 2010
I have now had several hours to play with this task. I have answered several of my original questions and now have some new ones.

You cannot pas php variables to values in the extra fields area. However you can call hidden fields in the extra code area and then assign the extra values to the hidden fields. Also if you are using a multi page form this extra code seems to effectively run on the last page of your form.

In the end it is much better to declare the hidden fields on the last page of your form along with the rest of the auth.net sample code. This allows it to enter the $_POST array correctly.

This brings us to my most recent discovery. The redirect plug in uses the GET method to pass data to the next website. Authorize.net requires the form to POST the data. Thus you cannot use the redirect plug in for SIM with authorize.net.

For a single page form there is an easy workaround. Just change the onSubmit url in the form's general settings to "https://test.authorize.net/gateway/transact.dll" (for developer accounts).

My new question is how do I change the onSubmit url for a multi page form? I have tried changing the onSubmit url for the mother form. This causes the form to go to the onSubmit url after the first page. I have also tried changing the onSubmit url of the last child form. This seemed to have no effect.
GreyHead 06 Oct, 2010
Hi DarksteelBlade,

My new question is how do I change the onSubmit url for a multi page form?

You can't, using an OnSubmit URL means that ChronoForms never sees the form results and so can't do *anything* with them; and that includes handling the multi-page functionality.

Is there some reason that you can't use the Authorize.net plug-in (or the cURL plug-in) which uses POST?

Bob

PS You can probably pass PHP variables to the Extra Code boxes if they are defined as having global scope - but this will depend on the flow sequence of the form.
DarksteelBlade 06 Oct, 2010
Thanks for the info GreyHead!

I gave the CURL plugin a try and though it does use post it does not redirect the user to the target url.

The reason I cant use the A.net plugin (which is awesome and I wish I could use it on this project) is that it uses the advanced integration method (AIM) api. My customer has specifically requested that I use the server integration method (SIM). The big functional difference between the two is that the SIM redirects the user to A.net's secure payment form hosted by A.net instead of doing all the data collection on the merchants website and only using A.net to authorize the transaction like AIM.

My current plan is to forgo using the multi page plugin. I plan on handling the post array between pages manually. Basically I plan on grabbing variables from the $_POST array and assigning them to hidden fields. Then I will set the onSubmit url of each form to the url of the next form. This way the values of the hidden fields will appear in the next page's $_POST array. Then I will set the onSubmit url of the form's last page to A.nets gateway. This way the last page will post all the pertinent data to A.net's secure form and redirect the user there. (I've already confirmed that works on a simple one page test form using the above sample code.)

The whole grabbing from $_POST and assigning to hidden fields feels like a messy solution to me. Is there a way to make the $_POST array visible to more than one form without using the nulti page plugin?
DarksteelBlade 07 Oct, 2010
I've now implemented the whole hidden fields and post nonsense I described above and it works for passing data between pages. However the last page of the form does not seem to be posting the values to the payment gateway if it has received post data from the previous page.

Let me explain...

Example case one:

I run the last page of the form alone. It has received no post data. The onSubmit url of the form is set to http://developer.authorize.net/tools/paramdump/ for debugging purposes. I click the submit button and I get the following result from A.net.



This is good and what I expected.

Example case two:

In example case one I opened the form from a direct link. In this case I arrived at OnlineReservationsConf from another from with OnlineReservationsConf in the onSubmit url. When I clicked the submit button this time A.net gave me the following.



It seems that by having the form accept POST data that it no longer forwards the field values to A.net.

I have no plugin's enabled on any of the form pages. This is what my form setting are:



Where should I go from here to get those values forwarded to A.net?
DarksteelBlade 07 Oct, 2010
To make this post even longer I discovered what was causing this error. Under "Other Form Settings" under the "General" tab I changed the following settings:

-Check Token ==> Off
-Republish fields if error occurs ==> Don't Republish
-Renew Form Instance on Submit ==> New Instance


This setup now works as intended. Shortly I will make a new thread all nice and neat describing how to do this properly the first time. I'll put a link back to this thread so others can see the thought process.

Before I do does anyone have any feedback?
GreyHead 07 Oct, 2010
Hi DarkSteelBlade,

This looks OK to me. I don't know much about authorize.net but have just pulled down the SMI manual and take a quick look.

I think I'd do it pretty much as you have. Probably I'd make the last step a separate form outside the multi-page form that looks like a Confirmation page - but with the info in hidden inputs - and use the OnSubmit URL on that to do the redirection to Authorize.net.

Is there a way to make the $_POST array visible to more than one form without using the multi page plugin?
I tend to play safe and save to the database; the ChronoForms multi-page plug-in saves the data in the user session. Either of these will work OK. It's easier to save the whole array and use some PHP to unpack it into hidden inputs than have to manage all of the inputs separately.

Bob
This topic is locked and no more replies can be posted.