Using Perl with USAePay

Simple Example Using LWP Module

Make sure to replace the UMkey parameter with your source key. Also, the example below uses our sandbox test server. Make sure to change the url to https://secure.usaepay.com/gate when ready to process production transactions

    use LWP::UserAgent;

    $ua = LWP::UserAgent->new;
    $res = $ua->post('https://sandbox.usaepay.com/gate', [
        'UMkey' => "Your_source_key_here",
        'UMname' => "Example Tester",
        'UMcard' => "4444555566667779",
        'UMexpir' => "0113",
        'UMcvv2' => "999",
        'UMamount' => "5.50",
        'UMinvoice' => "123456",
        'UMstreet' => "1234 Main Street",
        'UMzip' => "12345",
        'UMcommand' => 'cc:sale'
    ]);


    print "\n\nresult: ".$res->content;
    print "\n";

Source Key with Pin Example Using LWP Module

If your source key has been secured with a pin, you must generate and pass a hash authentication token to the server. The following example demonstrates this using the Digest::SHA1 module.

    use LWP::UserAgent;
    use Digest::SHA1  qw(sha1 sha1_hex sha1_base64);

    $sourcekey = 'Your_source_key_here';
    $pin = '1234';
    $command = 'cc:sale';
    $amount = '5.50';
    $invoice = '123123';

    # Generate Hash
    $seed = rand();
    $prehash = $command . ":" . $pin . ":" . $amount . ":" . $invoice . ":" . $seed;
    $hash = 's/' . $seed . '/' . sha1_hex($prehash) . '/n';


    $ua = LWP::UserAgent->new;
    $res = $ua->post('https://sandbox.usaepay.com/gate.php', [
        'UMkey' => $sourcekey,
        'UMhash' => $hash,
        'UMname' => "Example Tester",
        'UMcard' => "4444555566667779",
        'UMexpir' => "0113",
        'UMcvv2' => "999",
        'UMamount' => $amount,
        'UMinvoice' => $invoice,
        'UMstreet' => "1234 Main Street",
        'UMzip' => "12345",
        'UMcommand' => $command
    ]);


    print "\n\nresult: ".$res->content;
    print "\n";

Example Net::SSLeay Code

