Paypal Smart Button automatically closed while loading

Created on 17 February 2023, over 1 year ago
Updated 2 March 2023, over 1 year ago

I encountered an error when user click the Paypal button, popup window opened and automatically closed.
Since I couldn't find any question on the internet regarding this problem, I thought I share my solution here.

In the console, it seems the error comes from /commerce_paypal/js/paypal-checkout.js
The error was coming from undefined variable in createOrder function
messages.add(data.responseJSON.message, options);
The data variable is undefined.
And also if you uncomment above code, paypal will throw order id is missing since data is undefined.

Solution

/commerce_paypal/src/Events/CheckoutOrderRequestEvent.php

Remove the use Drupal\commerce\EventBase; and change class CheckoutOrderRequestEvent extends EventBase { to class CheckoutOrderRequestEvent {

and now the button is working again. Not sure why though, maybe commerce module doesn't have the EventBase class anymore?
Anyway I hope this will help someone.

🐛 Bug report
Status

Needs review

Version

1.0

Component

PayPal Checkout

Created by

🇲🇾Malaysia slashsharp

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @slashsharp
  • 🇮🇱Israel jsacksick

    Wow, this doesn't really make sense, sorry for reporting, haven't tried myself to reproduce yet.

    Care to share the Drupal version you're running? (And the Commerce core version while you're at it?)

  • 🇲🇾Malaysia slashsharp

    No worries, maybe something is wrong somewhere with my setup.
    Drupal 9.5.3, Commerce 8.x-2.33+5-dev

  • Status changed to Needs review over 1 year ago
  • 🇦🇹Austria a.milkovsky UTC +2

    We have experienced the same issue. In addition we can see a js error "Paypal Response "Expected an Order ID to be passed".

    As @slashsharp noted, the error happens in the messages.add(data.responseJSON.message, options); line, where data is a string with order id and not an object.

    This promise was added in #3303443: Enhance Exception Handling on Ajax calls . I am not sure why data does not contain responseJSON in this case.

    The next patch removed this promise and fixes the payment process.

  • 🇮🇱Israel jsacksick

    I'm a bit confused by this now... So there's both a JS error and the error with the event class?
    Remove the use Drupal\commerce\EventBase; and change class CheckoutOrderRequestEvent extends EventBase { to class CheckoutOrderRequestEvent

  • Assigned to TomTech
  • Status changed to Needs work over 1 year ago
  • 🇺🇸United States TomTech

    The promise referenced is the error handler of the Ajax callback to retrieve the order id.

    It is not causing this issue, but attempting to handle it. It displays the error message, if one was returned and reloads the page if the response code is 403 (access denied) so that the user can log in again.

    A patch to remove the error handler is not the solution here.

    I've re-tested, and the handler generally works as expected, though we can add more safety around it.

    If the popup window opens and closes, the root cause is that the order id was not available.

    The most common reason for this issue is if the session has gone away or the user has logged out.

    The most common case is a user gets to the checkout step with the PayPal buttons, does something else (gets a cup of coffee?), then the session times out, then they click the button, and the Ajax callback returns an error.

    It takes some patience to wait for the timeout to occur. :)

    A couple ways to reproduce this more quickly is:
    with an authenticated user:

    1. go to the page with the PayPal buttons
    2. open another tab on the site
    3. log out from the site on the other tab
    4. on the checkout tab, click the PayPal button

    You should be presented with the login page, and after you sign in, you should be back on the checkout step again.

    with an anonymous user:

    1. go to the page with the PayPal buttons
    2. go to the database and truncate the session table (Only in a dev environment, of course!)
    3. on the checkout tab, click the PayPal button

    Since this was an anonymous user, you will most likely end up on an empty cart page.

    We are aware of one specific case that would cause data to be a string, but that only occurs if you are using a version of jQuery before 1.8. (Promises on then() was not implemented until jQuery 1.7)

    I'll follow up with a patch that adds more safety to the js, but you really should be getting an object for data in the error handling. If you can identify a reproducible case, we can certainly look into it and troubleshoot!

  • Status changed to Needs review over 1 year ago
  • 🇺🇸United States TomTech

    Attached patch adds more safety around the data on the error handler, and tries to gracefully handle an unexpected payload.

  • 🇦🇹Austria a.milkovsky UTC +2

    I'm a bit confused by this now... So there's both a JS error and the error with the event class?

    @jsacksick #6, the event class change did not help me. The error came from js. I am still not happy with the solution, as it works unstable. That's why we decided to deactivate this payment type for now. I plan to get back to it again and debug a bit more.

    @TomTech your patch #8 is empty.

  • 🇺🇸United States TomTech

    Well...let's. try that again with a non-empty patch. :)

Production build 0.69.0 2024