Alaska Software Inc. - Passing web page control
Username: Password:
AuthorTopic: Passing web page control
Allen LeePassing web page control
on Mon, 18 Dec 2006 12:07:51 -0800
Hi everyone;

THE SITUATION:

In Canada, our WAA app uses an real-time national credit card processor to
provide authorization for our web transactions.

Our DLL web page vaildates the data and sends to the third party credit card
processor's site:
  oHtml:put('<form action="https://www3.creditcard.com/HPPDP/index.php"
method=post>')
  oHtml:put('<input type="hidden" name="rvar1" value="'+cVAR1+'">')
  oHtml:put('<input type="hidden" name="rvar2" value="'+cVAR2+'">')
  oHtml:put('<input type="hidden" name="rvar3" value="'+cVAR3+'">')
  ...
  oHtml:put('<p><input type="submit" name="submit" value="Process the
transaction">')
  oHtml:put('</form>')

The credit card company sends a get string back to our standalone HTML page
which includes their additional authorized/declined data.
They require the standalone page.
This page parses the string, creates the variable names/data and redirects
to a page back into our DLL.

THE PROBLEM:

Sometimes their returned get string is not processed by our app.
We think they don't send the string back.

THE QUESTION:

How can we create a real-time check to ensure that each tranaction sent is
returned?
Phil Ide
Re: Passing web page control
on Mon, 18 Dec 2006 22:18:24 +0000
Allen,

> THE PROBLEM:
> 
> Sometimes their returned get string is not processed by our app.
> We think they don't send the string back.
> 
> THE QUESTION:
> 
> How can we create a real-time check to ensure that each tranaction sent is
> returned?

Well, that depends on exactly you mean by the question 

1.  If you want to find out whether they actualy performed a GET/POST on
your page, you can always check your server logs.

2. If you want to find out whether they passed any data back, then put some
error checking in the code.  This is a static HTML page on your webserver
correct?  In that case, you could write the page in PHP, which will allow
you to have the web page generate a log of it's own recording all
transactions it processes, plus any data it receives.

3. If you are using Apache (you can probably do this with other servers)
then you can put a rewrite rule that puts in a redirector and permanently
moved flag, which then redirects to your WAA DLL.  This might not work,
because many scripts won't follow redirectors or follow alternate URL's.

I had a similar problem here in the UK - eventually we got the return URL
sorted to be a perl CGI script which a) created a log and b) posted the
data into PostgreSQL.

Regards,

Phil Ide

---------------------
www.xbhcl.com
www.pbih.eu
www.idep.org.uk/xbase
---------------------
He does the work of three men: Larry, Moe and Curly.
Allen LeeRe: Passing web page control
on Tue, 19 Dec 2006 11:36:31 -0800
Hi Phil;

You provided some good suggestions.

Your #1.  Since there will be a number GET/POSTs in the server log within
the same time frame, wouldn't it be difficult to identify a specific
transaction since there are no unique identifiers stored in the Apache log?

Your #2. Where would the error checking go to find out if they passed any
data back?  Not on the static HTML page because it would not get called if
no data was sent back and not on DLL page that send the data because it has
terminated.
It is a static HTML page on your webserver that receives the data back from
the credit card processor.
The redirected DLL page from the static HTML page already records all
transactions it processes, plus any data it receives.   I have written a
user-activated sent/received data matching utility that will find unreturned
transaction requests but the client wants to know at the time that a return
string has not been received back so that the staff users of the application
can re-submit the transaction request..

Your #3. Would the Apache rewrite rule (that puts in a redirector and
permanently moved flag, which then redirects to the WAA DLL) suggestion work
if no data was sent back from the credit card processor?

The only solution  I can think of is:
 a)  write a small transaction ID named text file into a queue directory.
 b) delete the file when the return data is received.
 c) write a java program to run in the background that wakes up every 45
seconds to send an email if it finds orphaned files in the queue directory.

Do you think that would work?
Phil Ide
Re: Passing web page control
on Wed, 20 Dec 2006 03:07:08 +0000
Allen,

