How to implement Paystack popup in Nuxt 3

Total
0
Shares

When building an e-commerce website or any other application that requires online payments, Paystack is always the first option that comes to mind and is often the preferred payment processing platform. It is a popular payment gateway in Nigeria and in many other African countries. Paystack provides an easy-to-use API that allows you to accept payments from your customers securely.

If you’re using Nuxt 3 to build your application, you may have noticed that Paystack’s official Vue package is not compatible with Nuxt 3 out of the box. In this article, we’ll show you how to implement a Paystack popup in Nuxt 3 using inline JavaScript.

Prerequisites

Before we begin, you’ll need the following:

  • A Paystack account
  • A Nuxt 3 project set-up and running

Step 1: Implement the design of your form

The code below is a simple HTML template, it sets up a basic form for collecting user information, including the first name, email address, phone number, and payment amount. It uses Vue.js’s data binding and form validation capabilities to facilitate user input and processing.

<template>
  <form>
    <div>
      <label>First Name</label>
      <input type="text" />
    </div>
    <div>
      <label>Email Address</label>
      <input type="email" required v-model="form.name" />
    </div>
    <div>
      <label>Phone Number</label>
      <input
        required
        v-model="form.phoneNumber"
        type="tel"
      />
    </div>
    <div>
      <label>Amount</label>
      <input type="number" v-model="form.amount" required />
    </div>
    <div>
      <button>Pay</button>
    </div>
  </form>
</template>

Step 2: Initialize Form Data and Load Paystack Library

The code sets up the form fields and defines the data structure for the form using an interface named FormType. It creates a reactive object form with properties for name, phoneNumber, email, and amount, initializing them with empty values or a default value of 0.

Moving on to the next step in the process, in your Nuxt 3 JavaScript, you can utilize the onMounted lifecycle hook to handle the dynamic creation of a <script> tag. This snippet allows you to set the src attribute of the <script> tag to the URL of the Paystack inline JavaScript library. Once the script is created, it can be appended to the <body> element of the current HTML page. This enables the loading of the Paystack library and facilitates further integration with the payment service.

<script setup lang="ts">

//some codes...

//initialize form data 
interface FormType {
  name: string;
  phoneNumber: string;
  email: string;
  amount: number;
}
const form = reactive({
  name: "",
  phoneNumber: "",
  email: "",
  amount: 0,
} as FormType);


//Load Paystack Library
onMounted(() => {
  const script = document.createElement("script");
  script.setAttribute("src", "https://js.paystack.co/v1/inline.js");
  document.body.appendChild(script);
});
</script>

NOTE The code snippet above will only load the Paystack inline script dynamically for the component where it is used. If you want to make the script available globally across your Nuxt 3 application, you can add it to the head section of your HTML file by creating a plugin.

Step 3: Linking Form Details to Paystack and Initiating Checkout Popup

After obtaining all the necessary transaction details from the form, the subsequent step involves linking them to a JavaScript function that transfers the details to Paystack and presents the checkout popup modal.

const initializePayment = () => {
  const handler = PaystackPop.setup({
    key: "YOUR_PAYSTACK_PUBLIC_KEY", //Replace with your public key
    email: form.email, //replace with user email
    amount: form.amount * 100, // the amount value is multiplied by 100 to convert to the lowest currency unit

    currency: "NGN", // Use GHS for Ghana Cedis or USD for US Dollars

    ref: random, // Replace with a reference you generated
    callback: function (response: any) {
      //this happens after the payment is completed successfully
      var reference = response.reference;
      alert("Payment complete! Reference: " + reference);

      //this happens after the payment is completed successfully
      router.push({
        path: "/success",
        query: {
          name: `${form.name}`,
        },
      });
      // Make an AJAX call to your server with the reference to verify the transaction
    },
    onClose: function () {
      alert("Transaction was not completed, window closed.");
    },
  });
  handler.openIframe();
};

If you have followed these steps correctly, your vue component should be similar to the following code:

<template>
  <form>
    <div>
      <label>First Name</label>
      <input type="text" />
    </div>
    <div>
      <label>Email Address</label>
      <input type="email" required v-model="form.name" />
    </div>
    <div>
      <label>Phone Number</label>
      <input
        required
        v-model="form.phoneNumber"
        type="tel"
      />
    </div>
    <div>
      <label>Amount</label>
      <input type="number" v-model="form.amount" required />
    </div>
    <div>
      <button>Pay</button>
    </div>
  </form>
</template>

<script setup lang="ts">
//some codes...

interface FormType {
  name: string;
  phoneNumber: string;
  email: string;
  amount: number;
}
const form = reactive({
  name: "",
  phoneNumber: "",
  email: "",
  amount: 0,
} as FormType);

//router allows navigation and manipulation of the application's routing system.
const router = useRouter();


function generateReference(prefix: string): string {
  // Function to generate a random transaction reference with a given prefix
  const length = 10;
  const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  let result = prefix;

  // Generate random characters and append them to the prefix
  for (let i = length; i > 0; --i) {
    result += chars[Math.floor(Math.random() * chars.length)];
  }

  // Return the generated transaction reference
  return result;
}

const random: string = generateReference("My Transaction Reference");

const initializePayment = () => {
  const handler = PaystackPop.setup({
    key: "YOUR_PUBLIC_KEY", //Replace with your public key
    email: form.email, //replace with user email
    amount: form.amount * 100, // the amount value is multiplied by 100 to convert to the lowest currency unit

    currency: "NGN", // Use GHS for Ghana Cedis or USD for US Dollars

    ref: random, // Replace with a reference you generated or use the provided function above
    callback: function (response: any) {
      //this happens after the payment is completed successfully
      var reference = response.reference;
      alert("Payment complete! Reference: " + reference);

      //this happens after the payment is completed successfully
      router.push({
        path: "/success",
        query: {
          name: `${form.name}`,
        },
      });
      // Make an AJAX call to your server with the reference to verify the transaction
    },
    onClose: function () {
      alert("Transaction was not completed, window closed.");
    },
  });
  handler.openIframe();
};

onMounted(() => {
  const script = document.createElement("script");
  script.setAttribute("src", "https://js.paystack.co/v1/inline.js");
  document.body.appendChild(script);
});
</script>

Step 4: Trigger the payment function

To proceed with the next step, let’s first recap the initial phase where we implemented the UI design of the form. Now, we’ll enhance its functionality by adding event listeners. To trigger the payment function, you can associate it with the @submit event of your form in the template like so:

<template>
  <form @submit.prevent="initializePayment">
    <div>
      <label>First Name</label>
      <input type="text" />
    </div>
    <div>
      <label>Email Address</label>
      <input type="email" required v-model="form.name" />
    </div>
    <div>
      <label>Phone Number</label>
      <input
        required
        v-model="form.phoneNumber"
        type="tel"
      />
    </div>
    <div>
      <label>Amount</label>
      <input type="number" v-model="form.amount" required />
    </div>
    <div>
      <button type="submit">Pay</button>
    </div>
  </form>
</template>


In the updated form code snippet above, the following changes have been made:

  1. The @submit.prevent="initializePayment" event listener has been added to the <form> tag. This ensures that the initializePayment method is called when the form is submitted, preventing the default form submission behavior.
  2. The <button> element has been updated with the type="submit" attribute. This specifies that the button acts as a submit button within the form and triggers the form submission when clicked.

Other than these changes, the structure and form fields remain the same as the previously shared code.

Conclusion

To sum up, we’ve covered the implementation of the Paystack popup in Nuxt 3 using inline JavaScript. This approach enables you to overcome compatibility problems with Paystack’s official Vue package and effectively integrate the Paystack payment service into your Nuxt 3 project.

To learn more about PayStack pop-up, visit the official documentation and also feel free to ask your questions by commenting below.

Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like