Standard payments with JavaScript frameworks

DocsCurrentLast updated: March 16th 2023, @ 11:23:55 am


Use this guide if your website uses a library or framework such as React, Vue, or Angular.

Know before you code

Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:

  • Client ID
  • Access token
  • Business account credentials
  • Use Postman to explore and test PayPal APIs.

How it works

Add payment buttons to your library or framework:

  1. React
  2. Angular
  3. Angular 2
  4. Vue
1const PayPalButton = paypal.Buttons.driver("react", { React, ReactDOM });

1. Add the JavaScript SDK

The JavaScript SDK displays payment methods on your checkout page.

Place the following script tag in your index.html page based on how you plan to render payment buttons, so the paypal object is available when you need it in the checkout flow.

  • To render payment buttons immediately:

    <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"></script>
    
  • To render payment buttons after user action, navigation, or page change, include the defer object in the JavaScript SDK script:

    <script
      defer
      src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"
    ></script>
    

Add and modify the code

Note: This sample code is optimized for JavaScript performance. To learn more about optimization considerations, see JavaScript SDK performance optimization.

  1. Copy the sample JavaScript SDK code and paste it into your checkout page.
  2. In the SDK code, replace YOUR_CLIENT_ID with your client ID.
  3. Pass parameters to replace default values, such as USD for currency. To learn more about the default values, see the JavaScript SDK script configuration.

2. Add the code

Choose your JavaScript library or framework:

React

Component implementation and functional implementation.

Component implementation

1import React from "react";
2import ReactDOM from "react-dom"
3const PayPalButton = paypal.Buttons.driver("react", { React, ReactDOM });
4class YourComponent extends React.Component {
5 createOrder(data) {
6 // Order is created on the server and the order id is returned
7 return fetch("/my-server/create-paypal-order", {
8 method: "POST",
9 headers: {
10 "Content-Type": "application/json",
11 },
12 // use the "body" param to optionally pass additional order information
13 // like product skus and quantities
14 body: JSON.stringify({
15 cart: [
16 {
17 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
18 quantity: "YOUR_PRODUCT_QUANTITY",
19 },
20 ],
21 }),
22 })
23 .then((response) => response.json())
24 .then((order) => order.id);
25 }
26 onApprove(data) {
27 // Order is captured on the server
28 return fetch("/my-server/capture-paypal-order", {
29 method: "POST",
30 headers: {
31 "Content-Type": "application/json",
32 },
33 body: JSON.stringify({
34 orderID: data.orderID
35 })
36 })
37 .then((response) => response.json());
38 }
39 render() {
40 return (
41 <PayPalButton
42 createOrder={(data, actions) => this.createOrder(data)}
43 onApprove={(data, actions) => this.onApprove(data)}
44 />
45 );
46 }
47}

Functional implementation

1import React from "react";
2import ReactDOM from "react-dom"
3const PayPalButton = paypal.Buttons.driver("react", { React, ReactDOM });
4function YourComponent() {
5 const createOrder = (data) => {
6 // Order is created on the server and the order id is returned
7 return fetch("/my-server/create-paypal-order", {
8 method: "POST",
9 headers: {
10 "Content-Type": "application/json",
11 },
12 // use the "body" param to optionally pass additional order information
13 // like product skus and quantities
14 body: JSON.stringify({
15 cart: [
16 {
17 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
18 quantity: "YOUR_PRODUCT_QUANTITY",
19 },
20 ],
21 }),
22 })
23 .then((response) => response.json())
24 .then((order) => order.id);
25 };
26 const onApprove = (data) => {
27 // Order is captured on the server and the response is returned to the browser
28 return fetch("/my-server/capture-paypal-order", {
29 method: "POST",
30 headers: {
31 "Content-Type": "application/json",
32 },
33 body: JSON.stringify({
34 orderID: data.orderID
35 })
36 })
37 .then((response) => response.json());
38 };
39 return (
40 <PayPalButton
41 createOrder={(data) => createOrder(data, actions)}
42 onApprove={(data) => onApprove(data, actions)}
43 />
44 );
45}

Angular

