Paypal Smart Button automatically closed while loading

Created on 17 February 2023, over 2 years 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

Active

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

Merge Requests

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 about 2 years 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 about 2 years 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 about 2 years 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. :)

  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    @tomtech you're still assigned, plans to finish this? Perhaps proceed with a MR?
    Or are you awaiting review by @jsacksick for #10 first?

  • Issue was unassigned.
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Anybody Porta Westfalica

    No reply from @tomtech :(

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia rakesh.regar Rajasthan, India

    rakesh.regar โ†’ made their first commit to this issueโ€™s fork.

  • Pipeline finished with Success
    30 days ago
    Total: 158s
    #479096
  • ๐Ÿ‡ฉ๐Ÿ‡ชGermany Grevil

    @rakesh.regar provided @tomtech's patch as an MR.

    Changes LGTM and makes the JS a bit more safe. Unsure if it will fix the original issue, as there aren't clear steps to reproduce (other the ones from @tomtech).

    The only thing is, that in the case "data.status" is "403", the added message will quickly disappear through location.reload(). Other than that, it looks fine!

    Let's hear feedback from others.

Production build 0.71.5 2024