> The only solution  I can think of is:
>  a)  write a small transaction ID named text file into a queue directory.
>  b) delete the file when the return data is received.
>  c) write a java program to run in the background that wakes up every 45
> seconds to send an email if it finds orphaned files in the queue directory.
> 
> Do you think that would work?

Possibly, but I wouldn't like to do it that way.

What I don't understand, is when the cc processor calls your static web
page, the web page seems to do two things:

1. receive data
2. record that data

A static web page can't do either, unless it is running some script, which
would then run on the client machine not the server.  Theer are only two
exceptions to this I can think of:

a) The page is an SHTML page which calls a server script passing in the url
used to invoke it, and the script then logs the transaction using the GET
data appended to the url.

b) The page is a pre-processed page, for example .php

Can you enlighten me on how the mechanism works?  Without understanding
what is currently (supposed) to be happening, I'd only be guessing at a
solution.

Regards,

Phil Ide

---------------------
www.xbhcl.com
www.pbih.eu
www.idep.org.uk/xbase
---------------------
I used to have a life, then I got a modem.
Allen LeeRe: Passing web page control
on Wed, 20 Dec 2006 11:43:23 -0800
Hi Phil;

I have stripped out the non-essentials of the static HTML page that is
called by the cc processor so you can see that it accepts the data and
redirects the paired values to the WAA DLL.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>Credit Card Authorization</title>
<script type="text/javascript">
/*
Webmonkey GET Parsing Module
Language: JavaScript 1.0
The parsing of GET queries is fundamental to the basic functionality of
HTTP/1.0.
This module parses GET with JavaScript 1.0.
Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)
Author: Patrick Corcoran Email: patrick@taylor.org
*/

function createRequestObject() {
  FORM_DATA = new Object();
     The Object ("Array") where our data will be stored.
  separator = ',';
     The token used to separate data from multi-select inputs
  query = '' + this.location;
  qu = query
     Get the current URL so we can parse out the data.
     Adding a null-string '' forces an implicit type cast
     from property to string, for NS2 compatibility.
  query = query.substring((query.indexOf('?')) + 1);
     Keep everything after the question mark '?'.
  if (query.length < 1) { return false; }   Perhaps we got some bad data?
  keypairs = new Object();
  numKP = 1;
     Local vars used to store and keep track of name/value pairs
     as we parse them back into a usable form.
  while (query.indexOf('&') > -1) {
    keypairs[numKP] = query.substring(0,query.indexOf('&'));
    query = query.substring((query.indexOf('&')) + 1);
    numKP++;
       Split the query string at each '&', storing the left-hand side
       of the split in a new keypairs[] holder, and chopping the query
       so that it gets the value of the right-hand string.
  }
  keypairs[numKP] = query;
     Store what's left in the query string as the final keypairs[] data.<
  for (i in keypairs) {
    keyName = keypairs[i].substring(0,keypairs[i].indexOf('='));
       Left of '=' is name.
    keyValue = keypairs[i].substring((keypairs[i].indexOf('=')) + 1);
       Right of '=' is value.
    while (keyValue.indexOf('+') > -1) {
      keyValue = keyValue.substring(0,keyValue.indexOf('+')) + ' ' +
keyValue.substring(keyValue.indexOf('+') + 1);
         Replace each '+' in data string with a space.
    }
    keyValue = unescape(keyValue);
       Unescape non-alphanumerics
    if (FORM_DATA[keyName]) {
      FORM_DATA[keyName] = FORM_DATA[keyName] + separator + keyValue;
         Object already exists, it is probably a multi-select input,
         and we need to generate a separator-delimited string
         by appending to what we already have stored.
    } else {
      FORM_DATA[keyName] = keyValue;
         Normal case: name gets value.
    }
  }
  return FORM_DATA;
}
FORM_DATA = createRequestObject();
   This is the array/object containing the GET data.
   Retrieve information with 'FORM_DATA [ key ] = value'.
