I think that InnoDB tables and related foreign keys with transactions would be a great advantage for OpenCart. There wouldn't be any lost records, relations pointing nowhere and half-processed actions. Consistent data are pretty important in e-commerce and in my projects I benefit of this technology quite often.
I made my first sale today on my site. 
Unfortunately, the order info did not appear in the admin section and I had to email the customer to find out what he ordered.
I have implemented Bruce's "paypal improved" contribution.
What else should I do?
Thanks,
Amin

Unfortunately, the order info did not appear in the admin section and I had to email the customer to find out what he ordered.
I have implemented Bruce's "paypal improved" contribution.
What else should I do?
Thanks,
Amin
Hi,
I think I am in the same boat as Amin.
I've set Opencart to test mode and created the 2 relevant accounts in the PayPal Dev sandbox (a buyer and a seller). My test account on my client's site has their email set to being the one used by my buyer Dev account. Initially, I used the paypal payment implementation that comes with OpenCart 0.77.
The first test run I did appeared to work smoothly, with the buyer getting the invoice confirmation, and the seller getting a request to capture the funds. The amounts were correct were to be processed correctly on the paypal side of things (buyer account was charged the correct amount and seller account was credited the right amount).
However, on reviewing my order history back on the Opencart-based solution I am developing, it was empty. I also logged in to the admin section and checked the orders there, but that was also empty. To be triple sure, I checked the relevant MySQL table which was also empty.
So, the payment appears to have been processed correctly, but the order has disappeared. As Amin has done, this can be worked around by emailing the customer and asking what they ordered, but not an ideal solution.
I also now have an issue from that same account where any further orders are confronted with an error from Paypal upon checkout; "This invoice has already been paid. For more information, please contact the merchant." I have also attempted the updated version of paypal.php (v1.0), but with no change.
Not sure if either issue is directly related to the callback function as I know I certainly returned back to the OpenCart site after confirming the order @ paypal (i.e. I clicked on the big orange button that said "return to merchant's site"), but any advice than anyone could give me would be greatly appreciated. Thank you.
I think I am in the same boat as Amin.
I've set Opencart to test mode and created the 2 relevant accounts in the PayPal Dev sandbox (a buyer and a seller). My test account on my client's site has their email set to being the one used by my buyer Dev account. Initially, I used the paypal payment implementation that comes with OpenCart 0.77.
The first test run I did appeared to work smoothly, with the buyer getting the invoice confirmation, and the seller getting a request to capture the funds. The amounts were correct were to be processed correctly on the paypal side of things (buyer account was charged the correct amount and seller account was credited the right amount).
However, on reviewing my order history back on the Opencart-based solution I am developing, it was empty. I also logged in to the admin section and checked the orders there, but that was also empty. To be triple sure, I checked the relevant MySQL table which was also empty.
So, the payment appears to have been processed correctly, but the order has disappeared. As Amin has done, this can be worked around by emailing the customer and asking what they ordered, but not an ideal solution.
I also now have an issue from that same account where any further orders are confronted with an error from Paypal upon checkout; "This invoice has already been paid. For more information, please contact the merchant." I have also attempted the updated version of paypal.php (v1.0), but with no change.
Not sure if either issue is directly related to the callback function as I know I certainly returned back to the OpenCart site after confirming the order @ paypal (i.e. I clicked on the big orange button that said "return to merchant's site"), but any advice than anyone could give me would be greatly appreciated. Thank you.
In the installation instructions, I mentioned that you have to put some specific values into a language file AND you have to create an additional payment status for every supported language. If you do not do these things correctly, nothing will happen.
here is the relevant code from paypal.php that uses these values. As you can see, if the language file does not have the status value, no order is created. However, you might expect to see the die() error displayed. This can happen, but only if the paypal callback does not occur before you return from the web site (sometimes it gets there first).
The following is not a fix, but you could try a test with this extra line at the beginning of the else clause. This will give you a processed order anyway but with pending status and would indicate that your setup of the "improved" paypal is incorrect.
here is the relevant code from paypal.php that uses these values. As you can see, if the language file does not have the status value, no order is created. However, you might expect to see the die() error displayed. This can happen, but only if the paypal callback does not occur before you return from the web site (sometimes it gets there first).
Code: Select all
$sql = "select `order_status_id` from `order_status` where `name` = '?' and `language_id` = '?'";
$parsed = $this->database->parse($sql, $this->language->get('order_status_paid_unconfirmed'), $this->language->getId());
$results = $this->database->getRow($parsed);
if ($results)
{
$this->order->process($results['order_status_id']);
}
else
{
// I think it may be better to die here with a message as it is
// a major configuration problem that should be found by even
// the most basic testing and hence not impact upon a customer.
die('Configuration error: You MUST have created an order status for "Paid Unconfirmed" for every installed language. The following sql statement returned no rows ' . $parsed);
// The following is a reasonable alternative but there is no way without making
// changes to checkout_failure, to get a user defined message to the that page.
// The message, as above, is a big help in tracking any teething problems with this code.
//$this->response->redirect($this->url->ssl('checkout_failure'));
}
Code: Select all
else
{
$this->order->process();
// I think it may be better to die here with a message as it is
...
}
Thanks Bruce. I went into the admin area and created the "Paid Unconfirmed" order status. Everything works fine now. Apologies for the foolish oversight! 
For others who raised the question, I can confirm (after testing) that callback fails are not related to .htaccess.
I also heartily recommend enabling the "auto-redirect" in your Business paypal account so as to take away that element of possible error away from the user's control.

For others who raised the question, I can confirm (after testing) that callback fails are not related to .htaccess.
I also heartily recommend enabling the "auto-redirect" in your Business paypal account so as to take away that element of possible error away from the user's control.

bruce,
in your coding example you say that the code needs to go into the callback() function located in the /catalog/extension/payment/paypal.php
where exactly do you insert this code ?
here is the example of the function from the file to make it easier for you:
in your coding example you say that the code needs to go into the callback() function located in the /catalog/extension/payment/paypal.php
where exactly do you insert this code ?
here is the example of the function from the file to make it easier for you:
Code: Select all
function callback() {
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$req .= '&' . $key . '=' . urlencode(stripslashes($value));
}
$header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n";
$header .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
$header .= 'Content-Length: ' . strlen($req) . "\r\n\r\n";
if (!$this->config->get('paypal_test')) {
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
} else {
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
}
if ($fp) {
fputs($fp, $header . $req);
while (!feof($fp)) {
$res = fgets($fp, 1024);
if (strcmp($res, 'VERIFIED') == 0) {
$this->order->load($this->request->get('invoice', 'post'));
$this->order->process();
}
}
fclose($fp);
}
}
It was good that you posted the code snippet.
It shows me that you have not installed the paypal improved contribution but are, instead using the one that comes with the default installation of opencart. Download and install this. http://www.opencart.com/contribution/do ... sion_id/48
Make sure to follow the installation instructions carefully and completely, otherwise it does not work.
After you have done that, the instructions here http://forum.opencart.com/index.php/top ... ml#msg4035 and here http://forum.opencart.com/index.php/top ... ml#msg4506 will make sense.
cheers,
Bruce

