Paypal customers not demoted after failed payment

I have just noticed that Paypal customers on my site do not get demoted after their subscription ends due to a failed payment. Some of my customers have kept access to the site for over a year without paying.

If a customer cancels their subscription normally through unsubscribing they get their EOT set properly and get demoted, so this issue only occurs when their payment fails.

1 Like

Hi Miro.

Thanks for reporting that. Do you have logging enabled? What do the logs say when you reproduce that behavior on your installation? (core/paypal ipn and api logs)

Is your EOT engine enabled and configured properly? I ask because in some rare/random cases, this setting gets reset. I’d like to confirm that that’s not part of the problem here.

Did you confirm that the PayPal subscription was ended after the failed payments and is not just waiting for a retry? Using the subscr ID, can you search for the relevant entries in the s2 logs?

Hi! I have the same issue that @Komar mentions and I have to demote my users manually whenever I receive PayPal’s email letting me know a payment didn’t go through as well.

Does PayPal send an IPN notification when that happens? I can also try to look at my IPN logs if you let me know how to see those, since I forgot the page on PayPal that has that information and I gave up last time I was trying to find it.

Hi Sim.

s2Member doesn’t act on a failed payment for a subscriptions, it acts when the subscription is ended, based on your configuration. See: WP Admin > s2Member > PayPal Options > Automatic EOT Behavior

Is this a subscription? Is the subscription ended or still active? If ended, did the user’s profile get an EOT time set by s2Member?

You can enable and view the logs from here: WP Admin > s2Member > Log Files


1 Like

Thanks for your reply.

Yes, it’s for subscriptions using PayPal Standard.

User pays the first month, gets upgraded.

Second month pay day comes, user does not have money in their account or their card is declined etc.

I receive an email from PayPal letting me know the payment didn’t go through and that they will try to charge the user again. s2Member does NOT demote the user instantly as it should, since the user didn’t pay from that moment onwards (it should demote the user and re-promote the user if payment happens later, IMHO).

Five days later, in 99% of those cases the user does NOT have funds again, PayPal emails me letting me know that it was not possible to charge the subscriber and that they’ll stop trying. Subscription is suspended on PayPal’s side. Nothing happens on s2Member again. If the user didn’t get demoted on the “first event” they should be on the second one, otherwise they’ll be able to continue accessing content that should not be available to them.

My only workaround has been editing user by user when that happens (which is something that happens quite often, since many users subscribe just to access certain content, they download whatever they want and leave after, but many re-subscribe once I demote them manually, but only when I do that).

I don’t know if PayPal sends a signal to the return URL in those cases, but I guess it should, since it does when a user cancels a subscription instead of “not paying” for it or when I refund a subscriber for any reason.

I am grateful for the plugin no matter what, of course. Hopefully we can have that feature at some point…?

Thanks Sim.

Actually s2Member would act when the subscription ends, not when a payment fails but subscription is active. I do have in my feature requests an option to remove access when payment fails and restore it if paid for an active subscription. I’m adding your vote to it.

Subscription is suspended on PayPal’s side. Nothing happens on s2Member again. If the user didn’t get demoted on the “first event” they should be on the second one, otherwise they’ll be able to continue accessing content that should not be available to them.

Exactly. If the paypal subscription was ended, then s2Member should get a notification from PayPal behind the scenes, and s2Member’s EOT would kick in based on your configuration for it.

Those notifications would show up in at least one of the s2Member logs. Did you look for them? We need to see if s2 is receiving it and not acting on it so we can look deeper into it, or if it’s just not getting told about it. WP Admin > s2Member > Log Files

My only workaround has been editing user by user when that happens

That’s a good way to handle it in the meantime.

1 Like

Hi! Finally got do test it. Yes, PayPal IPN sends a subscr_failed event to s2Member, therefore it needs to process that and demote the user right away, like when there’s a refund. Anyway I can hook the event that way by changing something in the code somewhere?

[txn_type] => subscr_failed

[s2member_log] => Array
        [0] => IPN received on: Tue Oct 6, 2020 11:38:18 am UTC
        [1] => s2Member POST vars verified through a POST back to PayPal.
        [2] => s2Member originating domain (`$_SERVER["HTTP_HOST"]`) validated.
        [3] => s2Member `txn_type` identified as ( `subscr_failed|recurring_payment_failed|recurring_payment_skipped` ).
        [4] => This `txn_type` does not require any action on the part of s2Member.
        [5] => s2Member does NOT respond to individual failed payments, only multiple consecutive failed payments.
        [6] => When multiple consecutive payments fail, a special IPN response will be triggered.

[subscr_gateway] => paypal


This is the file that handles that notification: s2member/src/includes/classes/

There are a few hooks there, and you could customize the behavior with a hack in the must-use plugins folder, for example.