```
#!/usr/bin/perl

#########################################################
#Connect.pl
#Developed by Mind2Web for USAePay
#For question or comments email: mind2webinfo@yahoo.com
# OR support@usaepay.com
#
#The following is a perl script to gather,
#parse and verify form data that is then sent
#through SSL to the USAePay gateway for verification.
#The script requires and uses Net::SSLeay which can
#be found at http://symlabs.com/Net_SSLeay/ or through
#http://search.cpan.org You will also need to install
#openSSL from http://www.openssl.org and have perl
#5.6.1 or later to use Net::SSLeay.
#########################################################
#To use the program after installing required packages
#you can either use this script as is (not recommended
#since the script only parses the response of the
#gateway without displaying any messages), or you can
#create your own response handling script. There are
#two ways of accomplishing this:
#1. At the end of this script add more lines of code
# to handle messages.
#2. Create a script of your own and at the top write the
# command
# require 'connect.pl';
# This will execute the script at run time and continue
# executing your script and response handling code.
# Keep in mind though that this script does call
# use Net::SSLeay, prints the Content-type and parses
# the form and responses, therefore you do not need to
# add them into your code.
#
#Your web site should have an HTML form pointing to this
#script (or to your own if you chose to go with option 2).
#This script was written to check for the gateway required
#fields and will reload your form HTML with red warning
#messages where the missing fields are and the others will
#have the values that were specified byt he user.
#WARNING: this has to be an HTML page (not a script) or else
#the program will not perform properly. If you have a script
#generated form then you will need to disable this feature
#and create your own error handling.
#Go over to the config section to learn how to disable this feature if
#you wish to handle error messages yourself. You can see a
#sample form by looking at the formPage.htm file provided with
#this perl script.
#
#########################################################
#INSTRUCTIONS:
#We have included helpful hints in comments throughout the
#script. Please read them carefully and follow the instructions.
#You can also find instructions about the variables in which
#the gateway responses are held and how to access them at the
#end of the script.
#
#go over the Config setion below and change any variables
#to your own values.
#
#########################################################

####CONFIG SECTION
#go over the following code and change any value
#$formPage should be the path to the html page that contains the form.
#this will be used if there is a required field missing, the program
#will automatically reload the script with the values and a red
#notice that the required field is missing.
#In order for this feature to work the page has to be an HTML page and
#the `<input ...>` openning and closing tag has to be on the same line.
#that is when you open an input tag '<input ...' ther should be no
#new lines untill you close that tag '>'. If not the script may produce
#undesired response.
#IF you do not wish to have this feature, you can leave $formPage.
#Just put a comment '#' in front of the following line and uncomment
#the line below it.
$formPage = 'formPage.htm';
#$formPage = '';
#uncomment the above line to disable reloading the form page with
#error messages

#Your Source Key that is provided by usaepay
$sourceKey = 'Your_source_key_here';


#END CONFIG SECTION. Go to the bottom "OUTPUT SECTION" and add any code
#you need to change the output of the script

use Net::SSLeay qw(post_https make_form);

print "Content-type: text/html\n\n";

###Pare Form Input. The following lines of code will parse
#the form variables sent through the web page. It can handle
#both POST and GET methods.

if ($ENV{'REQUEST_METHOD'} eq "GET") {
$buffer = $ENV{'QUERY_STRING'};
} elsif ($ENV{'REQUEST_METHOD'} eq "POST") {
read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}

@cgiPairs = split(/&/,$buffer);
foreach $cgiPair (@cgiPairs)
{
($name,$value) = split(/=/,$cgiPair);
$value =~ s/\+/ /g;
$value =~ s/%(..)/pack("c",hex($1))/ge;
$form{$name} .= "\0" if (defined($form{$name}));
$form{$name} .= "$value";
}

##### END FORM PARSE. VALUES ARE IN %form
# form values can now be accessed by calling $form{'formVariableName'}
# depending on what the form variable name is
#####

##Below if statement checks to see if there is a source key
#if not then it will print eror message and exit.
if ($sourceKey =~ /^\s*$/) {
print "Error Missing Source Key. Please contact site admin\n";
exit;
}

##Below IF statement checks for all gateway required fields
#if any of them are missing, it will print an error message
#and exit the program. If you have put in a value for $formPage
#then it will reload the HTML page and display the error messages.
$required = 0;
if ($form{'UMcommand'} eq 'check' || $form{'UMcommand'} eq 'checkcredit')
{
if ($form{'UMrouting'} =~ /^\s*$/ ||
$form{'UMaccount'} =~ /^\s*$/ ||
$form{'UMssn'} =~ /^\s*$/ ||
$form{'UMdlnum'} =~ /^\s*$/ ||
$form{'UMdlstate'} =~ /^\s*$/)
{
$required = 1;
}
}
else
{
if ($form{'UMcard'} =~ /^\s*$/ ||
$form{'UMexpirM'} =~ /^\s*$/ ||
$form{'UMexpirY'} =~ /^\s*$/)
{
$required = 2;
}
}

if ($required == 1 || $required == 2 ||
$form{'UMamount'} =~ /^\s*$/ ||
$form{'UMinvoice'} =~ /^\s*$/ ||
$form{'UMname'} =~ /^\s*$/ ||
$form{'UMstreet'} =~ /^\s*$/ ||
$form{'UMzip'} =~ /^\s*$/)
{
print "`<center>``<font color=\"red\" size=\"3\">`Error missing parameter`</font>``</center>`\n";
#if any form feild missing, read form page, find missing fields, display with double red asterisks.
if ($formPage)
{
open (formHTML, "$formPage")|| die"cannot open form page. Please click back button and complete required fields manually\n";
while (`<formHTML>`){
$line = $_;

if ($required == 0)
{
$line =~ s/(`<input.*type.*=.*"UMcard"[^>`]*)(>)/$1 value="$form{'UMcard'}">/;
$line =~ s/(`<input.*type.*=.*"UMexpirM"[^>`]*)(>)/$1 value="$form{'UMexpirM'}">/;
$line =~ s/(`<input.*type.*=.*"UMexpirY"[^>`]*)(>)/$1 value="$form{'UMexpirY'}">/;
$line =~ s/(`<input.*type.*=.*"UMrouting"[^>`]*)(>)/$1 value="$form{'UMrouting'}">/;
$line =~ s/(`<input.*type.*=.*"UMaccount"[^>`]*)(>)/$1 value="$form{'UMaccount'}">/;
$line =~ s/(`<input.*type.*=.*"UMssn"[^>`]*)(>)/$1 value="$form{'UMssn'}">/;
$line =~ s/(`<input.*type.*=.*"UMdlnum"[^>`]*)(>)/$1 value="$form{'UMdlnum'}">/;
$line =~ s/(`<input.*type.*=.*"UMdlstate"[^>`]*)(>)/$1 value="$form{'UMdlstate'}">/;
}

