C (and C++) Code v. 1.2
Description
This program will read the input from an HTML form. After processing the form values, it will set up an SSL session to forward the values to the USA ePay gateway. Response from the gateway is then saved in a string variable resultStatus. Detailed descriptions and instructions can be found by going through the source code and reading the comments.
Requirements and Installation Instructions
The most important element in this program is the W3c's libwww library. It can be found online at http://www.w3.com/Library. This library is used to communicate with the gateway, post results and retrieve responses. To ensure a secure transaction, you also need to install OpenSSL. It also uses a module transport wrapper so that libwww can use SSL by Olga Antropova http://www.w3.org/Library/src/SSL/WWWSSL.html.
It is highly recommended that you install OpenSSL first and then configure libwww to use OpenSSL, before compiling and installing libwww. If you are using a current version of Linux distro such as Red Hat 7 or Mandrake 8, OpenSSL and libwww can be found in the Cds RPM packages. We recommended using these RPMs, as long as you don't mind using a generic build. More advanced developers may want to download the most current source and compile it themselves. The SSL wrapper should come with libwww. The program will work with both Windows and Linux operating systems.
If you are using Windows (and do not have libwww already installed) it would be easier to use Microsoft's WinInet. You can find a detailed description of WinInet and its functions from Microsoft's MSDN http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wininet/wininet/wininet_functions.asp If you decide to use WinInet, you will need libwww but it is not designed for WinInet (to use winInet you will need to write another program).
Optional
The program uses a cgi library called cgi-html by Noel V Aguilar found at http://www.geocities.com/SiliconValley/Vista/6493/projects/cgi-lib.html. It was used to facilitate the parsing and usage of form variables. You are not required to use this library, since you may have a library of your own that you prefer. The most important parts of this application are the libwww functions which show you how to set up and use an SSL session. If you choose not to use cgi-html, you will need to manually erase or "comment out" the following library functions:
- mime_header("text/html");
- LIST *head;
- head = cgi_input_parse();
- html_begin("C Newtek Gateway Gateway connect",NULL);
- find_val(head, "formVariable")
- html_end();
Compiling the Program
Compiling under Windows should be easy and straightforward using a compiler such as Visual C++. Remember to include you libwww Object/Library path in Project Settings->Link tab.
To compile under Linux, using gcc for example, you will need to point to the library paths during compilation. To compile with libwww, SSL and cgi-html you would need to type something similar to:
gcc -o "yourCGIFileName.cgi" libwww-config --cflags
yourSourceFile.c libwww-config --libs
-L/usr/lib -lwwwssl /path/to/cgi-html/library/cgi-lib.a
This is assuming you installed libwww in /usr/lib.
To install without cgi-html, all you need to do is take out the path at the end of the command:
gcc -o "yourCGIFileName.cgi" libwww-config --cflags
yourSourceFile.c libwww-config --libs
-L/usr/lib -lwwwssl
It would be a good idea to run the commands:
libwww-config --cflags
&
libwww-config --libs
before compiling, to see the exact path of your libwww and the modules installed. If you can find the SSL wrapper -lwwwssl in the list, then you won't need to add the -L/usr/lib -lwwwssl at the end.
Running the Program
Copy the compiled file into your website's cgi folder. Remember to make sure the permissions are set up correctly. On Linux you will need to change chgrp and chown to a username that can run cgi files, also make sure to chmod to 755.
Warning
Use an HTML form with the action pointing to the cgi file. If you run the program without any form fields sent through either GET or POST you will probably receive an "Internal Server Error." This is because cgi-html will output an error message that there are no form fields, before outputting a content-type, which is necessary for normal http operation. You can circumvent this error by adding an "if" statement to check if there is a QUERY_STRING and if the CONTENT_LENGTH is greater than zero in the environment variables. Then execute the command head = cgi_input_parse(); or else print your own error message with a proper content-type.
Example Code
/*Code for libwwwPost.c
/*Written by min2web for USAEpay
for questions or comments you can contact us at:
support@newtekgateway.com
OR
mind2webinfo@yahoo.com
*/
/*this program requires libwww libraries found at
http://www.w3.org/Library
to contact and submit info to the server.
You will also need to have the SSL wrapper for libwww wwwssl.*/
#include "WWWLib.h"
#include "WWWHTTP.h"
#include "WWWInit.h"
#include "WWWSSL.h"
#include `<stdio.h>`
#include `<stdlib.h>`
/*In this program we are using the ANSI C library cgi-html by Noel V Aguilar
found at
http://www.geocities.com/SiliconValley/Vista/6493/projects/cgi-lib.html
It is not necessary to use this library. You can simply replace it with your
own form parsing function.*/
#include "cgi-lib/cgi-lib.h" /* include the cgi-lib.h header file THIS SHOULD BE
THE PATH TO THE cgi-html LIBRARY */
#include "cgi-lib/html-lib.h" /* include the html-lib.h header file THIS SHOULD
BE THE PATH TO THE cgi-html LIBRARY */
/*as mentioned above you are not required to use the cgi-html
library, it is only used in this program to facilitate the form
processing functions. The main focus of the program is the libwww
functions*/
//we set a variable of type HTChunk that will eventually contain the server response.
PRIVATE HTChunk * result = NULL;
char resultStatus[1000];
//The following two functions tell libwww what to do in case of
//messages and trace. We will see these set as callback functions later on
PRIVATE int printer (const char * fmt, va_list pArgs)
{
return (vfprintf(stdout, fmt, pArgs));
}
PRIVATE int tracer (const char * fmt, va_list pArgs)
{
return (vfprintf(stderr, fmt, pArgs));
}
//The following function describes what to do when libwww's main
//event loop terminates. That is after libwww has contacted the
//server and has recieved the result. This is where you might like
//to add your own response handling function.
PRIVATE int terminate_handler (HTRequest * request, HTResponse * response,
void *param, int status)
{
if (status == HT_LOADED && result && HTChunk_data(result)) {
//HTPrint("%s", HTChunk_data(result));
sprintf(resultStatus, "%s", HTChunk_data(result));
printf("\nresultStatus = %s", resultStatus);
/*Results are saved in string resultStatus. For further validation comment out the
above printf code,
instead put your own URLdecoding function to decode the server's response and
display it to your users.*/
HTChunk_delete(result);
}
/* We are done with this request */
HTRequest_delete(request);
HTSSLhttps_terminate();
/* Terminate libwww */
HTProfile_delete();
exit(status ? status : 0);
}
int main (int argc, char ** argv)
{
HTRequest * request = NULL;
HTAnchor * anchor = NULL;
HTAssocList * formfields = NULL;
char * uri = "https://secure.newtekgateway.com/gate.php";
//Initiate CGI session. This is from cgi-html
mime_header("text/html");
//LIST that cgi-html uses.
LIST *head;
//parse form variables. cgi-html
head = cgi_input_parse();
//print HTML header. cgi-html
html_begin("C Newtek Gateway Gateway connect",NULL);
printf("`<pre>`\n");
char string[10000];
//The following "if" statements determine if the required fields are found
sprintf(string, "%s", find_val(head, "UMkey"));
//find_val is a cgi-html function that returns the value of the form key.
if (find_val(head, "UMkey") == NULL || strcmp(string, "") == 0)
{
printf("`<center>``<h1>`ERROR`</h1>``<br>`Source Key not found. Cannot complete
operation.");
html_end();
return 0;
}
if ((find_val(head, "UMcard") != NULL && find_val(head, "UMexpir") != NULL)
||
(find_val(head, "UMrouting") != NULL && find_val(head, "UMaccount") !=
NULL
&& find_val(head, "UMssn") != NULL && find_val(head, "UMdlnum") != NULL
&& find_val(head, "UMdlstate") != NULL))
{
if (find_val(head, "UMamount") == NULL ||
find_val(head, "UMinvoice") == NULL ||
find_val(head, "UMname") == NULL ||
find_val(head, "UMstreet") == NULL ||
find_val(head, "UMzip") == NULL )
{
printf("`<center>``<h1>`ERROR`</h1>``<br>`Missing form fields.`<br>`Please click the
back button and complete all required fields.`<br>` Cannot complete operation.");
html_end();
return 0;
}
}
else
{
printf("`<center>``<h1>`ERROR`</h1>``<br>`Missing form fields.`<br>`Please click the
back button and complete all required fields.`<br>` Cannot complete operation.");
html_end();
return 0;
}
//Initiate SSL wrapper for libwww
/* Create a new preemptive client */
HTProfile_newNoCacheClient("TestApp", "1.0");
HTSSL_protMethod_set (HTSSL_V23);
HTSSL_verifyDepth_set (2);
//Be careful of the following init statement. If set to YES it could
//initiate a blocking session. Currently it is set to NO to have a
//non-blocking https communication. If you have problems receiving a
//response from the server, you may want to try setting the value to YES.
HTSSLhttps_init(NO);
/* Need your own trace and print functions */
HTPrint_setCallback(printer);
HTTrace_setCallback(tracer);
/* Get trace messages, change the 0 to 1 to see more detailed trace
message*/
#if 0
HTSetTraceMessageMask("sop");
#endif
/* Add our own filter to update the history list */
HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
/* Set the timeout to how long we will wait for a response */
HTHost_setEventTimeout(10000);
/* Create a list to hold the form arguments */
if (!formfields) formfields = HTAssocList_new();
/* Parse the content and add it to the association list */
/*you can add as many more fields as you want here*/
sprintf(string, "UMkey=%s", find_val(head, "UMkey"));
HTParseFormInput(formfields, string);
sprintf(string, "UMauthCode=%s", find_val(head, "UMauthCode"));
HTParseFormInput(formfields, string);
sprintf(string, "UMrefNum=%s", find_val(head, "UMrefNum"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcard=%s", find_val(head, "UMcard"));
HTParseFormInput(formfields, string);
sprintf(string, "UMexpir=%s", find_val(head, "UMexpir"));
HTParseFormInput(formfields, string);
sprintf(string, "UMrouting=%s", find_val(head, "UMrouting"));
HTParseFormInput(formfields, string);
sprintf(string, "UMaccount=%s", find_val(head, "UMaccount"));
HTParseFormInput(formfields, string);
sprintf(string, "UMamount=%s", find_val(head, "UMamount"));
HTParseFormInput(formfields, string);
sprintf(string, "UMtax=%s", find_val(head, "UMtax"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcustid=%s", find_val(head, "UMcustid"));
HTParseFormInput(formfields, string);
sprintf(string, "UMinvoice=%s", find_val(head, "UMinvoice"));
HTParseFormInput(formfields, string);
sprintf(string, "UMponum=%s", find_val(head, "UMponum"));
HTParseFormInput(formfields, string);
sprintf(string, "UMticket=%s", find_val(head, "UMticket"));
HTParseFormInput(formfields, string);
sprintf(string, "UMdescription=%s", find_val(head, "UMdescription"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcvv2=%s", find_val(head, "UMcvv2"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcustemail=%s", find_val(head, "UMcustemail"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcustreceipt=%s", find_val(head, "UMcustreceipt"));
HTParseFormInput(formfields, string);
sprintf(string, "UMname=%s", find_val(head, "UMname"));
HTParseFormInput(formfields, string);
sprintf(string, "UMstreet=%s", find_val(head, "UMstreet"));
HTParseFormInput(formfields, string);
sprintf(string, "UMzip=%s", find_val(head, "UMzip"));
HTParseFormInput(formfields, string);
sprintf(string, "UMssn=%s", find_val(head, "UMssn"));
HTParseFormInput(formfields, string);
sprintf(string, "UMdlnum=%s", find_val(head, "UMdlnum"));
HTParseFormInput(formfields, string);
sprintf(string, "UMdlstate=%s", find_val(head, "UMdlstate"));
HTParseFormInput(formfields, string);
sprintf(string, "UMip=%s", find_val(head, "UMip"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcommand=%s", find_val(head, "UMcommand"));
HTParseFormInput(formfields, string);
sprintf(string, "UMredir=%s", find_val(head, "UMredir"));
HTParseFormInput(formfields, string);
sprintf(string, "UMredirApproved=%s", find_val(head, "UMredirApproved"));
HTParseFormInput(formfields, string);
sprintf(string, "UMredirDeclined=%s", find_val(head, "UMredirDeclined"));
HTParseFormInput(formfields, string);
sprintf(string, "UMechofields=%s", find_val(head, "UMechofields"));
HTParseFormInput(formfields, string);
sprintf(string, "UMechounsafe=%s", find_val(head, "UMechounsafe"));
HTParseFormInput(formfields, string);
sprintf(string, "UMtestmode=%s", find_val(head, "UMtestmode"));
HTParseFormInput(formfields, string);
sprintf(string, "UMrecurring=%s", find_val(head, "UMrecurring"));
HTParseFormInput(formfields, string);
sprintf(string, "UMschedule=%s", find_val(head, "UMschedule"));
HTParseFormInput(formfields, string);
sprintf(string, "UMnumleft=%s", find_val(head, "UMnumleft"));
HTParseFormInput(formfields, string);
sprintf(string, "UMstart=%s", find_val(head, "UMstart"));
HTParseFormInput(formfields, string);
sprintf(string, "UMemail=%s", find_val(head, "UMemail"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillfname=%s", find_val(head, "UMbillfname"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbilllname=%s", find_val(head, "UMbilllname"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillcompany=%s", find_val(head, "UMbillcompany"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillstreet=%s", find_val(head, "UMbillstreet"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillstreet2=%s", find_val(head, "UMbillstreet2"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillcity=%s", find_val(head, "UMbillcity"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillstate=%s", find_val(head, "UMbillstate"));
HTParseFormInput(formfields, string);
sprintf(string, "umbillzip=%s", find_val(head, "UMbillzip"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillcountry=%s", find_val(head, "UMbillcountry"));
HTParseFormInput(formfields, string);
sprintf(string, "UMbillphone=%s", find_val(head, "UMbillphone"));
HTParseFormInput(formfields, string);
sprintf(string, "UMemail=%s", find_val(head, "UMemail"));
HTParseFormInput(formfields, string);
sprintf(string, "UMfax=%s", find_val(head, "UMfax"));
HTParseFormInput(formfields, string);
sprintf(string, "UMwebsite=%s", find_val(head, "UMwebsite"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipfname=%s", find_val(head, "UMshipfname"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshiplname=%s", find_val(head, "UMshiplname"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipcompany=%s", find_val(head, "UMshipcompany"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipstreet=%s", find_val(head, "UMshipstreet"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipstreet2=%s", find_val(head, "UMshipstreet2"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipcity=%s", find_val(head, "UMshipcity"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipstate=%s", find_val(head, "UMshipstate"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipzip=%s", find_val(head, "UMshipzip"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipcountry=%s", find_val(head, "UMshipcountry"));
HTParseFormInput(formfields, string);
sprintf(string, "UMshipphone=%s", find_val(head, "UMshipphone"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcardauth=%s", find_val(head, "UMcardauth"));
HTParseFormInput(formfields, string);
sprintf(string, "UMpares=%s", find_val(head, "UMpares"));
HTParseFormInput(formfields, string);
sprintf(string, "UMxid=%s", find_val(head, "UMxid"));
HTParseFormInput(formfields, string);
sprintf(string, "UMcavv=%s", find_val(head, "UMcavv"));
HTParseFormInput(formfields, string);
sprintf(string, "UMeci=%s", find_val(head, "UMeci"));
HTParseFormInput(formfields, string);
if (uri && formfields) {
/* Create a request */
request = HTRequest_new();
/* Set the default output to "asis" */
HTRequest_setOutputFormat(request, WWW_SOURCE);
/* Get an anchor object for the URI */
anchor = HTAnchor_findAddress(uri);
/* Post the data and get the result in a chunk */
result = HTPostFormAnchorToChunk(formfields, anchor, request);
/* Clean up the form fields */
HTAssocList_delete(formfields);
/* Go into the event loop... */
HTEventList_loop(request);
} else {
printf("`<center>``<h1>`ERROR`</h1>``<br>`Missing form fields.`<br>`Please click the
back button and complete all required fields.`<br>` Cannot complete operation.");
html_end();
return 0;
}
printf("`</pre>`\n");
html_end();
return 0;
}
Example HTML FORM Code
<html>
<head>
<title>Credit Card sample form</title>
</head>
<body>
<form action="path/to/your/cgi/folder/yourCGIexecutable.cgi" method="POST">
<input type="hidden" name="UMkey" value="YOUR_SOURCE_KEY_HERE">
<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>
</body>
</html>
Change Log
1.0.1 -> 1.2 Added support for VBV and MSC as well as other fields (tax, po...). 10/15/03