If you remove access for the user but the subscription is still active, you will also want to restore it if a payment comes in later. See: s2member/src/includes/classes/

I hope that helps! :slight_smile:

1 Like

Yes! Very much! Thank you so much!!!

1 Like

I just changed the file at its line 44 from:

if ((!empty($paypal["txn_type"]) && preg_match ("/^(subscr_cancel|recurring_payment_profile_cancel|mp_cancel)$/i", $paypal["txn_type"]))


if ((!empty($paypal["txn_type"]) && preg_match ("/^(subscr_cancel|recurring_payment_profile_cancel|mp_cancel|subscr_failed|recurring_payment_failed|recurring_payment_skipped)$/i", $paypal["txn_type"]))

Changing also Line 61 do add the new types and renaming the php file you mentioned to something else so it won’t run.

I’ll see what happens when another payment fails, then I’ll let you know :wink:

1 Like

I suggest using the hooks, though.

Those files will be replaced next time you update s2.

1 Like

Thanks! Good to know! I am still learning (and quite clueless yet) :grin:

I thought I’d had to hold back updating until I changed the new files to match my modifications, LOL


My experiment did not work as I expected it was unlikely, but it was worth giving it a try. I’ll have to do it properly by adding code to the file you mentioned or by using the hooks you linked. I’ll study a bit more and let you know what I get from it when I make progress.

Thanks a lot for always being available to help us! :smiling_face_with_three_hearts:

1 Like

One idea for a future addon would be to use PayPal’s API to retry collecting outstanding amounts every x hours:,next%20billing%20cycle%20is%20reached.

Since it seems we can run it as frequently as we want, it would be nice to be able to have your plugin do that instead of using their interface to try to collect one by one manually. I didn’t know where to post this idea, so I felt it would fit here better than in a loose topic because of the relation.

Any chance we can have a fix for this problem? I have to deal with this problem almost everyday. :grimacing:

I don’t mind if users aren’t automatically reupgraded, I would just like to have them automatically demoted when their payment is declined while keeping their subscription active so PayPal or Stripe continue trying to collect pending payments.

I already have an EOT email set up to warn them they have to contact me to restore access and that the fact they lost access does not cancel their billing. I’d rather have half of a solution than having to process everything manually. It’s been 2 years since I pointed this issue out but I am unable to fix it by myself, sorry… :grimacing:

Sorry for unburying an old topic but I really believe this issue is relevant. I have been demoting users manually, daily, for years already. :cry:

Thanks again!

The whole demotion based on failed payements is not logical. This problem is even worse for users running a complaint against a payment. In that case until the money is refunded - the access should still be active (which it is not).
And yes if the paid area suddenly is not available any more while payment is pending - it would give more motivation to users to fix their credit card in paypal

Your policy might be different from mine. If a payment fails I want the user demoted right away or in 24 hours and an email sent asking them to pay or resubscribe. That is what is logical. I don’t want to give free access and most declines are not recoverable otherwise. People just use the content for free.

In my experience most people that fix only do so after losing access. Majority involuntary churn and a good amount of people pay days or months later when their cards authorize the payment, then they are fast to email me asking to regain access, since I warn them the plugin won’t reupgrade them automatically and the payment processor does not send a message to warn us when a late payment is successful.

Many people use disposable cards to prevent recurring charges as well.

I don’t have a problem with disposable cards and most complaints about payments at paypal are about users forgetting they had the subscription.
However if you demote them directly on complaint - then you have no right to claim that payment. So that’s why I say - demotion should happen once payment has actually been refunded and not while it’s inside the paypal decision time.
I’m not sure if s2member can identify complaint (non receival or similar) to credit card chargebacks. As I have so far lost all chargebacks - in that case a direct demotion is fine. I win nearly all other complaints however - so I don’t want the user to be demoted in that case.

Quite a few complaints are from users having an unreachable mailbox - thus not receiving their userdata or it ending up in their spam folder - so demotion or even worse inability to create that account because the payment is on hold for paypal complaint is the worse decision.
It would be different for physical products - but to me it’s digital only and I rather have the user keep on having access than justifying their complaint by demotion.

Oh no, I have very clear terms and most of the issues I have are with users that have second/third later payments declined due to not having funds, cards that are frozen etc.

I do what I mention manually and send them an email letting them know the system doesn’t notify me when a later successful payment happens, but that PayPal (or Stripe) continues collecting until successful and that their recurring subscription is not cancel, just their access to the content. That way they are responsible for letting me know after they pay by sending me a message so I can reinstate them.

Saying you “forgot” you had a subscription is the same as saying you didn’t bring your homework because your dog ate it, sorry.

You seem to have pretty much the opposite problem. Maybe you have a much larger user base, I don’t know. I would be unable to do the things I do manually if it were the case. :grimacing:

Ideally the system should demote delinquent users and reinstate them once they pay.