Paypal provides an easy way to integrate its express checkout solution but what is the best solution to use this solution in an angular2 project working written in typescript?
By using Remotec's answer I'm able to render the express checkout. It gives some violation warnings though. I've rendered in my function after user selects currency. I've passed 'this' from angular template. I've used Angular 6 and Angular material 2
<div class="container">
<div *ngFor="let currency of currencies">
</div>
<div class="row">
<form >
<mat-form-field appearance="standard" class="col-sm-12 col-md-6">
<mat-label>Cost</mat-label>
<input matInput placeholder="Amount" [(ngModel)]="cost" required disabled="true" name="amount" id="amount">
</mat-form-field>
<mat-form-field appearance="standard" class="col-sm-12 col-md-6">
<mat-select placeholder="Select Currency" [(ngModel)]="selectedCurrency" name="curr" id="curr" (selectionChange)="CurrencyChange(cost,selectedCurrency,this)" >
<mat-option *ngFor="let c of currencies" [value]="c.value" >
{{c.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</div>
<div id="paypal-button" class="align-content-between align-content-center"></div>
</div>
In function CurrencyChange I've this is passed and in paypal function I've again called my angular function to complete the payment. I don't know if this is a good practice. But this worked.
export class PaymentComponent implements OnInit {
cost = '1';
currency = 'INR';
selectedCurrency = "0";
currencies: Currency[] = [
{
value: "0",
viewValue: "Select Currency"
},
{
"value": "INR",
"viewValue": "Indian Ruppe"
}, {
"value": "USD",
"viewValue": "US Dollar"
},
{
"value": "EUR",
"viewValue": "EURO"
}]
private loadExternalScript(scriptUrl: string) {
return new Promise((resolve, reject) => {
const scriptElement = document.createElement('script')
scriptElement.src = scriptUrl
scriptElement.onload = resolve
document.body.appendChild(scriptElement)
})
}
ngOnInit() {
this.loadExternalScript("https://www.paypalobjects.com/api/checkout.js");
}
constructor() { }
paymentSuccess(payment) {
//alert('Payment Success');
}
CurrencyChange(cost, selectedCurreny,self): void {
document.getElementById("paypal-button").innerHTML = "";
if (selectedCurreny == 0) {
alert('Please select the Country');
return;
}
//reset earlier inserted paypal button
paypal.Button.render({
env: 'sandbox',
client: {
production: 'AQ9IbOayBJxHmad9DMGoysS4UhzE-usUqfSQ-CLzSn3M96qvZny5vZZ2VkNzn6EBTnE2UU4L8PDkqJJE',
sandbox: 'AQ9IbOayBJxHmad9DMGoysS4UhzE-usUqfSQ-CLzSn3M96qvZny5vZZ2VkNzn6EBTnE2UU4L8PDkqJJE'
},
commit: true,
payment: function (data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: cost, currency: selectedCurreny }
}
]
}
})
},
onAuthorize: function (data, actions) {
return actions.payment.execute().then(function (payment) {
alert('Payment Successful')
self.paymentSuccess(payment);
console.log(payment)
})
}
}, '#paypal-button');
}
}
you can implement paypal checkout with angular 4 like this :
import { Component, OnInit } from '@angular/core';
declare let paypal: any;
@Component({
selector: 'app-page-offers',
templateUrl: './page-offers.component.html',
styleUrls: ['./page-offers.component.sass']
})
export class PageOffersComponent implements OnInit {
constructor() {}
ngOnInit() {
$.getScript( 'https://www.paypalobjects.com/api/checkout.js', function() {
paypal.Button.render({
[...]
})
[...]
Enjoy :)
I've used a solution like this:
Method to load external scripts
private loadExternalScript(scriptUrl: string) {
return new Promise((resolve, reject) => {
const scriptElement = document.createElement('script')
scriptElement.src = scriptUrl
scriptElement.onload = resolve
document.body.appendChild(scriptElement)
})
Component Code
ngAfterViewInit(): void {
this.loadExternalScript("https://www.paypalobjects.com/api/checkout.js").then(() => {
paypal.Button.render({
env: 'sandbox',
client: {
production: '',
sandbox: ''
},
commit: true,
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) {
// TODO
})
}
}, '#paypal-button');
});
}
Credit
Andrei Odri's answer here: script tag in angular2 template / hook when template dom is loaded
I've recently answered similar question (how to write the below code in angular 2 component using typescript) and wrote simple component encapsulating the paypal button.
I've extended my example to have input cost property, so you can pass a cost to the button's component. You can easily extend this and pass more data if needed.
As Aluan Haddad said in the comment, you can wrap the PayPal global in the service. I've written a simple service wrapping the Button property with some type definitions:
export class PaypalService {
constructor() { }
// You can bind do paypal's button with type definitions in the following way:
public Button: {
render: ({ payment, onAuthorize }: {
payment?: (data: any, actions: any) => void,
onAuthorize?: (data: any, actions: any) => void
}, divId: string) => void
} = (window as any).paypal.Button;
}
Working example is in: https://plnkr.co/edit/9AlbWnZDzek9kDdigdED
I'm not sure about inner workings of the PayPal's button but this should give you a head start, hope it helps.