News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

Paid Subscriptions - Always enddate 2005 and Status is Finished

Started by agentblackhat, October 20, 2014, 07:45:56 AM

Previous topic - Next topic

Sir Osis of Liver

Part of the problem seems to be here -

ManagePaid.php



// Check this is definitely a valid gateway!
$fp = fopen($sourcedir . '/' . $file, 'rb');
$header = fread($fp, 4096);
fclose($fp);

if (strpos($header, '// SMF Payment Gateway: ' . strtolower($matches[1])) !== false)
{
loadClassFile($file);

$gateways[] = array(
'filename' => $file,
'code' => strtolower($matches[1]),
// Don't need anything snazier than this yet.
'valid_version' => class_exists(strtolower($matches[1]) . '_payment') && class_exists(strtolower($matches[1]) . '_display'),
'payment_class' => strtolower($matches[1]) . '_payment',
'display_class' => strtolower($matches[1]) . '_display',
);
}



$gateway['code'] comes up empty, which causes the process to error out when it gets here -

subscriptions.php



// We need to see whether we can find the correct payment gateway,
// we'll going to go through all our gateway scripts and find out
// if they are happy with what we have.
$txnType = '';
$gatewayHandles = loadPaymentGateways();
foreach ($gatewayHandles as $gateway)
{
$gatewayClass = new $gateway['payment_class']();
if ($gatewayClass->isValid())
{
$txnType = $gateway['code'];
break;
}
}

if (empty($txnType))
generateSubscriptionError($txt['paid_unknown_transaction_type']);



Also looks like you have to add this here -

Subscriptions-PayPal.php



/// Is this a normal payment?
public function isPayment()
{
if ($_POST['payment_status'] == 'Completed' && $_POST['txn_type'] == 'web_accept')
return true;

else if ($_POST['payment_status'] == 'Completed' && $_POST['txn_type'] == 'subscr_payment')
return true;

else
return false;
}



Tried a few things, but can't get it to go.  No activation, no pending payment, just the two errors.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

If $gateway['code'] is coming up empty, I'd have to ask if there is an extra file in the folder that shouldn't be there for some reason.

There is more code in 2.1 than just those changes, though in terms of processing subscr_payment... you realise I keep bringing this up for a reason, right?

Sir Osis of Liver

Quote from: Arantor on December 04, 2014, 03:32:33 PM
If $gateway['code'] is coming up empty, I'd have to ask if there is an extra file in the folder that shouldn't be there for some reason.

Are you referring to /Sources?  My test forum is pretty much a scratch install.  OP's forum has around 20 mods installed, so there are additional source files.  He also has an .htaccess in forum root containing pretty urls mod.  The two installs are quite different, problem is exactly the same.

Quote
in terms of processing subscr_payment... you realise I keep bringing this up for a reason, right?

Can't figure why subscr_payment is not working, with the change to Subscriptions-PayPal.php, but as far as I can see, the 'Unknown Paid Subscriptions transaction type' error only occurs if $txnType is empty, and that comes from loadPaymentGateways() in ManagePaid.php.  If the entire process were in one file, might be able to grasp it, but as it is, makes my old brain feel like a pingpong ball.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

The entire reason I keep bringing this stuff up is that I made more changes to the entire workflow in 2.1 than simply the bit you seem to think I might have done. There's entire branches of process flow added for conditional testing that have been missed out here.

Do a comparison of both subscriptions.php and the PayPal handler against 2.0's files and see how different they are.

Sir Osis of Liver

