strangerstudios / paid-memberships-pro

WordPress membership plugin to restrict access to content and charge recurring subscriptions using Stripe, PayPal, and more. Fully open source. 100% GPL.
https://www.paidmembershipspro.com
Other
460 stars 357 forks source link

FATAL ERROR: Uncaught Error: Call to undefined method Stripe\Customer::invoices() #1194

Open woodwardmatt opened 4 years ago

woodwardmatt commented 4 years ago

Describe the bug When cancelling a membership a fatal error is thrown.

To Reproduce Steps to reproduce the behavior:

  1. Create a new member & membership
  2. Whilst logged in as that member, choose to cancel the membership
  3. See error "There has been a critical error on your website."

Analysis Upon closer inspection in the WordPress debug log...

[09-Dec-2019 01:27:26 UTC] PHP Fatal error:  Uncaught Error: Call to undefined method Stripe\Customer::invoices() in /wp-content/plugins/paid-memberships-pro/classes/gateways/class.pmprogateway_stripe.php:1940
Stack trace:
#0 /wp-content/plugins/paid-memberships-pro/classes/gateways/class.pmprogateway_stripe.php(1882): PMProGateway_stripe->cancelSubscriptionAtGateway(Object(Stripe\Subscription))
#1 /wp-content/plugins/paid-memberships-pro/classes/class.memberorder.php(844): PMProGateway_stripe->cancel(Object(MemberOrder))
#2 /wp-content/plugins/paid-memberships-pro/includes/functions.php(1034): MemberOrder->cancel()
#3 /wp-content/plugins/paid-memberships-pro/preheaders/cancel.php(55): pmpro_changeMembershipLevel(0, 123, 'cancelled')
#4 /wp-content/plugins/paid-memberships-pro/includes/init.php(73): require_once('/ho in /wp-content/plugins/paid-memberships-pro/classes/gateways/class.pmprogateway_stripe.php on line 1940

... it appears that the code is calling deprecated functions on the stripe-php library. The call can be seen here: https://github.com/strangerstudios/paid-memberships-pro/blob/00e7e8130ad667808c161f0c3964ae732798a3df/classes/gateways/class.pmprogateway_stripe.php#L1940

This function (i.e. Stripe\Customer::invoices()) was deprecated in the Stripe PHP Library in this commit: https://github.com/stripe/stripe-php/commit/8a046cfd119e50a048645f8d4249490a566379bc#diff-814438c52fc09aaad9ad47d5fa40351c

Resolution

Having queries this with the Stripe support team, the recommended approach is now to use the list function on the Invoice object with the appropriate customer id and status (of open). This approach is documented at: https://stripe.com/docs/api/invoices/list?lang=php

This should mean changing...

        $invoices = $this->customer->invoices();
        $invoices = $invoices->all();

...to...

$invoices = Stripe_Invoice::all(['customer' => $this->customer->id, 'status' => 'open']);

Conclusion I have implemented this change in my local code base and checked this approach delivers the correct behavior. This solution has been raised as a PR at: https://github.com/strangerstudios/paid-memberships-pro/pull/1193

ideadude commented 4 years ago

Thanks so much for the info. We will get this out ASAP.

ideadude commented 4 years ago

Forgot to update this issue.

This error will only come up if your WordPress site is loading a different (though newer) version of the Stripe PHP library. The version bundled with PMPro, includes the invoices method for customers: https://github.com/strangerstudios/paid-memberships-pro/blob/dev/includes/lib/Stripe/lib/Customer.php

The latest version (probably loaded by another plugin on your site) doesn't: https://github.com/stripe/stripe-php/blob/master/lib/Customer.php

We can and should update our code to work with the newer version of the API. This would require us to find the customer invoices in a different way and make sure other parts of our code work with the latest library. This takes some time. In general, we try to time these updates with other Stripe-related work we are doing.

The short term solution for you, if you are receiving this error, is to figure out which other plugin is activated and loading the Stripe API. If you don't need that plugin, you can deactivate it. If you do need that plugin, we can figure out a custom code gist to selectively skip loading the Stripe API library that is bundled with that plugin when PMPro is doing things. Exactly how to do that depends on which other plugin is loading the Stripe API.

You could also try to load the Stripe API from the PMPro directory early on in the WP loading sequence and that other plugin might check if Stripe is already loaded and skip its own load.

ideadude commented 4 years ago

PMP 2.3 has NOT been updated to use the new orders API methods. The above advice still applies.

scoreytime commented 4 years ago

Hi @ideadude,

We recently installed WP Simple Pay Lite and are experiencing the same error mentioned by @woodwardmatt. PMPro members are unable to downgrade their accounts as per the API issues mentioned in your post.

Are you able to provide a solution so that PMPro can co-exist with WP Simple Pay? We need both plugins on our site.

Thank you!