1paypal.Buttons.driver("angular", window.angular);
2angular
3 .module("app", ["paypal-buttons"])
4 .controller("appController", function ($scope) {
5 $scope.opts = {
6 createOrder: function (data) {
7 // Order is created on the server and the order id is returned
8 return fetch("/my-server/create-paypal-order", {
9 method: "POST",
10 headers: {
11 "Content-Type": "application/json",
12 },
13 // use the "body" param to optionally pass additional order information
14 // like product skus and quantities
15 body: JSON.stringify({
16 cart: [
17 {
18 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
19 quantity: "YOUR_PRODUCT_QUANTITY",
20 },
21 ],
22 }),
23 })
24 .then((response) => response.json())
25 .then((order) => order.id);
26 },
27 onApprove: function (data) {
28 // Order is captured on the server
29 return fetch("/my-server/capture-paypal-order", {
30 method: "POST",
31 headers: {
32 "Content-Type": "application/json",
33 },
34 body: JSON.stringify({
35 orderID: data.orderID
36 })
37 })
38 .then((response) => response.json());
39 },
40 };
41 });
1<body ng-app="app" ng-controller="appController">
2 <paypal-buttons props="opts"></paypal-buttons>
3</body>

Angular 2

1(function () {
2 const PayPalButton = paypal.Buttons.driver("angular2", ng.core);
3 const appComponent = ng.core
4 .Component({
5 selector: "my-app",
6 template:
7 <div id="app">
8 <paypal-buttons [props]="{
9 createOrder: createOrder,
10 onApprove: onApprove
11 }"></paypal-buttons>
12 </div>
13 ,
14 })
15 .Class({
16 constructor: function () {
17 this.createOrder = (function(data) {
18 // Order is created on the server and the order id is returned
19 return fetch("/my-server/create-paypal-order", {
20 method: "POST",
21 headers: {
22 "Content-Type": "application/json",
23 },
24 // use the "body" param to optionally pass additional order information
25 // like product skus and quantities
26 body: JSON.stringify({
27 cart: [
28 {
29 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
30 quantity: "YOUR_PRODUCT_QUANTITY",
31 },
32 ],
33 }),
34 })
35 .then((response) => response.json())
36 .then((order) => order.id);
37 }).bind(this);
38 this.onApprove = (function(data, actions) {
39 // Order is captured on the server
40 return fetch("/my-server/capture-paypal-order", {
41 method: "POST",
42 headers: {
43 "Content-Type": "application/json",
44 },
45 body: JSON.stringify({
46 orderID: data.orderID
47 })
48 })
49 .then((response) => response.json())
50 }).bind(this);
51 });
52 }});
53 const appModule = ng.core
54 .NgModule({
55 imports: [ng.platformBrowser.BrowserModule, PayPalButton],
56 declarations: [appComponent],
57 bootstrap: [appComponent],
58 })
59 .Class({
60 constructor: function () {},
61 });
62 document.addEventListener("DOMContentLoaded", function () {
63 ng.platformBrowserDynamic
64 .platformBrowserDynamic()
65 .bootstrapModule(appModule);
66 });
67})();
1(function () {
2 const PayPalButton = paypal.Buttons.driver("angular2", ng.core);
3 const appComponent = ng.core
4 .Component({
5 selector: "my-app",
6 template:
7 <div id="app">
8 <paypal-buttons [props]="{
9 createOrder: createOrder,
10 onApprove: onApprove
11 }"></paypal-buttons>
12 </div>
13 ,
14 })
15 .Class({
16 constructor: function () {
17 this.createOrder = (function(data) {
18 // Order is created on the server and the order id is returned
19 return fetch("/my-server/create-paypal-order", {
20 method: "POST",
21 headers: {
22 "Content-Type": "application/json",
23 },
24 // use the "body" param to optionally pass additional order information
25 // like product skus and quantities
26 body: JSON.stringify({
27 cart: [
28 {
29 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
30 quantity: "YOUR_PRODUCT_QUANTITY",
31 },
32 ],
33 }),
34 })
35 .then((response) => response.json())
36 .then((order) => order.id);
37 }).bind(this);
38 this.onApprove = (function(data) {
39 // Order is captured on the server
40 return fetch("/my-server/capture-paypal-order", {
41 method: "POST",
42 headers: {
43 "Content-Type": "application/json",
44 },
45 body: JSON.stringify({
46 orderID: data.orderID
47 })
48 })
49 .then((response) => response.json())
50 }).bind(this);
51 });
52 }});
53 const appModule = ng.core
54 .NgModule({
55 imports: [ng.platformBrowser.BrowserModule, PayPalButton],
56 declarations: [appComponent],
57 bootstrap: [appComponent],
58 })
59 .Class({
60 constructor: function () {},
61 });
62 document.addEventListener("DOMContentLoaded", function () {
63 ng.platformBrowserDynamic
64 .platformBrowserDynamic()
65 .bootstrapModule(appModule);
66 });
67})();