For support purposes I need a fix for 2.0, those are the forums I'm trying to help.  Now that I've duplicated the problem on a test install, I have the opportunity to work on it without limitations.  If recurring payments ever worked on any 2.0 forum (I'm fairly certain it did), it doesn't work now, possibly due to changes in 2.0 updates or in PayPal API.  The basic problem doesn't seem that difficult, but the payment verification and subscription activation process is spread out over at least three files, and I'm not understanding it well enough to fix it.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

And again, I will reiterate that if people tested all the changes in 2.1 as a group, the relevant changes could be isolated and backported. Doing so just in the *hopes* of a fix is a scary amount of work.

Kindred

and I will note, Krash...  recurring payments *DO* work on many system - including this site.


What I'd suggest now ---   is install 2.1 on the system and see if it processes differently
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Sir Osis of Liver

Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

Quote from: Kindred on December 05, 2014, 02:02:08 PM
and I will note, Krash...  recurring payments *DO* work on many system - including this site.

Um, yes?

Sir Osis of Liver

Ooops, not seeing well tonight.  Just d/led 2.1 beta, will replace alpha and give it a try.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Sir Osis of Liver

Can't set up a $0.10 test sub, only allows integers for cost.  Too rich for my budget.  Theme's a bit hard to look at, very cluttered.

Back to 2.0.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

And you couldn't have looked at this any time in the preceding... 6 months? As in before this got to public beta?

Sir Osis of Liver

Don't have a PP business account, so can only test recurring payments when I have access to someone else's business account, which is rarely.

Just for the halibut, uploaded subscriptions.php, ManagePaid.php, and Subscriptions-PayPal.php from 2.1 to my 2.0.9 test install, and I get the same two errors.  Non-recurring doesn't work either, get one error.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Sir Osis of Liver

Ok, here's a puzzle.

subscriptions.php does this -



// We need to see whether we can find the correct payment gateway,
// we'll going to go through all our gateway scripts and find out
// if they are happy with what we have.
$txnType = '';
$gatewayHandles = loadPaymentGateways();
foreach ($gatewayHandles as $gateway)
{
$gatewayClass = new $gateway['payment_class']();
if ($gatewayClass->isValid())
{
$txnType = $gateway['code'];
break;
}
}

if (empty($txnType))
generateSubscriptionError($txt['paid_unknown_transaction_type']);



loadPaymentGateways() is in ManagePaid.php -



// Load all the payment gateways.
function loadPaymentGateways()
{
global $sourcedir;

$gateways = array();
if ($dh = opendir($sourcedir))
{
while (($file = readdir($dh)) !== false)
{
if (is_file($sourcedir .'/'. $file) &&

preg_match('~^Subscriptions-([A-Za-z\d]+)\.php$~', $file, $matches))
{
// Check this is definitely a valid gateway!
$fp = fopen($sourcedir . '/' . $file, 'rb');
$header = fread($fp, 4096);
fclose($fp);

if (strpos($header, '// SMF Payment Gateway: ' .

strtolower($matches[1])) !== false)
{
loadClassFile($file);

$gateways[] = array(
'filename' => $file,
'code' => strtolower($matches[1]),
// Don't need anything snazier than this yet.
'valid_version' =>

class_exists(strtolower($matches[1]) . '_payment') && class_exists(strtolower($matches[1]) . '_display'),
'payment_class' => strtolower($matches[1])

. '_payment',
'display_class' => strtolower($matches[1]) .

'_display',
);
}
}
}
}
closedir($dh);

return $gateways;
}



When I dump the $gateways[] array I get this -



array(1) { [0]=> array(5) { ["filename"]=> string(24) "Subscriptions-PayPal.php" ["code"]=> string(6) "paypal"

["valid_version"]=> bool(true) ["payment_class"]=> string(14) "paypal_payment" ["display_class"]=>

string(14) "paypal_display" } }



$txnType = $gateway['code']; should make $txnType = 'paypal', but instead it's empty and subscriptions.php errors out.

If I assign values from the array to $txnType and $gatewayClass -



$txnType = '';
$gatewayHandles = loadPaymentGateways();
foreach ($gatewayHandles as $gateway)
{
// $gatewayClass = new $gateway['payment_class']();
$gatewayClass = 'paypal_payment';
if ($gatewayClass->isValid())
{
$txnType = $gateway['code'];
break;
}
}

$txnType = 'paypal';

if (empty($txnType))
generateSubscriptionError($txt['paid_unknown_transaction_type']);



.... subscription is unsuccessful but there are no errors.  It appears that $gatewayHandles is empty, so the loadPaymentGateways() function does not work in subscriptions.php, but does work in ManagePaid.php

Have no idea what this means.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Sir Osis of Liver

Is it possible to use a local <form> to post IPN data to subscriptions.php for test purposes?
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

agentblackhat

Krash, keep a running total of all the money you're sending me, I don't want to have to refund each one of those payments, there are loads! I can refund in one payment then.

Sir Osis of Liver


The thought occurred, late last night, that perhaps Old Krash has been flogging the wrong end of the horse.

Mr. Obvious asks:  When recurring payment fails, where's the pending subscription?

Hint:  If subscriptions.php receives an IPN and there is no pending subscription, it will error out exactly as it's doing here.


Quote from: agentblackhat on December 08, 2014, 05:45:27 AM
Krash, keep a running total of all the money you're sending me, I don't want to have to refund each one of those payments, there are loads! I can refund in one payment then.

Don't worry about that for now, it'll take me a couple of hours to straighten out my PapPal account if I'm ever done with this.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Sir Osis of Liver

Ok, mopes, Old Krash may be old and slow, but sometimes gets there in the end.  Here's the problem -

The PayPal email address in Paid Subscriptions is set for [email protected].  When you subscribe and uncheck recurring payments, the post data returns business: [email protected]Subscriptions-PayPal.php compares $_POST['business'] to the email address setting, here -



// This function returns true/false for whether this gateway thinks the data is intended for it.
public function isValid()
{
global $modSettings;

// Has the user set up an email address?
if (empty($modSettings['paypal_email']))
return false;
// Check the correct transaction types are even here.
if ((!isset($_POST['txn_type']) && !isset($_POST['payment_status'])) || (!isset($_POST['business']) && !isset($_POST['receiver_email'])))
return false;
/// Correct email address?
if (!isset($_POST['business']))
$_POST['business'] = $_POST['receiver_email'];
if ($modSettings['paypal_email'] != $_POST['business'] && (empty($modSettings['paypal_additional_emails']) || !in_array($_POST['business'], explode(',', $modSettings['paypal_additional_emails']))))
return false;
return true;
}



If they match, function isValid() returns 'true' to subscriptions.php, here -



$txnType = '';
$gatewayHandles = loadPaymentGateways();
foreach ($gatewayHandles as $gateway)
{
$gatewayClass = new $gateway['payment_class']();
if ($gatewayClass->isValid())
{
$txnType = $gateway['code'];
break;
}
}

if (empty($txnType))
generateSubscriptionError($txt['paid_unknown_transaction_type']);



... and the subscription is processed correctly.


When you subscribe and check recurring payments (it's checked by default), the post data returns business: [email protected].  For reasons unknown, PayPal forwards [email protected] to a second account, [email protected].  The payment interface is completely different, so I'm guessing that [email protected] is a personal account, and [email protected] is the business account required for recurring payments.  Apparently PayPal uses the personal account for nonrecurring subscriptions, but forwards to the business account for recurring.  When this occurs, $_POST['business'] does not match the PayPal email setting, isValid() returns 'false', and $txnType is empty, causing subscriptions.php to error out, and subscription fails.

The solution is to use the business account as the PayPal email address in Paid Subscription settings.  Tried it, and it works for both recurring and non-recurring subs.
Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Arantor

This would explain why it works perfectly for most sites - the ones that actually have a business acount and use it correctly.

Sir Osis of Liver

Don't believe the site owners are aware this is happening, probably to do with the way PayPal sets up the business accounts, or does upgrades from personal to business.  Their website is just awful, and the business payment interface is much more confusing than the personal ui.  This is not an isolated case, it's affected a number of forums.

Thanks to agentblackhat for your patience, and use of your PP account.



Ashes and diamonds, foe and friend,
 we were all equal in the end.

                                     - R. Waters

Advertisement: