Step-by-step guide to generating a Paypal Button using Vue 3 script setup

After going through the PayPal Developer Docs, I'm still struggling to understand how to integrate the PayPal Button into Vue.js. The code examples provided are unclear, and I can't determine if it's related to Vue 2, Vue 3, or even Angular.

1: Firstly, import the script in the parent blade:

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

2: Should I use the button within a script tag of the component?

paypal.Buttons.driver("vue", window.Vue);

3: This part is where I'm getting lost - do I need to include this in app.js?

@ng.core.Component({
  selector: 'my-app',
  template:
    <div id="app">
        <paypal-buttons [props]="{
            createOrder: createOrder,
            onApprove: onApprove
        }"></paypal-buttons>
    </div>
  ,
})
class AppComponent {
    createOrder(data, actions) {
      return actions.order.create({
          purchase_units: [{
              amount: {
                  value: '0.01'
              }
          }]
      });
    }
    onApprove(data, actions) {
      return actions.order.capture();
    }
}
@ng.core.NgModule({
    imports: [
        ng.platformBrowser.BrowserModule,
        paypal.Buttons.driver('angular2', ng.core)
    ],
    declarations: [
        AppComponent
    ],
    bootstrap: [
        AppComponent
    ]
})
class AppModule {}
ng.platformBrowserDynamic
    .platformBrowserDynamic()
    .bootstrapModule(AppModule);

Could it be that this is actually Angular code rather than Vue code?

4: And should I place this in the Vue component?

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

  Vue.component("app", {
    // Style prop for PayPal button must be passed as `style-object` or `styleObject` to avoid conflicts.
    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, actions) => {
          return actions.order.create({
            purchase_units: [
              {
                amount: {
                  value: "10",
                },
              },
            ],
          });
        }
      },
      onApprove: function () {
        return (data, actions) => {
          return actions.order.capture();
        }
      },
      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>

I'm now wondering how I can create a simple PayPal button with Vue 3's script setup. The PayPal CDN has been imported in the parent blade file.

Is there a way to achieve something like this:

<script setup>
import {onMounted} from "vue";

onMounted(() => {
    // Create component using -> paypal.Buttons.driver("vue", window.Vue);
})
</script>


<template>
  <div id="checkout" class="checkout">
    <paypal-buttons></paypal-buttons>
  </div>
</template>

Answer №1

Here's a suggestion for how you can implement this:

  • Start by installing the official paypal-js npm package: npm install @paypal/paypal-js

Next, create your PaypalButtons Component like this:

<script setup>
import {Inertia} from '@inertiajs/inertia';
import {loadScript} from '@paypal/paypal-js';
import {onMounted} from 'vue';

const props = defineProps({
    // You can include a reference here if needed
    reference: Object
});

onMounted(async() => {
    try {
        const paypal = await loadScript({
            'client-id': <your-paypal-client-id>
        });

        await paypal.Buttons({
            createOrder: function(data, actions) {
                return actions.order.create({
                    purchase_units: [{
                        amount: {
                            value: '<your-price>',  // For example: reference.price
                        },
                    }],
                });
            },
            onApprove: function(data, actions) {
                return actions.order.capture().then(function(orderData) {
                    // Order successfully captured!
                    // e.g. Inertia.post(route('order.update', reference.orderId)
                });
            },
            style: {
                layout: 'vertical',
                color: 'gold',
                shape: 'rect',
                label: 'paypal',
            },
            fundingSource: paypal.FUNDING.PAYPAL,  // Optional - customize button options
        }).render('#paypal-button-container');
    } catch (error) {
        console.error(error);  // Add proper error handling
    }
});
</script>

<template>
    <div id="paypal-button-container"></div>
</template>

Now you can use it like this:

<PaypalButtons :reference="reference" />

Answer №2

The documentation provided by Paypal can be a bit confusing. When integrating with the server, it seems to follow these steps:

If you are using laravel as your backend, include this in your app.blade.php/welcome.blade.php file:

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

Then, your vue component should look something like this:

<script setup>
import {onMounted} from "vue";

onMounted(() => {
    paypal.Buttons({
        // Implement functions here
    }).render('#paypal-button-container');
})

</script>

<template>
  <div id="checkout" class="checkout">
    <div id="paypal-button-container"></div>
  </div>
</template>

The displayed payment methods are automatically determined based on your IP address. You can hide certain payment methods by adjusting the script import like this:

<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&disable-funding=card,giropay,sepa,sofort"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Converting a unix timestamp to a Date in TypeScript - a comprehensive guide

To retrieve the unix timestamp of a Date in plain JavaScript and TypeScript, we can use this code snippet: let currentDate = new Date(); const unixTime = currentDate.valueOf(); Converting the unix timestamp back to a Date object in JavaScript is straight ...

Is it possible to verify the versions of node and npm prior to running an npm install command?