if ($required == 1)
{
if ($form{'UMrouting'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMrouting".*/) {
$line =~ s/(`<input.*type.*=.*"UMrouting"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Routing.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMrouting"[^>`]*)(>)/$1 value="$form{'UMrouting'}">/;
}

if ($form{'UMaccount'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMaccount".*/) {
$line =~ s/(`<input.*type.*=.*"UMaccount"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Account Number.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMaccount"[^>`]*)(>)/$1 value="$form{'UMaccount'}">/;
}

if ($form{'UMssn'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMssn".*/) {
$line =~ s/(`<input.*type.*=.*"UMssn"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field SSN.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMssn"[^>`]*)(>)/$1 value="$form{'UMssn'}">/;
}

if ($form{'UMdlnum'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMdlnum".*/) {
$line =~ s/(`<input.*type.*=.*"UMdlnum"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Driver's License Number.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMdlnum"[^>`]*)(>)/$1 value="$form{'UMdlnum'}">/;
}

if ($form{'UMdlstate'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMdlstate".*/) {
$line =~ s/(`<input.*type.*=.*"UMdlstate"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field State Where Driver's License Was Issued.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMdlstate"[^>`]*)(>)/$1 value="$form{'UMdlstate'}">/;
}

$line =~ s/(`<input.*type.*=.*"UMcard"[^>`]*)(>)/$1 value="$form{'UMcard'}">/;
$line =~ s/(`<input.*type.*=.*"UMexpirM"[^>`]*)(>)/$1 value="$form{'UMexpirM'}">/;
$line =~ s/(`<input.*type.*=.*"UMexpirY"[^>`]*)(>)/$1 value="$form{'UMexpirY'}">/;
}

if ($required == 2)
{
if ($form{'UMcard'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMcard".*/) {
$line =~ s/(`<input.*type.*=.*"UMcard"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Card Number.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMcard"[^>`]*)(>)/$1 value="$form{'UMcard'}">/;
}

if ($form{'UMexpirM'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMexpirM".*/) {
$line =~ s/(`<input.*type.*=.*"UMexpirM"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Expire Date Month.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMexpirM"[^>`]*)(>)/$1 value="$form{'UMexpirM'}">/;
}

if ($form{'UMexpirY'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMexpirY".*/) {
$line =~ s/(`<input.*type.*=.*"UMexpirY"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Expire Date Year.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMexpirY"[^>`]*)(>)/$1 value="$form{'UMexpirY'}">/;
}

$line =~ s/(`<input.*type.*=.*"UMrouting"[^>`]*)(>)/$1 value="$form{'UMrouting'}">/;
$line =~ s/(`<input.*type.*=.*"UMaccount"[^>`]*)(>)/$1 value="$form{'UMaccount'}">/;
$line =~ s/(`<input.*type.*=.*"UMssn"[^>`]*)(>)/$1 value="$form{'UMssn'}">/;
$line =~ s/(`<input.*type.*=.*"UMdlnum"[^>`]*)(>)/$1 value="$form{'UMdlnum'}">/;
$line =~ s/(`<input.*type.*=.*"UMdlstate"[^>`]*)(>)/$1 value="$form{'UMdlstate'}">/;
}

if ($form{'UMamount'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMamount".*/) {
$line =~ s/(`<input.*type.*=.*"UMamount"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Amount.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMamount"[^>`]*)(>)/$1 value="$form{'UMamount'}">/;
}

if ($form{'UMinvoice'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMinvoice".*/) {
$line =~ s/(`<input.*type.*=.*"UMinvoice"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Invoice Number.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMinvoice"[^>`]*)(>)/$1 value="$form{'UMinvoice'}">/;
}

if ($form{'UMname'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMname".*/) {
$line =~ s/(`<input.*type.*=.*"UMname"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Customer Name.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMname"[^>`]*)(>)/$1 value="$form{'UMname'}">/;
}

