Creating a Payment Flow using Velo Pay API

Written by velo | Published 2021/05/15
Tech Story Tags: velo | web-development | ecommerce-web-development | ecommerce | wix | tutorial | coding-with-velo | digital-payments

TLDR Velo Pay API allows you to collect payments from your site's visitors outside the context of a Wix App like Wix Stores. The Pay API is split between backend and client-side functions to facilitate a secure payment process as described below. The following is an example showing the payment lifecycle in code. For security reasons you should always create the payment information in the backend code. Do not pass payment information from client side code which can be easily exploited. If you want to perform operations based on a payment's status, always use the status updates received by the backend payment events.via the TL;DR App

Using the Velo Pay API you can collect payments from your site's visitors outside the context of a Wix App like Wix Stores. The API allows you to collect a payment when triggered by any user interaction on any page.
Warning:
Before starting with payments, it is important that you fully understand how to handle the security concerns detailed below that arise when collecting payments.

Prerequisites

Before using the Pay API, you need to set up your site to accept payments. To learn more, see About Accepting Payments.
Note:
When setting up your site to accept payments, be sure to select the payment methods you want to offer and set your payment currency.
Additionally, you will need to be familiar with creating backend web modules and calling the functions defined in them from page code. To learn more, see Calling Server-Side Code from the Front-End with Web Modules.
You also might want to familiarize yourself with who can see and call your site's code. To learn more, see the Code Visibility section of Security Considerations When Working with Velo.

Pay API

Note:
To work with the Pay API, you need to save and publish your site. 
The Pay API is split between backend and client-side functions to facilitate a secure payment process as described below. It consists of two functions and one event:
  • createPayment()
     - Called in backend code to create a payment and generate a 
    paymentId
    .
  • startPayment()
     - Called in client-side code to prompt the current site visitor to enter the payment information.
  • onPaymentUpdate()
     - Fired in backend code when a payment's status has changed.
For detailed information on the Pay API see wix-pay and wix-pay-backend in the API Reference.

Payment Lifecycle

The following list outlines the steps taken in a typical payment lifecycle:
  1. A site visitor clicks a button to start the payment process.
  2. The button's event handler calls a backend function.
  3. PaymentInfo
     object containing information about the payment, such as the payment amount, is created in the backend function.
  4. The backend function calls 
    createPayment()
     using the 
    PaymentInfo
     object and returns the generated 
    Payment
     object to the calling client-side event handler.
  5. The event handler then calls the 
    startPayment()
     function with the 
    id
     from the 
    Payment
     object, which opens the payment popup on your site.
  6. The site visitor enters the payment information.
  7. The event handler optionally handles the returned 
    PaymentResult
    .
  8. Handle additional status updates to the payment transaction using the 
    onPaymentUpdate()
     event.

Payment Code Example

The following is an example showing the payment lifecycle in code. The numbered comments correspond to the numbered steps in the payment lifecycle described above.
/********************
 * client-side code *
 ********************/

import {createMyPayment} from 'backend/pay';
import wixPay from 'wix-pay';
import wixWindow from 'wix-window';

// Step 1 - User clicks a button.
export function myButton_click(event) {
  // Step 2 - Call backend function. 
  // (Next, see step 3 in the backend code below.)
  createMyPayment()
    // When the payment has been created and a paymentId has been returned:
    .then( (payment) => {
      // Step 5 - Call the startPayment() function with the paymentId.
      // Include PaymentOptions to customize the payment experience.
      wixPay.startPayment(payment.id, {
          "showThankYouPage": false,
          "termsAndConditionsLink": "https://mysite.com/terms"
      })
      // Step 6 - Visitor enters the payment information.
      // When the payment form is completed:
        .then( (result) => {
          // Step 7 - Handle the payment result.
          // (Next, see step 8 in the backend code below.)
          if (result.status === "Successful") {
            wixWindow.openLightbox("Success Box");
          } else if (result.status === "Pending") {
            wixWindow.openLightbox("Pending Box");
          }
      } );
    } );
}
/**************************
 * backend code - pay.jsw *
 **************************/

import wixPay from 'wix-pay-backend';

export function createMyPayment() {
  // Step 3 - Create payment info object.
  // Here we use static data. You might want to use data from a
  // collection. To see an example of such a usage, see the API Reference.
  let paymentInfo = {
    "items": [ 
      {
        name: "Product 1",
        price: 9.99
      },
      {
        name: "Product 2",
        price: 19.99
      }
    ],
    amount: 29.98
  }
  
  // Step 4 - Call createPayment() with the payment information 
  // and return the paymentId.
  // (Next, see step 5 in the client-side code above.)
  return wixPay.createPayment(paymentInfo);
}
/*****************************
 * backend code - events.js  *
 *****************************/

export function wixPay_onPaymentUpdate(event) {
  // Step 8 - Handle additional status updates using 
  // the onPaymentUpdate() event.
  let paymentId = event.payment.id;
  let newTransactionStatus = event.status;
  let userInfo = event.userInfo;
  
  // Handle new payment status.
}

Security Considerations

For security reasons you should always create the 
PaymentInfo
 object (step 3 above) in backend code. Do not pass payment information from client-side code.
Passing payment information from client-side code opens a vulnerability which is easily exploited. Since malicious site visitors can call your exported backend functions from the browser, they would be able to alter the payment information that is passed to the backend code. For example, if you pass the price of an item being purchased from client-side code, a user can change the price of the item.
To securely process a payment, always define the payment information in the backend. Even though malicious users can call the backend function, they cannot see or change what happens in that function. If needed, you can also include additional validations in your backend function.
If you want to perform operations based on a payment's status, always use the status updates received by the backend payment events. Status information that is received in client-side code should only be used for display purposes.

Written by velo | Velo is a full-stack development platform that empowers you to rapidly build, manage and deploy professional web apps.
Published by HackerNoon on 2021/05/15