It seems many of us have been having problems with Ubercart orders becoming stuck in pending and transactions never going through with the Paypal Sandbox. Anyways after 3 days of working on this issue and some help from Wombat and code samples from Ttol I found a solution that works for me. Although this Does work for me I have only tested it on the paypal sandbox and need others to tell me of any possible issues or problems with this code.
Anyways the issue seemed to be with the IPN verification process on Ubercarts end, most of our shared hosting servers (Mine is GoDaddy) seem to not be able to post back to verify an IPN via ssl (paypal sandbox's site). It appears that the problem is with the fsock function opening a socket, it just times out.
Taking some code from an old forum (Ttol) I merged this script into the uc_paypal module from line 577 - 705. I just replaced that code with the following, which uses the function "curl" to verify a valid or invalid IPN:
<?php
//Custom curl function for Godaddy Ubercart Usage, Thanks TToll and Wombat
$req = 'cmd=_notify-validate';
foreach (
$_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
if (variable_get('uc_paypal_wpp_server', '') == 'https://api-3t.paypal.com/nvp') {
$domain = 'https://www.paypal.com/cgi-bin/webscr';
}
else {
$domain = variable_get('uc_paypal_wps_server', 'https://www.sandbox.paypal.com/cgi-bin/webscr');
}
$ch = curl_init();
curl_setopt ($ch,CURLOPT_URL,$domain);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt ($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt ($ch, CURLOPT_HEADER , 0);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
//curl_setopt ($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt ($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt ($ch, CURLOPT_PROXY,"http://proxy.shr.secureserver.net:3128");
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt ($ch, CURLOPT_URL, $domain);
curl_setopt ($ch, CURLOPT_TIMEOUT, 120);
$my_curl_result = curl_exec($ch);
curl_close($ch);
// END CURL POSTBACK MECHANISM
// assign posted variables to local variables
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$payment_fee = $_POST['mc_fee'];
$receiver_email = $_POST['receiver_email'];
$txn_id = $_POST['txn_id'];
$txn_type = $_POST['txn_type'];
$payer_email = $_POST['payer_email'];
// END CURL POSTBACK MECHANISM
if (!$my_curl_result) {
watchdog('uc_paypal', t('IPN failed with HTTP error.'), WATCHDOG_ERROR);
return;
}
if (
strcmp ($my_curl_result, "VERIFIED") == 0) {
watchdog('uc_paypal', t('IPN transaction verified.'));
$duplicate = db_result(db_query("SELECT COUNT(*) FROM {uc_payment_paypal_ipn} WHERE txn_id = '%s' AND status != 'Pending'", $txn_id));
if ($duplicate > 0) {
if ($order->payment_method != 'credit') {
watchdog('uc_paypal', t('IPN transaction ID has been processed before.'), WATCHDOG_NOTICE);
}
return;
}
db_query("INSERT INTO {uc_payment_paypal_ipn} VALUES (%d, '%s', '%s', '%s', "
."'%s', '%s', '%s', %d)", $order_id, $txn_id, $txn_type,
$payment_amount, $payment_status, $receiver_email, $payer_email,
time());
/*if (variable_get('uc_paypal_wps_email', '') != $receiver_email) {
watchdog('uc_paypal', t('IPN received for an e-mail that is not your primary e-mail: !email', array('!email' => $receiver_email)));
}*/
switch ($payment_status) {
case 'Canceled_Reversal':
uc_order_comment_save($order_id, 0, t('PayPal has cancelled the reversal and returned !amount !currency to your account.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'admin');
break;
case
'Completed':
$comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
uc_cart_complete_sale($order);
uc_order_comment_save($order_id, 0, t('Payment of !amount !currency submitted through PayPal.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)), 'order', 'payment_received');
uc_order_comment_save($order_id, 0, t('PayPal IPN reported a payment of !amount !currency.', array('!amount' => uc_currency_format($payment_amount, FALSE), '!currency' => $payment_currency)));
break;
case
'Denied':
uc_order_comment_save($order_id, 0, t("You have denied the customer's payment."), 'admin');
break;
case
'Expired':
uc_order_comment_save($order_id, 0, t('The authorization has failed and cannot be captured.'), 'admin');
break;
case
'Failed':
uc_order_comment_save($order_id, 0, t("The customer's attempted payment from a bank account failed."), 'admin');
break;
case
'Pending':
uc_order_update_status($order_id, 'paypal_pending');
uc_order_comment_save($order_id, 0, t('Payment is pending at PayPal: !reason', array('!reason' => _uc_paypal_pending_message(check_plain($_POST['pending_reason'])))), 'admin');
break;
// You, the merchant, refunded the payment.
case 'Refunded':
$comment = t('PayPal transaction ID: @txn_id', array('@txn_id' => $txn_id));
uc_payment_enter($order_id, 'paypal_wps', $payment_amount, $order->uid, NULL, $comment);
break;
case
'Reversed':
watchdog('uc_paypal', t('PayPal has reversed a payment!'), WATCHDOG_ERROR);
uc_order_comment_save($order_id, 0, t('Payment has been reversed by PayPal: !reason', array('!reason' => _uc_paypal_reversal_message(check_plain($_POST['reason_code'])))), 'admin');
break;
case
'Processed':
uc_order_comment_save($order_id, 0, t('A payment has been accepted.'), 'admin');
break;
case
'Voided':
uc_order_comment_save($order_id, 0, t('The authorization has been voided.'), 'admin');
break;
}
}
else if (strcmp ($my_curl_result, "INVALID") == 0) {
watchdog('uc_paypal', t('IPN transaction failed verification.'), WATCHDOG_ERROR);
uc_order_comment_save($order_id, 0, t('An IPN transaction failed verification for this order.'), 'admin');
}
}
?>If you see anything wrong with this code or any future problems let me know, otherwise it is working as a solution for me.
r00tk1ll