if ($form{'UMstreet'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMstreet".*/) {
$line =~ s/(`<input.*type.*=.*"UMstreet"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Customer Address Street.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMstreet"[^>`]*)(>)/$1 value="$form{'UMstreet'}">/;
}

if ($form{'UMzip'} =~ /^\s*$/) {
if ($line =~ /<input.*type.*=.*"UMzip".*/) {
$line =~ s/(`<input.*type.*=.*"UMzip"[^>`]*>)/$1`<font color=\"red\" size=\"1\">`Missing Required Field Customer Address Zip.`<\/font>`\n/;
}
} else {
$line =~ s/(`<input.*type.*=.*"UMzip"[^>`]*)(>)/$1 value="$form{'UMzip'}">/;
}
print "$line\n";
}
close (formHTML);
}
exit;
}


###Following lines format the fields to gateway specs.
$form{'UMcard'} =~ s/[^0-9]//g;
$form{'UMexpirM'} =~ s/[^0-9]//g;
$form{'UMexpirY'} =~ s/[^0-9]//g;
$form{'UMexpir'} = "$form{'UMexpirM'}$form{'UMexpirY'}";
$form{'UMamount'} =~ s/[^0-9\.]//g;


#All required fields are checked and formatted
#Now we need to save them in a hash array and submit them through
#Net::SSLeay to the gateway

#Uncomment the following line to enable tracing (for debugging)
#values are: 0=no debugging, 1=ciphers, 2=trace, 3=dump data
#$Net::SSLeay::trace = 2;

#gather all the cgi form variables to be sent to the gateway.
%formData = make_form (
#'UMkey' => $form{'UMkey'},
'UMkey' => $sourceKey,
'UMauthCode' => $form{'UMauthCode'},
'UMrefNum' => $form{'UMrefNum'},
'UMcard' => $form{'UMcard'},
'UMexpir' => $form{'UMexpir'},
'UMrouting' => $form{'UMrouting'},
'UMaccount' => $form{'UMaccount'},
'UMamount' => $form{'UMamount'},
'UMtax' => $form{'UMtax'},
'UMcustid' => $form{'UMcustid'},
'UMinvoice' => $form{'UMinvoice'},
'UMponum' => $form{'UMponum'},
'UMticket' => $form{'UMticket'},
'UMdescription' => $form{'UMdescription'},
'UMcvv2' => $form{'UMcvv2'},
'UMcustemail' => $form{'UMcustemail'},
'UMcustreceipt' => $form{'UMcustreceipt'},
'UMname' => $form{'UMname'},
'UMstreet' => $form{'UMstreet'},
'UMzip' => $form{'UMzip'},
'UMssn' => $form{'UMssn'},
'UMdlnum' => $form{'UMdlnum'},
'UMdlstate' => $form{'UMdlstate'},
'UMip' => $form{'UMip'},
'UMcommand' => $form{'UMcommand'},
'UMredir' => $form{'UMredir'},
'UMredirApproved' => $form{'UMredirApproved'},
'UMredirDeclined' => $form{'UMredirDeclined'},
'UMechofields' => $form{'UMechofields'},
'UMechounsafe' => $form{'UMechounsafe'},
'UMtestmode' => $form{'UMtestmode'},
'UMrecurring' => $form{'UMrecurring'},
'UMbillamount' => $form{'UMbillamount'},
'UMschedule' => $form{'UMschedule'},
'UMnumleft' => $form{'UMnumleft'},
'UMstart' => $form{'UMstart'},
'UMbillfname' => $form{'UMbillfname'},
'UMbilllname' => $form{'UMbilllname'},
'UMbillcompany' => $form{'UMbillcompany'},
'UMbillstreet' => $form{'UMbillstreet'},
'UMbillstreet2' => $form{'UMbillstreet2'},
'UMbillcity' => $form{'UMbillcity'},
'UMbillstate' => $form{'UMbillstate'},
'UMbillzip' => $form{'UMbillzip'},
'UMbillcountry' => $form{'UMbillcountry'},
'UMbillphone' => $form{'UMbillphone'},
'UMemail' => $form{'UMemail'},
'UMfax' => $form{'UMfax'},
'UMwebsite' => $form{'UMwebsite'},
'UMshipfname' => $form{'UMshipfname'},
'UMshiplname' => $form{'UMshiplname'},
'UMshipcompany' => $form{'UMshipcompany'},
'UMshipstreet' => $form{'UMshipstreet'},
'UMshipstreet2' => $form{'UMshipstreet2'},
'UMshipcity' => $form{'UMshipcity'},
'UMshipstate' => $form{'UMshipstate'},
'UMshipzip' => $form{'UMshipzip'},
'UMshipcountry' => $form{'UMshipcountry'},
'UMshipphone' => $form{'UMshipphone'},
'UMcardauth' => $form{'UMcardauth'},
'UMpares' => $form{'UMpares'},
'UMxid' => $form{'UMxid'},
'UMcavv' => $form{'UMcavv'},
'UMeci' => $form{'UMeci'},
);
#send data via SSLeay and gather encrypted reply.

