15

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?

loicb
  • 587
  • 2
  • 6
  • 24
  • All JavaScript is TypeScript so start there. Angular 2 integration will probably benefit from a creating an injectable service to wrap the global. – Aluan Haddad May 05 '17 at 16:39

4 Answers4

14

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

Remotec
  • 10,304
  • 25
  • 105
  • 147
  • 1
    How can you change (set it dinamically) the value of amount.total? how can you make a call to a function in your controller when the callback of onAuthorize is executed? – Alex 75 Jan 19 '18 at 01:53
  • I loaded script on ngOninit but rendered button by manually calling a function. Passed amount and currency to the function and assigned to their variables like this amount: { total: cost, currency: selectedCurreny } – Shatayu Darbhe Jul 21 '18 at 11:35
  • 1
    Is it necessary to add "https://www.paypalobjects.com/api/checkout.js" through loadExternalScript() function ? or we can add this js in the index page of website. I am doing same but when i create paypal button on update cart i am getting an error 'PayPal Checkout Integration Script with same version (4.0.235) already loaded on page' .Please suggest me better way to this @Remotec – khurshed alam Nov 27 '18 at 06:56
  • How do you import PayPal to the project? Where does `paypal.Button.render({` come from? – BanAnanas Mar 30 '21 at 09:34
4

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 :)

Mikhaël Gerbet
  • 147
  • 2
  • 8
0

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');
  }
}
Shatayu Darbhe
  • 797
  • 1
  • 7
  • 13
-2

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.

Community
  • 1
  • 1