PayPal Donate With Ionic

Hi. I am developing a Progressive Web App using Ionic. Native PayPal Mobile SDK does not work with a web app. How can I achieve the PayPal integration, donate specifically with Ionic as PWA? I have tried different approach like HTML forms for PayPal (and those that I previously used in previous projects) but they does not seem to work here. Any idea? TIA.

I don’t know about donations specifically but I use the Client REST provided by PayPal in Ionic3 for PWA’s.
https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/client-side-REST-integration/

Hi @shepard. Thank you for your idea. I have actually seen it but the problem is I do not know how to attach it properly to Ionic because when I tried, the button does not show.

I put the <script src="https://www.paypalobjects.com/api/checkout.js"></script> at index.html. Then at the bottom of it,

<script>
    paypal.Button.render({

        env: 'production', // Or 'sandbox'

        client: {
            sandbox:    'xxxxxxxxx',
            production: 'xxxxxxxxx'
        },

        commit: true, // Show a 'Pay Now' button

        payment: function(data, actions) {
            return actions.payment.create({
                payment: {
                    transactions: [
                        {
                            amount: { total: '1.00', currency: 'USD' }
                        }
                    ]
                }
            });
        },

        onAuthorize: function(data, actions) {
            return actions.payment.execute().then(function(payment) {

                // The payment is complete!
                // You can now show a confirmation message to the customer
            });
        }

    }, '#paypal-button');
</script>

I also added <div id="paypal-button"></div> at the donation page but the button does not show. Thanks!

I add the following to the head in the index.html:
<script src="https://www.paypalobjects.com/api/checkout.js"></script>

In your page’s html, add:
<div #paypalbuttoncontainer id="paypal-button-container"></div>

In the .ts file, add:
declare var paypal: any;

Then you can set up your initializePayPal function:

initPayPal() {
this.paypal_initialized = true;
let paypalbuttoncontainer = this.paypalbuttoncontainer.nativeElement as HTMLDivElement;
let _this = this;

paypal.Button.render({
  env: 'production', // sandbox | production
  style: {
    size: 'responsive',
    color: 'gold',
    shape: 'pill',
    label: 'checkout', //                    label: checkout, buynow, credit, pay, paypal
    tagline: false
  },


  client: {
    sandbox: 'YOUR_SANBOX_CLIENT_ID';
    production:YOUR_LIVE_CLIENT_ID';
  },

  // Show the buyer a 'Pay Now' button in the checkout flow
  commit: true,


  payment: function (data, actions) {

    return actions.payment.create({
      //weight_unit: "kgs",
      //enableShippingAddress: true,
      payment: {
        transactions: [
          {
            amount: {
              total: _this.total_fixed,
              currency: _this.country.currency,
              details: {
                subtotal: _this.subtotal_fixed,
                tax: _this.tax_total_fixed,
                shipping: _this.shipping,
                handling_fee: _this.surcharge,
              }
            },
            description: 'Describe your transactiont',
            custom: 'Hello Shopper',
            invoice_number: _this.invoice_id,
            payment_options: {
              allowed_payment_method: 'INSTANT_FUNDING_SOURCE'
            },
            soft_descriptor: 'ECHI5786786',
            item_list: {
              items: _this.items_paypal,
            }
          }
        ]

      },

      experience: {
        input_fields: {
          //no_shipping: 1
        }
      }
    });

  },

  onCancel: function (data, actions) {
    //return actions.redirect();
  },


  // onAuthorize() is called when the buyer approves the payment
  onAuthorize: function (data, actions, error) {
    if (error) {
      console.log("---------WE HAVE AN ERROR-------------------")
      console.log("ERROR: " + error)
    }
    if (error === 'INSTRUMENT_DECLINED') {
      actions.restart();
    }

    actions.payment.get().then(function (paymentDetails) {
      /
      console.log("paymentDetails: " + paymentDetails);
      _this.paymentDetails = paymentDetails;
    });
    // Make a call to the REST api to execute the payment
    return actions.payment.execute().then(function () {
      let confirm = this.alertCtrl.create({
        title: 'Payment Complete!',
        message: "Your payment has completed successfully.<br>You will find it in your History.",
        buttons: [
          {
            text: 'OK',
            handler: () => {

            }
          }
        ]
      });
      confirm.present();

    });
  }

}, paypalbuttoncontainer);

}

setupPayPay() {
    if (!this.paypal_initialized) {
      this.initPayPal();
    }
  }

I use the setupPayPal() function to make sure the button was not already initialized.
All of the vars that start with a _this. are dealt with outside of the button render eg:
subtotal: _this.subtotal_fixed,
tax: _this.tax_total_fixed,
shipping: _this.shipping,
handling_fee: _this.surcharge,

_this.items_paypal is an array and the totals, taxes, etc of all the items within - must match the final totals above.

Hi @shepard, thanks for your help. You dont know how much I appreciate.
Paypal is now being read by my page :slight_smile: .
I already added <div #paypalbuttoncontainer id="paypal-button-container"></div> but , I am still getting this:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property ‘nativeElement’ of undefined
TypeError: Cannot read property ‘nativeElement’ of undefined

I added the @ViewChild for the paypalbutton but the error is still there.
I really apologize for I am really new to Ionic as well as Angular. Thanks again.

Have you imported:
import { Component, ViewChild, ElementRef } from '@angular/core';

Thanks to you @shepard.

Yes I did. I added import { Component, ViewChild, ElementRef } from '@angular/core';
Then inside the export class, @ViewChild('paypalbuttoncontainer') paypalbuttoncontainer: ElementRef;
Here is where I encounter the “Cannot read property ‘nativeElement’ of undefined” error:
let paypalbuttoncontainer = this.paypalbuttoncontainer.nativeElement as HTMLDivElement;

@shepard, Thanks for your help. I made it the button show by setting a timeout
setTimeout(() => {
let paypalbuttoncontainer = this.paypalbuttoncontainer.nativeElement as HTMLDivElement
}, 1000);

Everything works fine now. I can save all the retrieved data. A big thanks to you @shepard for being so helpful! It could help people who struggle with this. Thanks!

That’s great that you got it working!
Glad I could be of some help.
Good luck with your project.