my $host = 'www.usaepay.com';
my $script = '/gate.php';
my $port = '443';

$Net::SSLeay::ssl_version = 3;

my ($replyData, $reply_type, %reply_headers)
######  post_https($host, $port, $script, '',%formData);


####Parse the reponse from the gateway.
@replyPairs = split(/&/,$replyData);
foreach $replyPair (@replyPairs)
{
($name,$value) = split(/=/,$replyPair);
$value =~ s/\+/ /g;
$value =~ s/%(..)/pack("c",hex($1))/ge;
$reply{$name} .= "\0" if (defined($reply{$name}));
$reply{$name} .= "$value";
}


###REPLY FORMAT AND INSTRUCTIONS ON HOW TO ACCESS THEM
#The Gateway sends a reply through form variables
#you can find more description about these variables on
#the usaepay web site. Follow the link to the
#Developer's Center -> Developer's Library -> USA ePay Gateway API
#currently found at:
#http://www.usaepay.com/topics/api.html
#the replies are stored in the %reply hash array and can
#be access by specifying the key. For example, to find the
#status of the transaction, you would access it through the
#variable $reply{'UMstatus'} which should be Approved for a
#successful transaction.

####OUTPUT SECTION:
#following is a generic unprocessed output of the gateway's response.
#you will need to change the code to format it to your site's look and feel
#and give your users a more informative result.
print "replyData = $replyData `<br>`\n response = $response `<br>`\nreply headers:`<br>`\n";
foreach $key (keys %reply_headers)
{
print "$key: $reply_headers{$key}`<br>`\n";
}

#return results to user's script.
```

Example HTML FORM Code

:::html

<form action="connect.pl" method="POST">
<table border="1" width="80%">
<tr>
<td>Card Number</td>
<td><input type="text" name="UMcard" size="12"></td>
</tr>
<tr>
<td>Expire Date (MM/YY)</td>
<td><input type="text" name="UMexpirM" size="2" maxlength="2">/
<input type="text" name="UMexpirY" size="2" maxlength="2"></td>
</tr>
<tr>
<td>Amount</td>
<td>$<input type="text" name="UMamount" size="6"></td>
</tr>
<tr>
<td>Invoice Number</td>
<td><input type="text" name="UMinvoice" size="12"></td>
</tr>
<tr>
<td>Customer Name</td>
<td><input type="text" name="UMname" size="20"></td>
</tr>
<tr>
<td>Street</td>
<td><input type="text" name="UMstreet" size="20"></td>
</tr>
<tr>
<td>Zip</td>
<td><input type="text" name="UMzip" size="5" maxlength="5"></td>
</tr>
<tr>
<td align="center"><input type="submit" name="submit" value="Submit"></td>
<td align="center"><input type="reset" name="reset" value="reset"></td>
</tr>
</table>
</form>

Troubleshooting

We've noticed that because of some updates to NetSSL that the code above may need to be modified in order to get everything working.

If you are getting a "Specified Source Key Not Found" even when placing a proper value for the Key you may need to modify the code:

The line in connect.pl:

%formData = make_form (

should be:

$formData_ref = make_form (

and the line in connect.pl:

my ($replyData, $reply_type, %reply_headers) = post_https($host, $port, $script, '', %formData);

should be:

my ($replyData, $reply_type, %reply_headers) = post_https($host, $port, $script, '', $formData_ref);

Change Log

1.2

  • Typos in code of connect.pl fixed 03/04/04

1.0 -> 1.2

  • Added support for VBV and MSC as well as other fields (tax, po...). 10/15/03