Angular 2 using TypeScript

1@ng.core.Component({
2 selector: 'my-app',
3 template:
4 <div id="app">
5 <paypal-buttons [props]="{
6 createOrder: createOrder,
7 onApprove: onApprove
8 }"></paypal-buttons>
9 </div>
10 ,
11})
12class AppComponent {
13 createOrder(data) {
14 // Order is created on the server and the order id is returned
15 return fetch("/my-server/create-paypal-order", {
16 method: "POST",
17 headers: {
18 "Content-Type": "application/json",
19 },
20 // use the "body" param to optionally pass additional order information
21 // like product skus and quantities
22 body: JSON.stringify({
23 cart: [
24 {
25 sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
26 quantity: "YOUR_PRODUCT_QUANTITY",
27 },
28 ],
29 }),
30 })
31 .then((response) => response.json())
32 .then((order) => order.id);
33 }
34 onApprove(data, actions) {
35 // Order is captured on the server
36 return fetch("/my-server/capture-paypal-order", {
37 method: "POST",
38 headers: {
39 "Content-Type": "application/json",
40 },
41 body: JSON.stringify({
42 orderID: data.orderID
43 })
44 })
45 .then((response) => response.json())
46 }
47}
48@ng.core.NgModule({
49 imports: [
50 ng.platformBrowser.BrowserModule,
51 paypal.Buttons.driver('angular2', ng.core)
52 ],
53 declarations: [
54 AppComponent
55 ],
56 bootstrap: [
57 AppComponent
58 ]
59})
60class AppModule {}
61ng.platformBrowserDynamic
62 .platformBrowserDynamic()
63 .bootstrapModule(AppModule);

Vue

<div id="container">
  <app></app>
</div>
<script>
  const PayPalButton = paypal.Buttons.driver('vue', window.Vue)

  Vue.component('app', {
    // The style prop for the PayPal button should be passed in as `style-object` or `styleObject` to avoid conflict with Vue's `style` reserved prop.
    template: `
      <paypal-buttons :on-approve="onApprove" :create-order="createOrder" :on-shipping-change="onShippingChange" :on-error="onError" :style-object="style" />
    `,
    components: {
      'paypal-buttons': PayPalButton,
    },

    computed: {
      createOrder: function () {
        return (data) => {
          // Order is created on the server and the order id is returned
          return fetch("/my-server/create-paypal-order", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            // use the "body" param to optionally pass additional order information
            // like product skus and quantities
            body: JSON.stringify({
              cart: [
                {
                  sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
                  quantity: "YOUR_PRODUCT_QUANTITY",
                },
              ],
            }),
          })
          .then((response) => response.json())
          .then((order) => order.id);
        }
      },
      onApprove: function () {
        return (data) => {
          // Order is captured on the server
          return fetch("/my-server/capture-paypal-order", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify({
              orderID: data.orderID
            })
          })
          .then((response) => response.json());
        }
      },
      onShippingChange: function () {
        return (data, actions) => {
          if (data.shipping_address.country_code !== 'US') {
            return actions.reject()
          }
          return actions.resolve()
        }
      },
      onError: function () {
        return (err) => {
          console.error(err)
          window.location.href = '/your-error-page-here'
        }
      },
      style: function () {
        return {
          shape: 'pill',
          color: 'gold',
          layout: 'horizontal',
          label: 'paypal',
          tagline: false,
        }
      },
    },
  })

  const vm = new Vue({
    el: '#container',
  })
</script>

Next steps

Test in PayPal sandbox, then go live in PayPal's live environment.