Page 1 of 2
Keeping connection alive while processing credit card info
Posted: Wed Jun 08, 2005 10:20 am
by dreamscape
Greetings all.
I am having this problem with my ecommerce web server, where sometimes during checkout a client's browser may time out while awaiting credit card authorization. This does not happen alot, but it can and I'm looking for a solution.
In the section of the application that it happens basically flows like this:
receive customer payment info -> validate input (ok) -> process payment (ok) -> insert order into database -> email receipt -> forward to success page
It is fairly straghtforward. The "process payment" occurs in the background and flows like this:
build authorization message -> establish connection with payment gateway via CURL -> send message -> receive response -> process response (ok or fail)
Between "send message" and "receive response" the script is just waiting on the response from the payment gateway.
It is this step, awaiting the gateway's response, that can take some time. I would guess that it can take up to 2 minutes, though usually it is received in about 15-30 seconds.
I have increased the PHP execution time to avoid the script timing out. I have also increased PHP's socket timeout to avoid the connection with the payment gateway timing out while awaiting the response.
However, I am looking for a solution to avoid the client's browser timing out after 60 seconds, which seems to be what most browsers have as their time out.
I have yet to find a solution that will keep the connection between PHP and the client's browser alive while it waits on the gateway response.
Can anyone provide any assistance?
Posted: Wed Jun 08, 2005 10:28 am
by dreamscape
if it helps any, the section of code that sends the messages to the gateway and awaits on the response is the following function in the payment gateway class. This function generates the message (using "generateTransactionData"), sends & receives the response, and then sets up the response into an associative array
Code: Select all
function processTransaction() {
$this->generateTransactionData();
unset($gateway_response);
if (function_exists('curl_init')) {
$authNetConnection = curl_init();
curl_setopt($authNetConnection, CURLOPT_URL, $this->authNetURL);
curl_setopt($authNetConnection, CURLOPT_USERAGENT, $this->UserAgent);
curl_setopt($authNetConnection, CURLOPT_POST, 1);
curl_setopt($authNetConnection, CURLOPT_POSTFIELDS, $this->transaction_URLdata);
curl_setopt($authNetConnection, CURLOPT_RETURNTRANSFER, 1);
$gateway_response = curl_exec($authNetConnection);
curl_close($authNetConnection);
} else {
exec("{$this->curl_path} -d \"{$this->transaction_URLdata}\" {$this->authNetURL}", $tmpresponse);
$gateway_response = '';
foreach ($tmpresponse as $key => $value) {
$gateway_response .= $value;
}
}
$response_vars = explode($this->delim_char, $gateway_response);
$len = sizeof($this->response_fields);
$j=0;
for($i=0; $i< $len; $i++) {
if ($this->response_fields[$i]) {
$this->response[$this->response_fields[$i]] = $response_vars[$i];
} else {
$j++;
$this->response["x_custom_$j"] = $response_vars[$i];
}
}
}
Posted: Wed Jun 08, 2005 10:53 am
by Syranide
it should be the script or so timing out I believe, IE (apache, or whatever it is) won't force timeout til after an hour or so, this should be PHP timing out, try making the time limit (set_time_limit) a little higher. however, this can be set from webserver too, meaning that it might be the webserver that closes the connection.
however, a better solution might be a self-refreshing page which queries from a database or so, which is updated when the transaction has been done, thus eliminating 1min load time too (which can be confusing).
Posted: Wed Jun 08, 2005 11:05 am
by dreamscape
Actually it is the web browser that is timing out. I know this because the script executes to completion. the order is processed, credit card authorized, and order placed in the database, but the customer does not think it has gone through because their browser timed out waiting for the form to process.
As I mentioned I did have problems with the CURL connection timing out, but I cleared this up by increasing the PHP socket timeout. And as I mentioned, I have also increased the script execution time to keep PHP from timing out.
The problem that remains is the browser timing out waiting for the form to process (i.e, page to load)
I prefer to not use a self-refreshing page. That is such an ugly solution, no offense meant for the suggestion. I am really looking for something more elegant and smooth to the end user. I see this all the time at the "big boys" of ecommerce where you get the page "please wait while we process your order. this may take a few minutes" and your browser will sit there (seemingly waiting for the next page to load) and wait for 2 minutes if necessary without timing out.
Posted: Wed Jun 08, 2005 11:24 am
by Syranide
dreamscape wrote:I prefer to not use a self-refreshing page. That is such an ugly solution, no offense meant for the suggestion. I am really looking for something more elegant and smooth to the end user. I see this all the time at the "big boys" of ecommerce where you get the page "please wait while we process your order. this may take a few minutes" and your browser will sit there (seemingly waiting for the next page to load) and wait for 2 minutes if necessary without timing out.
that is exactly what yours does? it waits for the script to end? and no, that wasn't quite what I meant, what you do is you have a page that updates every 5 sec or so, and queries the status from the database, this prevents browsers locking up, timing out, and other problems, also presents your customers with stable approach, instead of the old... uhm, this might take a sek... or minutes... uhm, heck, could take 10min... or no... it has already been done, but the browser has locked up or timed out without telling so. regardless of action, loading a page should generally not take more than 1 sec if you ask me, otherwise people keep hitting that refresh button 15 times and making more or more purchases, alternatively getting an "already ordered" text with a question in their forehead.
Posted: Wed Jun 08, 2005 11:25 am
by dreamscape
I suppose I should add I am a Mac OS X user. I am not exactly sure of the request timeouts of other browsers. However, most of the customers of this particular site are Mac OS X users also who use Apple's Safari web browser, which has a default request time out of 60 seconds.
Posted: Wed Jun 08, 2005 11:30 am
by dreamscape
Syranide wrote:loading a page should generally not take more than 1 sec if you ask me
Ha, that may be true if everyone was on a T3

