2

I have a website with multiple payment forms. I can switch between them and then I have a button with "Continue to checkout" label that when you click, it does something depending on the payment method chosen. The handler function looks something like this:

const handlePayment = (method) => {
   if(method === paymentMethods.STRIPE){
       // do something
   }

   if(method === paymentMethods.PAYPAL){
       // do something else
   }
}

The problem is I looked at the docs and it's always about showing a PayPal button, I don't want a PayPal button, I want to open the PayPal form directly from my button, when a method is selected.

So want I mean is, I want to do it programmatically. Is there any way to do this? I don't want to do a hacky solution hiding the button or triggering the click or some weird thing...

The React PayPal component is just a wrapper for the JS SDK.

My UI looks something like this: I'd like to open the PayPal payment form when I click on Pay, only if PayPal is selected.

enter image description here

isherwood
  • 58,414
  • 16
  • 114
  • 157
nick
  • 2,819
  • 5
  • 33
  • 69
  • Again, I'm not sure why you wouldn't just conditionally render the PayPal component rather than trying to hack it up. Is there some reason that wouldn't work? – isherwood Feb 25 '22 at 14:03
  • The PayPal component is a button that when you click it opens it, I don't want this, I want to have it opened from my own handler – nick Feb 25 '22 at 14:05
  • Perhaps you can hide the button, and then trigger a click event on it via script? (I don't know how exactly these buttons render, if they hide in shadow DOM or are in an iframe loaded from paypal, then this of course won't work.) – CBroe Feb 25 '22 at 14:13
  • @CBroe yeah this is what I wanted to avoid but I think it's the only option, either that or open a modal with the paypal button when I click on Pay, but now it's another click for the user :/ – nick Feb 25 '22 at 14:14
  • Right, so _use your own button_ and _use your own handler_. When you detect click on your button, trigger click on the PayPal component's button (assuming there's no API option to have it shown initially). – isherwood Feb 25 '22 at 14:17
  • Looks like Paypal's React component [intentionally doesn't support force-clicking](https://stackoverflow.com/questions/43276570/trigger-paypal-checkout-button-click) – GalAbra Feb 25 '22 at 15:58

1 Answers1

1

If you use the PayPal JS SDK to open the checkout, you have to use its button, and the user has to click it themselves. PayPal does this intentionally so that the button shown uses their consistent branding.

If you want an alternative, you can integrate without the JS SDK (REST API only) and have your own button which redirects to the PayPal page for approval, which will then return to your site. This is an old integration pattern, for old websites, and not recommended.

Despite your misgivings and desire not to use it, the JS SDK and its button in a container sized to your requirements is in fact the best available solution.

Based on the UI shown, what you might op to do is hide your "Pay" button and replace it with one that says "Pay With PayPal" when that method is selected, which could look like this (sized to fit your container): enter image description here Here's sample HTML/JS for that, you can do the same from react-paypal-js :

    <script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>

    <div id="paypal-button-container"></div>

    <script>
        paypal.Buttons({
            fundingSource: paypal.FUNDING.PAYPAL,
            style: {
                color: "blue",
                label: "pay"
            },

            // Set up the transaction
            createOrder: function(data, actions) {

                return actions.order.create({
                    purchase_units: [{
                        amount: {
                            value: '88.44'
                        }
                    }]
                });
            },

            // Finalize the transaction
            onApprove: function(data, actions) {
                return actions.order.capture().then(function(orderData) {
                    // Successful capture! For demo purposes:
                    console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
                    var transaction = orderData.purchase_units[0].payments.captures[0];
                    alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');

                    // Replace the above to show a success message within this page, e.g.
                    // const element = document.getElementById('paypal-button-container');
                    // element.innerHTML = '';
                    // element.innerHTML = '<h3>Thank you for your payment!</h3>';
                    // Or go to another URL:  actions.redirect('thank_you.html');
                });
            }


        }).render('#paypal-button-container');
    </script>
Preston PHX
  • 27,642
  • 4
  • 24
  • 44
  • Hi thanks for your response, we will use the redirect method for the moment being, but I'll mark your answer as correct so maybe it can help someone! – nick Feb 27 '22 at 02:03
  • In that case the return to your site needs to display a final order review page, with an action that will trigger a capture of the payment and display success/failure. Alternatively, you can set `user_action` in the create API call so that the final button on PayPal says "Pay Now", and instead of showing a review page on return, immediately do the capture and show the result. Again, though, the JS SDK is a better experience because payment approval is "in context", keeping your site loaded in the background and not redirecting a way from it. Modern websites should prefer this... – Preston PHX Feb 27 '22 at 03:19