Creating a Payment Order
Relevant source files
The following files were used as context for generating this wiki page:Introduction
This document outlines the process of creating a payment order by integrating with the ZaloPay gateway. The system is a Node.js application that serves as a backend to facilitate payment transactions. The core functionality involves receiving a payment request from a client, constructing a valid order payload, signing it, sending it to the ZaloPay API, and returning a payment URL to the client. The application also handles callback notifications from ZaloPay to confirm transaction status.
The primary components involved are the server setup, routing, configuration management, and the ZaloPay helper module which contains the business logic for API interaction.
Sources: index.js, routes/index.js, common/zalopay.js
System Configuration
All necessary credentials and endpoints for the ZaloPay integration are stored in a central configuration file. This isolates sensitive information and service-specific URLs from the main application logic.
Sources: config/config.js
Configuration Parameters
The following table details the parameters defined in the configuration.
| Parameter | Type | Description |
|---|---|---|
app_id | String | The application ID provided by ZaloPay. |
key1 | String | The first key used for generating the mac (Message Authentication Code) for creating orders. |
key2 | String | The second key used for verifying the signature of callback (IPN) requests from ZaloPay. |
endpoint | String | The URL of the ZaloPay API endpoint for creating new payment orders. |
Sources: config/config.js:3-8
Order Creation Flow
The process begins when a user initiates a payment from the client-side. This triggers a request to the application's backend, which then communicates with the ZaloPay API to create the order.
Sequence of Events
The following diagram illustrates the sequence of interactions between the client, the Node.js server, and the ZaloPay API.
Sources: routes/index.js:10-23, common/zalopay.js:10-34
API Endpoint
The order creation is handled by a single API endpoint.
- Endpoint:
POST /api/create-order - Description: Receives payment details, orchestrates the creation of a ZaloPay order, and returns the payment URL.
- Handler: The route is defined in
routes/index.jsand calls theZaloPay.CreateOrdermethod.
Sources: routes/index.js:10-23
Order Data Structure
To create an order, the server constructs a specific data object. A unique transaction ID (app_trans_id) is generated for each order using the current date and a random suffix.
The key fields for the order creation request are:
| Field | Description | Source |
|---|---|---|
app_id | The application ID from the configuration. | config.app_id |
app_trans_id | A unique transaction ID for the merchant's system (e.g., YYMMDD_random). | moment().format('YYMMDD') + '_' + Date.now() |
app_user | The user initiating the payment. Hardcoded to "user123". | user123 |
app_time | The transaction timestamp in milliseconds. | Date.now() |
amount | The transaction amount, received from the client request. | req.body.amount |
item | A JSON string representing the items in the cart. Hardcoded in this implementation. | JSON.stringify({}) |
embed_data | A JSON string for extra data. Includes the redirecturl. | JSON.stringify({ redirecturl }) |
description | A description for the order. | ZaloPay Integration for NodeJS |
bank_code | The bank code for the transaction. An empty string allows the user to select on ZaloPay's side. | "" |
mac | The HMAC signature to ensure data integrity. | Generated via HMAC-SHA256 |
Sources: common/zalopay.js:12-26
HMAC Signature Generation
A critical step is the generation of a Message Authentication Code (mac) to sign the order request. This ensures that the request has not been tampered with.
The following flowchart shows the process for generating the mac.
The data string for the HMAC is created by joining the following fields with a | separator: app_id|app_trans_id|app_user|amount|app_time|embed_data|item. This string is then encrypted using HMAC-SHA256 with key1.
Sources: common/zalopay.js:23-25
Payment Callback Handling
After the user completes the payment, ZaloPay sends a server-to-server callback (IPN) to notify the application of the transaction status.
- Endpoint:
POST /api/callback - Description: Receives transaction status updates from ZaloPay. It validates the data's integrity using
key2before processing.
Sources: routes/index.js:25-41
Callback Validation
The callback handler must verify that the request is genuinely from ZaloPay. This is done by generating an HMAC signature on the received data and comparing it with the mac provided in the callback body.
The validation process is as follows:
- The server receives a POST request at
/api/callbackwith a JSON body containing transaction data and amac. - It uses
key2from the configuration to compute an HMAC-SHA256 signature on thedatafield of the callback body. - This computed signature is compared to the
macfield from the callback body. - If the signatures match, the callback is considered valid, and the server can proceed to update the order status in its own database (though this final step is not implemented in the provided files).
- The server responds to ZaloPay with a
return_codeandreturn_messageto acknowledge receipt.
Sources: common/zalopay.js:36-47, routes/index.js:26-40
Frontend View
A simple frontend form is provided to initiate the payment process. It allows a user to enter an amount and click a button to create the order.
The view is rendered using the Pug template engine and is served on the root path /.
//- Source: views/index.pug:10-14
form(action='/api/create-order' method='POST')
.form-group
label Amount
input.form-control(name='amount' value='50000')
button.btn.btn-primary(type='submit') Create Order
When this form is submitted, it sends a POST request to the /api/create-order endpoint, triggering the entire payment flow.
Sources: views/index.pug, routes/index.js:8