braintree / braintree-web

A suite of tools for integrating Braintree in the browser
https://developer.paypal.com/braintree/docs/start/hello-client/javascript/v3
MIT License
444 stars 134 forks source link

No callback function for loadPayPalSDK method #703

Closed ruaridhnewman closed 12 months ago

ruaridhnewman commented 12 months ago

General information

Issue description

I'm trying to use the loadPayPalSDK method instead of using the paypal.com script directly, but am having issues with success/error handling on attempting to call it. In the docs, it says you can pass a callback method to the loadPayPalSDK function (see here and here), but that never appears to be triggered, and I can see in the braintree-web code that it doesn't accept a callback as far as I can tell:

paypal-checkout.js, L1186

PayPalCheckout.prototype.loadPayPalSDK = function (options) {
  // code
}

This means that I can't update my checkout page on an unsuccessful attempt at loading the paypal SDK, which has caused me some issues with users attempting to buy something from the site I work on.

Here's a minimal repliacation:

CodeSandbox

Note: you will need to generate a client token and add it to the CLIENT_TOKEN variable in BraintreePayment.js.

Essentially what happens in this flow is it gets to the call to use loadPayPalSDK, but on failing to load the script it never calls the callback method that gets passed into it:

this.#payPalInstance.loadPayPalSDK(options, callback)

=> callback is never called, so I can never know for sure if it errored.

simeyla commented 12 months ago

I had a strange, yet similar issue with manual loading of the PayPal script today. I load it by dynamically adding a script tag and setting it to 'https://www.paypal.com/sdk/js?client-id=....&.... In fact I hadn't even seen this loadPayPalSDK option before.

Was noticing that on my iPhone (currently iOS 17.2) it wasn't running the callback for onload (so my Express Checkout button failed), but in Chrome on my Windows machine it was. I could load the script by pasting the URL into Safari just fine - it loaded instantly.

I actually had started to wonder if iOS was getting clever and stripping out the client-id parameter if it was thinking it was a tracking parameter.

But I just got back from an airport run and it's all working again normally without touching anything. So I'm still puzzled, but wanted to mention what I'd seen since it sounded so similar. When you said 'Any browser' did you really mean any browser?

ruaridhnewman commented 12 months ago

When you said 'Any browser' did you really mean any browser?

I've tried on Firefox, Chrome, Safari on my mac, and it never triggers the callback on failing to load the script. Haven't tried on mobile, but I'm assuming it's the same considering it's all the browsers on desktop 🤷

jplukarski commented 12 months ago

Hello @ruaridhnewman , thanks for this report.

I can see in the braintree-web code that it doesn't accept a callback as far as I can tell:

We have built a module wrap-promise to bring callback functionality to the SDK. Here is where it is implemented in the PayPalCheckout component..

I am able to successfully get the callback function to execute in my own simple integration. Taking a look at your code, it looks like you are using a combination of both callbacks and promises:

 loadPayPal = async ({ onSuccess, onError }) => {
    return this.#payPalInstance.loadPayPalSDK(
      {
        'client-id': 'invalid-client-id',
        components: 'buttons,messages',
        currency: 'GBP',
        'enable-funding': 'paylater',
        dataAttributes: {
            amount: 12.34
        }
      },
      // THIS IS NEVER CALLED
      (error) => {
        if(error) {
          onError(error.message)
          throw new Error('Something went wrong loading PayPal SDK')
        }

        onSuccess();
      }
    )
  }

I would suggest either using promises or callbacks. Moreover, since it looks like this is an issue with your integration and not a bug in the SDK, I can suggest reaching out to our Support Team who can help you with issues in your own integration.

@simeyla , it sounds like your issue is unrelated. I can also suggest reaching out to our support team if you continue to experience the onload callback not executing.