Make sure to follow the installation instructions carefully and completely, otherwise it does not work.
After you have done that, the instructions here http://forum.opencart.com/index.php/top ... ml#msg4035 and here http://forum.opencart.com/index.php/top ... ml#msg4506 will make sense.
cheers,
Bruce
ok installed the new code...
my orders still stay in Paid Unconfirmed on the return to checkout_success.php (im in paypal test mode if that matters)
the order obviously enters fine and the cart clears correctly though, anything you can think of that would be causing this ?
my orders still stay in Paid Unconfirmed on the return to checkout_success.php (im in paypal test mode if that matters)
the order obviously enters fine and the cart clears correctly though, anything you can think of that would be causing this ?
Last edited by dvfd9 on Mon Apr 07, 2008 10:54 am, edited 1 time in total.
Most likely the callback does not arrive which is exactly the circumstance this contribution attemps to address. If you want to confirm that, write some sort of logging code (file or database) into the beginning of the callback function and test again. If you are testing on a web site that is not on the internet then the callback cannot find you.
I got it,
edit: maybe not. and i'm on a live site with access to a sandbox paypal account for testing
does this function look correct? i left in all your comments and etc sorry for the mess
edit: maybe not. and i'm on a live site with access to a sandbox paypal account for testing
does this function look correct? i left in all your comments and etc sorry for the mess
Code: Select all
function callback() {
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$req .= '&' . $key . '=' . urlencode(stripslashes($value));
}
$header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n";
$header .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
$header .= 'Content-Length: ' . strlen($req) . "\r\n\r\n";
if (!$this->config->get('paypal_test')) {
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
} else {
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
}
if ($fp)
{
fputs($fp, $header . $req);
while (!feof($fp))
$res = fgets($fp, 1024);
fclose($fp);
$pos = strpos($res, 'VERIFIED');
if ($pos === false)
{
// Payment is not verified so there is nothing we need to do.
}
else
{
//
// The payment is verified so we try to change the status from Paid Unconfirmed to Pending
// but only if the status is currently Paid Unconfirmed. A change to any other value
// has probably been made by the store administrator.
//
// Remember also, that we are not relying on this to succeed and that it is being
// executed by a callback from paypal. Hence there is no error recovery required.
//
$paidUnconfirmedStatus = 0;
$pendingStatus = 0;
$sql = "select `order_status_id` from `order_status` where `name` = '?' and `language_id` = '?'";
$parsed = $this->database->parse($sql, $this->language->get('order_status_pending'), $this->language->getId());
$results = $this->database->getRow($parsed);
if ($results)
{
$pendingStatus = $results['order_status_id'];
}
//
// Perhaps the IPN from paypal has arrived before the user has returned from
// the paypal web site OR the user has not returned at all.
// In response to either case, we should load and process the order.
//
$reference = $this->request->get('invoice', 'post');
if ($this->order->load($reference))
{
// IPN is winner or customer never returned and IPN arrived.
// default status should be Pending so the update below will have no
// effect if we process the order here but the end result is still correct.
$this->order->process();
}
else
{
$this->order->process();
// I think it may be better to die here with a message as it is
// a major configuration problem that should be found by even
// the most basic testing and hence not impact upon a customer.
die('Configuration error: You MUST have created an order status for "Paid Unconfirmed" for every installed language. The following sql statement returned no rows ' . $parsed);
// The following is a reasonable alternative but there is no way without making
// changes to checkout_failure, to get a user defined message to the that page.
// The message, as above, is a big help in tracking any teething problems with this code.
//$this->response->redirect($this->url->ssl('checkout_failure'));
}
$sql = "update `order` set `order_status_id` = '?' where `reference` = '?' and `order_status_id` = '?'";
// bug fix from asif
//$parsed = $this->database->parse($sql, $paidUnconfirmedStatus, $reference, $pendingStatus);
$parsed = $this->database->parse($sql, $pendingStatus, $reference, $paidUnconfirmedStatus);
$this->database->query($parsed);
}
// $reference = $this->request->get('invoice', 'post');
// $sql = "update `order` set `order_status_id` = '?' where `reference` = '?' and `order_status_id` = '?'";
// // bug fix from asif
// //$parsed = $this->database->parse($sql, $paidUnconfirmedStatus, $reference, $pendingStatus);
// $parsed = $this->database->parse($sql, $pendingStatus, $reference, $paidUnconfirmedStatus);
// $this->database->query($parsed);
//}
}
}
Last edited by dvfd9 on Mon Apr 07, 2008 11:25 am, edited 1 time in total.
Hi Patrick,
Attached is a version of catalog\extension\payment\paypal.php which I believe contains all of the patches for paypal improved. Within the next 4 weeks, I will be releasing a complete contribution with better admin and no need for the language file hacks this uses to find the order status values.
Please ensure that you have followed all of the instructions from the original download and this should be fine for you. If there are problems, please let me know.
Also check the order status values in the table itself, depending on the version of opencart, the admin gui for order status does not work. (other patches for this on the forums).
Kind Regards
Bruce
Attached is a version of catalog\extension\payment\paypal.php which I believe contains all of the patches for paypal improved. Within the next 4 weeks, I will be releasing a complete contribution with better admin and no need for the language file hacks this uses to find the order status values.
Please ensure that you have followed all of the instructions from the original download and this should be fine for you. If there are problems, please let me know.
Also check the order status values in the table itself, depending on the version of opencart, the admin gui for order status does not work. (other patches for this on the forums).
Kind Regards
Bruce
Attachments
[The extension has been deactivated and can no longer be displayed.]
that would be great effort by you and will be well acknowledged... keep it upbruce wrote: Attached is a version of catalog\extension\payment\paypal.php which I believe contains all of the patches for paypal improved. Within the next 4 weeks, I will be releasing a complete contribution with better admin and no need for the language file hacks this uses to find the order status values.

Hi Bruce,
I have followed all the instructions correctly and I am getting the same error as Patrick. Do you have any suggestions as to why the error is occuring? I downloaded the latest version v0.7.8, although I've tried it with v.0.7.7 and neither have worked. I have tried installing and uninstalling but still no luck. Any thoughts?
Thanks,
Lindsey
I have followed all the instructions correctly and I am getting the same error as Patrick. Do you have any suggestions as to why the error is occuring? I downloaded the latest version v0.7.8, although I've tried it with v.0.7.7 and neither have worked. I have tried installing and uninstalling but still no luck. Any thoughts?
Thanks,
Lindsey
Who is online
Users browsing this forum: No registered users and 7 guests