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 .
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.