</script>
</head>
<body onLoad="createRequestObject();">
<script type="text/javascript">
var rvar1=FORM_DATA['rvar1'];
var rvar2=FORM_DATA['rvar2'];
var rvar3=FORM_DATA['rvar3'];

var cHEA,cBGC,cURL;
if (rvar1=='1') {cHEA='approved',cBGC='7FFFD4';}
else {cHEA='declined',cBGC='FFB6C1';}

document.write('<table bgcolor="#C6D7DE" width="75%" cellpadding=6
border=1>');
document.write('<tr><td bgcolor="#'+cBGC+'" align="center"
style="font-size:26px">Processing ...');
document.write('</table>');

cURL =
"/cgi-bin/waa1gate.exe?WAA_PACKAGE=iReg6&WAA_FORM=RegNew&cVAR1="+rvar1+"&cVA
R2="+rvar2+"&cVAR3="+rvar3;
window.location = cURL;
</script>
</body>
</html>

What don't you like about the background java program?
Phil Ide
Re: Passing web page control
on Wed, 20 Dec 2006 22:49:47 +0000
Allen,

> What don't you like about the background java program?

The Javascript is fine.  I am just surprised that their automated system
fetches the page and then runs the Javascript.  In fact, it's a very weird
way to do it - I would have expected them to call a CGI app and even
supplied a sample one written in perl or something.

Ok, so the problem you now have is how to record the data returned to the
page. One way to do it is to call another dll function passing in the raw
value of 'query'.  A simple way to do that is using the XMLHTTPRequest
object.  This can send a synchronous request to your dll, which can then
record the raw data, then the page will continue and call the usual
function using the redirect it is using now.

Does that sound ok to you?  I can give you some help using the
XMLHTTPRequest object - it's the same object used in Ajax and JSon calls.

Regards,

Phil Ide

---------------------
www.xbhcl.com
www.pbih.eu
www.idep.org.uk/xbase
---------------------
Taglines cause cancer.
Allen LeePassing web page control
on Wed, 20 Dec 2006 21:41:20 -0800
Hi Phil;

I don't quite understand.
The problem is not how to record the data returned to the page.
This line creates the paired values:

cURL ="/cgi-bin/waa1gate.exe?WAA_PACKAGE=iReg6
&WAA_FORM=RegNew&cVAR1="+rvar1+"&cVAR2="+rvar2+"&cVAR3="+rvar3;

And this line sends it back into the app for further processing:

window.location = cURL;

That works.
The problem is how to handle transactions that are NOT returned to the page.
That is why I suggested  a java program to run in the background outside of
the app.
Bruce AndersonRe: Passing web page control
on Tue, 19 Dec 2006 08:20:37 -0600
Perhaps you can use Phil's LoadFromURL( ) function to send this POST to your 
processor.
The processor will return the Accepted/Declined response, a string which is 
LoadFromURL's return value in your DLL.  Parse it and create the resultant 
page for your user.
LoadFromURL, the magical function with a thousand and one uses.  Thank you, 
Phil!
Allen LeeRe: Passing web page control
on Tue, 19 Dec 2006 11:40:22 -0800
Thanks Bruce;

What happens if the credit card processor drops the transaction and doesn't
send a return string back?
Then there won't be anything to re-direct ... right?
Have I misunderstood your point?
Bruce AndersonRe: Passing web page control
on Wed, 20 Dec 2006 16:02:31 -0600
Correct, you can wait a suitable length of time and then deal with the NIL. 
However, just because you received nothing from your processor does not mean 
that your customer has not been charged. You had better verify if your POST 
got through and was acted upon.  But, if this is a frequent problem with 
your current service provider, then you need to change something.  Failure 
to close the loop every time is a deal breaker.  Card processor, your ISP, 
your equipment, whatever is dying at the awkward moment must go.
Allen LeePassing web page control
on Wed, 20 Dec 2006 21:45:17 -0800
Hi Bruce;

You have understood the problem.
In this scenerio, how do you wait a suitable length of time and then deal
with the NIL?
Any suggestion?