Posted: Wed Jun 08, 2005 11:33 am
by dreamscape
Syranide wrote:that is exactly what yours does? it waits for the script to end? and no, that wasn't quite what I meant, what you do is you have a page that updates every 5 sec or so
Yes I know that is what you meant. IMO, that is an ugly solution. Pages that refresh themselves every 5 seconds or so are horrible, IMO.
Posted: Wed Jun 08, 2005 11:36 am
by Burrito
fixed the cURL you said you did? Tried posting directly to the action page (eliminating the call to authorize.net) have you?
If so, the same result you should see (assuming fixed correctly the cURL you did).
Another authorize.net function I have...uses AIM it does (with cURL).
if interested in it you are, let me know you should.
assuming you are using authorize.net I am based on: CURLOPT_URL, $this->authNetURL
Posted: Wed Jun 08, 2005 12:01 pm
by dreamscape
sorry, I don't speak yoda
Posted: Wed Jun 08, 2005 12:05 pm
by Syranide
dreamscape wrote:Syranide wrote:that is exactly what yours does? it waits for the script to end? and no, that wasn't quite what I meant, what you do is you have a page that updates every 5 sec or so
Yes I know that is what you meant. IMO, that is an ugly solution. Pages that refresh themselves every 5 seconds or so are horrible, IMO.
well there are only two options, either you make it wait and wait for the script to finish, or you make a self-refreshing page... there are no other alternatives those are the two main strategies, thus could be modified, but still resulting in the very same behaviour.
Posted: Wed Jun 08, 2005 12:18 pm
by dreamscape
I am looking into the XML HTTP Object now, which basically provides the same functionality as the self-refreshing page would, but without the unsightliness.
I believe this way, I also can make just a simple header GET or POST request to a script that checks the order status in the database and just returns a true or false to the waiting page.
Posted: Wed Jun 08, 2005 12:23 pm
by dreamscape
Burrito wrote:fixed the cURL you said you did? Tried posting directly to the action page (eliminating the call to authorize.net) have you?
If so, the same result you should see (assuming fixed correctly the cURL you did).
Another authorize.net function I have...uses AIM it does (with cURL).
if interested in it you are, let me know you should.
assuming you are using authorize.net I am based on: CURLOPT_URL, $this->authNetURL
Didn't mean to offend you if I did, but seriously the only thing you said that I understood was "curl" and "authorize.net"
1. Yes I have fixed the curl to keep it from timing out
2. Why would I want to eliminate the call to a payment gateway in a eCommerce checkout?
3. Thanks, but I don't need any authorize.net gateway functions. I already have an Authorize.net AIM class for managing transactions that works wonderfully.
4. Authorize.net is not the problem. While technically speaking, maybe, because the script is waiting on authorize.net; however, replace authorize.net with XXX processor and the result will be the same (script waiting on XXX processor).
Posted: Wed Jun 08, 2005 12:24 pm
by Syranide
as I said, modifications, that is if any an ugly solution if you ask me as using JScript for such things itn't very good, browsers don't support JScript that good, AND that object is pure IE I think.
safest way? have a hidden frame, but still, that also provides some problems as all browsers don't support JScript... and I'd bet someone would be furious if his browser would just stay there for an hour.
sure there are ways to fix it, but all with probability of failure.
Posted: Wed Jun 08, 2005 12:28 pm
by dreamscape
Syranide wrote:as I said, modifications, that is if any an ugly solution if you ask me as using JScript for such things itn't very good, browsers don't support JScript that good, AND that object is pure IE I think.
IE on windows, Konqueror on Linux, Safari on OS X, Opera 7.6 on all platforms, and Mozilla on all platforms support client side javascript HTTP Request objects.