To ensure only specific versions of node and npm are used before a user can run the npm install command on my module, I need to set certain criteria. According to NPM documentation, I can use the engine attribute for this purpose: "engines": { "nod ...

Steps for creating interconnected datepickers in jQuery with month and year selection:To create a dependent datepicker with month and year selection using

The JSFiddle I currently have is not functioning as expected. When the user directly selects the end-date, it does not restrict the start-date in this particular fiddle. It should change once the user directly changes the end-date. The functionality works ...

Is requesting transclusion in an Angular directive necessary?

An issue has cropped up below and I'm struggling to figure out the reason behind it. Any suggestions? html, <button ng-click="loadForm()">Load Directive Form</button> <div data-my-form></div> angular, app.directive(&apos ...

Each $.each function varies based on the type of object it is iterating

I have encountered an issue with my $.each statement. When it is written like this: $.each($(".permissions"), function (index, element) { ... }).promise().done(function () {...}); everything works fine. However, when I change the $.each statement to: ...

Trouble with defining variables in EJS

Recently delving into the world of node development, I encountered an issue with my EJS template not rendering basic data. I have two controllers - one for general pages like home/about/contact and another specifically for posts. When navigating to /posts ...

Utilizing jQuery to display labels only for selected checkboxes while concealing the ones that are not checked

I currently have the following setup: <style>.selectit{display:none;}</style> <div id="foo"> <label class="selectit"> <input type="checkbox" name="one" id="one" checked> One </label> <label class="selectit"> <i ...

Validation for dates in Angular.Js input is important to ensure that only

Take a look at this form: <form name="user_submission" novalidate="novalidate" method="post"> <input type="date" name="date_of_birth" ng-focus="save_data()" ng-model-options="{timezone: 'UTC'}" ng-pattern="/^(19\d{2}|[2-9]& ...

Developing an edit form using Vue and Axios: Incorporating a dynamic database value into the form field

I am currently working on an edit form using Vue and Axios, but I have encountered a conflict. Here is my Vue code: <script> import { required, minLength } from 'vuelidate/lib/validators' export default { created() { this ...

Arrange the items in a list in JavaScript in descending sequence

How to sort a list of records in JavaScript in descending order? var number; //dynamic number retrieved from API var test; //dynamic text retrieved from API for (var i; i <= accList.length; i++) { var odlist = 'you have :' + test + number ...

Removing the Tawk.to integration in React Redux using external JavaScript

Seeking help with integrating the Tawk.To Widget into my React APP. The widget (javascript) loads successfully when the page is first opened, but remains present when navigating to another page. How can I properly unmount this script when moving to a diff ...

Exploring Angular2: A Guide to Interpolating Expressions in Templates

Is it possible to interpolate different types of Javascript expressions? Along with displayed properties like object.property and short expressions such as {{1+1}}, what other valid Javascript expressions can be used for interpolation? ...

Ways to retrieve information from an Ajax post method call using an index similar to an array

My code doesn't seem to be working in the success function of my AJAX call. I suspect there might be an issue with how I'm specifying tr and td elements. Can someone help me identify where the problem might be? $(document).ready(function () { ...

What is the best way to display the value of a PHP variable in a JavaScript pop-up window?

Here are the scripts I have. A user will input a numerical value like 123 as a parameter in the URL, and the application will retrieve that value from MySQL and display it in the textarea. For example, if you enter "example.com/index.php?id=123" in the UR ...

Activate the button solely when the text field has been populated without any spaces

Searching for a solution to my query, but all the suggestions I've encountered don't consider spaces as valid input. In the join function I have, the button should be disabled if the user enters only spaces. A requirement is for actual text inpu ...

What's the issue with my ExpressJS req.query not functioning as expected?

My NodeJS repl setup includes an input, button, and h1 element. The goal is to update the HTML inside the h1 element with the value of the input upon button click. Here's a glimpse of my code: index.js: const Database = require("@replit/database ...

I find myself a little mixed up with this syntax in JavaScript: `arr.indexOf(searchElement[, fromIndex])`

const beasts = ['ant', 'bison', 'camel', 'duck', 'bison']; console.log(beasts.indexOf('bison')); // expected output: 1 // start from index 2 console.log(beasts.indexOf('bison', 2)); // ...

Is there a Wordpress floating bar similar to the one seen on 9gag?

After browsing through some posts on stackoverflow, I noticed that my website is not responding as expected. You can check out my site here: To troubleshoot, you can examine the source code and utilize Firebug to inspect the css and javascript being used ...

Exploring Vue 3.1+ and its Delimiters: Common Problems for Beginners

Hi there, I could use a little assistance. I'm just getting started with Vue and I'm having trouble changing the delimiters to get them working properly. Would someone be willing to review this code snippet and let me know if it looks like it sho ...

Communicating between PHP chat client and server

Currently, I am developing a basic PHP web chat application that interacts with a MySQL database. The communication is facilitated through AJAX requests - when a user posts a message, it gets saved in the database. function sendData(){ var textData = $(& ...