Velo Tutorial: Processing Payments

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-frontend 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. A 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.

Copy
1
/********************
2
* client-side code *
3
********************/
4
5
import { createMyPayment } from 'backend/pay.web';
6
import wixPayFrontend from 'wix-pay-frontend';
7
import wixWindowFrontend from 'wix-window-frontend';
8
9
// Step 1 - User clicks a button.
10
export function myButton_click(event) {
11
// Step 2 - Call backend function.
12
// (Next, see step 3 in the backend code below.)
13
createMyPayment()
14
// When the payment has been created and a paymentId has been returned:
15
.then( (payment) => {
16
// Step 5 - Call the startPayment() function with the paymentId.
17
// Include PaymentOptions to customize the payment experience.
18
wixPayFrontend.startPayment(payment.id, {
19
"showThankYouPage": false,
20
"termsAndConditionsLink": "https://mysite.com/terms"
21
})
22
// Step 6 - Visitor enters the payment information.
23
// When the payment form is completed:
24
.then( (result) => {
25
// Step 7 - Handle the payment result.
26
// (Next, see step 8 in the backend code below.)
27
if (result.status === "Successful") {
28
wixWindowFrontend.openLightbox("Success Box");
29
} else if (result.status === "Pending") {
30
wixWindowFrontend.openLightbox("Pending Box");
31
}
32
} );
33
} );
34
}
Copy
1
/**************************
2
* backend code - pay.web.js *
3
**************************/
4
5
import { Permissions, webMethod } from 'wix-web-module';
6
import wixPay from 'wix-pay-backend';
7
8
export const createMyPayment = webMethod(Permissions.Anyone, () => {
9
// Step 3 - Create payment info object.
10
// Here we use static data. You might want to use data from a
11
// collection. To see an example of such a usage, see the API Reference.
12
let paymentInfo = {
13
"items": [
14
{
15
name: "Product 1",
16
price: 9.99
17
},
18
{
19
name: "Product 2",
20
price: 19.99
21
}
22
],
23
amount: 29.98
24
}
25
26
// Step 4 - Call createPayment() with the payment information
27
// and return the paymentId.
28
// (Next, see step 5 in the client-side code above.)
29
return wixPay.createPayment(paymentInfo);
30
});
Copy
1
/*****************************
2
* backend code - events.js *
3
*****************************/
4
5
export function wixPay_onPaymentUpdate(event) {
6
// Step 8 - Handle additional status updates using
7
// the onPaymentUpdate() event.
8
let paymentId = event.payment.id;
9
let newTransactionStatus = event.status;
10
let userInfo = event.userInfo;
11
12
// Handle new payment status.
13
}

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.

Was this helpful?
Yes
No