Collection Link – Tạo liên kết thanh toán

Nội dung Markdown đầy đủ của trang tài liệu.

# 🔗 Collection Link – Tạo liên kết thanh toán

[Xem API hủy đơn hàng chưa thanh toán](/api/cancel-order).

Để kiểm thử tự động với đơn demo, dùng [API mô phỏng thanh toán](/api/simulate-payment) sau khi create thành công.

::: info Cần gửi dữ liệu xuất hóa đơn điện tử?
Tích hợp mới nên xem [Collection Link V2](/api/collection-link-v2). V2 bổ sung metadata người mua, hàng hóa và yêu cầu xuất HĐĐT nhưng vẫn giữ nguyên endpoint tạo đơn.
:::

## 🧠 Khái niệm

Collection Link là API dùng để khởi tạo đơn hàng từ website của merchant đến hệ thống Pay2S.

## 🔄 Luồng xử lý

1. Khách hàng thực hiện mua hàng trên Website hoặc ứng dụng của merchant và lựa chọn thanh toán trực tuyến Napas 247 cho đơn hàng.
2. Website hoặc ứng dụng của merchant tiến hành gọi tạo link thanh toán, Pay2S sẽ kiểm tra dữ liệu và trả về kết quả chứa link thanh toán. Khi hệ thống của merchant nhận kết quả link thanh toán cần chuyển hướng khách hàng của bạn đến trang checkout của Pay2S bằng cách mở link thanh toán từ kết quả.
3. Khách hàng sử dụng ứng dụng ngân hàng để quét mã VietQR từ link thanh toán.
4. Giao dịch ghi nhận thành công tại ngân hàng, Pay2S sẽ trả kết quả thành công về redirectUrl gồm: trạng thái, mã đơn hàng, mã link thanh toán, ... Từ kết quả nhận được trên redirectUrl Website hoặc ứng dụng của merchant hiển thị giao diện thành công.
5. Sau khi có kết quả ở giao diện, đồng thời Pay2S sẽ gửi một kết quả với đầy đủ thông tin thanh toán tới ipnUrl của cửa hàng, sau đó merchant cập nhật trạng thái đơn hàng phù hợp.

## ⚙️ Cấu hình API

### 🔸 HTTP Request

- **URL**: `https://payment.pay2s.vn/v1/gateway/api/create`
- **Method**: `POST`
- **Content-Type**: `application/json; charset=UTF-8`

### Request Parameters

| Key           | Type       | Required | Description                                        |
| ------------- | ---------- | -------- | -------------------------------------------------- |
| partnerCode   | String     | ✓        | Định danh duy nhất cho mỗi yêu cầu.                |
| partnerName   | String     |          | Tên đối tác.                                       |
| requestId     | String(50) | ✓        | Định danh duy nhất cho mỗi yêu cầu.                |
| amount        | Long       | ✓        | Số tiền cần thanh toán (VND).                      |
| bankAccounts | String     | ✓        | Mảng chứa các số tài khoản và Bank Code.  |
| orderId       | String     | ✓        | Mã đơn hàng của đối tác.                           |
| orderInfo     | String     | ✓        | Thông tin đơn hàng. Lưu ý: Giới hạn 10-32 ký tự, chỉ chấp nhậ ký tự chữ + số, không dấu gạch ngang hoặc đặc biêt.                             |
| redirectUrl   | String     | ✓        | URL chuyển hướng sau khi thanh toán.               |
| ipnUrl        | String     | ✓        | API nhận kết quả thanh toán của đối tác.           |
| requestType   | String     | ✓        | Định danh kiểu của request.                        |
| signature     | String     | ✓        | [Chữ ký](/others/signature.md) xác nhận giao dịch. Sử dụng thuật toán Hmac_SHA256 với data theo định dạng: 1 chuỗi String được sort theo thứ tự:` accessKey=$accessKey&amount=$amount&bankAccounts=Array&ipnUrl=$ipnUrl&orderId=$orderId&orderInfo=$orderInfo&partnerCode=$partnerCode&redirectUrl=$redirectUrl&requestId=$requestId&requestType=$requestType`                         |

### 📦 Sample Request

```json
{
  "accessKey": "YOUR_KEY",
  "partnerCode": "PAY2S7EPF0SB1ZP27W71",
  "partnerName": "Cửa hàng trải nghiệm",
  "requestId": "DEVd33eb1381791659971923e7ba11",
  "amount": 250000,
  "orderId": "DEVd33eb1381791659971923e7ba11",
  "orderInfo": "TT81791659971923e7ba11",
  "bankAccounts": [
    {
      "account_number": "P2S99999999",
      "bank_id": "ACB"
    }
  ],
  "redirectUrl": "https://developer.example.com/demos/?mode=live",
  "ipnUrl": "https://developer.example.com/sandbox/live-receiver/ipn",
  "requestType": "pay2s",
  "signature": "<SIGNATURE>"
}
```

### 📦 Sample Response

```json
{
  "partnerCode": "PAY2S7EPF0SB1ZP27W71",
  "requestId": "DEVd33eb1381791659971923e7ba11",
  "orderId": "DEVd33eb1381791659971923e7ba11",
  "orderInfo": "TT81791659971923e7ba11",
  "amount": 250000,
  "message": "Thành công",
  "lang": "vi",
  "resultCode": 0,
  "qrList": [
    {
      "bank_id": "ACB",
      "account_number": "P2S99999999",
      "account_name": "TAI KHOAN DEMO ACB",
      "qrCode": "<QRCODE_OMITTED>",
      "qrData": "00020101021238550010A000000727012500069704160111P2S999999990208QRIBFTTA52040000530370454062500005802VN62260822TT81791659971923e7ba11630497F4",
      "qrUrl": "https://sandbox-payment.pay2s.vn/quicklink/ACB/P2S99999999/TAI%20KHOAN%20DEMO%20ACB?amount=250000&memo=TT81791659971923e7ba11&is_mask=0"
    }
  ],
  "payUrl": "https://sandbox-payment.pay2s.vn/v2/gateway/pay?t=YOUR_KEY",
  "storeId": null,
  "credentialScope": "owner",
  "isDemo": true,
  "environment": "demo"
}
```

## 💻 Code mẫu

::: code-group
``` php [PHP]

function execPostRequest($url, $data)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Content-Length: ' . strlen($data))
    );
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    
    $result = curl_exec($ch);
    curl_close($ch);
    
    echo($result);
    $jsonResult = json_decode($result, true);
    
    // Điều hướng đến URL thanh toán nếu có
    if (isset($jsonResult['payUrl'])) {
        header('Location: ' . $jsonResult['payUrl']);
    }
    
    return $result;
}

$endpoint = 'https://payment.pay2s.vn/v1/gateway/api/create';
$merchantName = "TEST";
$accessKey = '';
$secretKey = '';
$orderInfo = 'pay with Pay2S';
$order_desc = 'DH{{orderid}}';
$partnerCode = 'PAY2S72MLKFJFURCGPEM';
$redirectUrl = 'https://webhook.site/dd3de633-0a13-40e8-996d-ccd195d7237b';
$ipnUrl = 'https://webhook.site/dd3de633-0a13-40e8-996d-ccd195d7237b';
$amount = '50000';
$bank_accounts = "9877644888|vcb";
$orderId = time()."";
$requestId = time()."";
$extraData = '';
$requestType = 'pay2s';
$partnerName = 'Pay2S Payment';
$lang = 'vi';

if (!empty($_POST)) {
    $accessKey = $_POST["accessKey"];
    $secretKey = $_POST["secretKey"];
    $orderInfo = $_POST["orderInfo"];
    $partnerCode = $_POST["partnerCode"];
    $redirectUrl = $_POST["redirectUrl"];
    $amount = $_POST["amount"];
    $orderId = $_POST["orderId"];
    $order_desc = $_POST['order_desc'];
    $orderInfo = str_replace('{{orderid}}', $orderId, $_POST['order_desc']);
    $bank_accounts = $_POST['bank_accounts'];
    
    $lines = explode("\n", $bank_accounts);
    $bankList = [];
    foreach ($lines as $line) {
        // Tách từng dòng thành account_number và bank_id
        list($accountNumber, $bankId) = explode('|', trim($line));
        // Đưa các giá trị này vào mảng kết quả
        $bankList[] = [
            'account_number' => trim($accountNumber),
            'bank_id' => trim($bankId)
        ];
    }

    $requestId = time() . '';
    $extraData = "";
   
    // Tạo chữ ký HMAC SHA256
    $rawHash = "accessKey=" . $accessKey . "&amount=" . $amount . "&bankAccounts=Array&ipnUrl=" . $ipnUrl . "&orderId=" . $orderId . "&orderInfo=" . $orderInfo . "&partnerCode=" . $partnerCode . "&redirectUrl=" . $redirectUrl . "&requestId=" . $requestId . "&requestType=" . $requestType;
    $signature = hash_hmac("sha256", $rawHash, $secretKey);

    $data = array(
        'accessKey' => $accessKey,
        'partnerCode' => $partnerCode,
        'partnerName' => $merchantName,
        'requestId' => $requestId,
        'amount' => $amount,
        'orderId' => $orderId,
        'orderInfo' => $orderInfo,
        'orderType' => $requestType,
        'bankAccounts' => $bankList,
        'redirectUrl' => $redirectUrl,
        'ipnUrl' => $ipnUrl,
        'requestType' => $requestType,
        'signature' => $signature,
    );

    $result = execPostRequest($endpoint, json_encode($data));
    $jsonResult = json_decode($result, true);  // decode json
}
?>
```
```js [NodeJS]
const axios = require('axios');
const crypto = require('crypto');

// Các giá trị mặc định
let endpoint = 'https://payment.pay2s.vn/v1/gateway/api/create';
let merchantName = "TEST";
let accessKey = '';
let secretKey = '';
let orderInfo = 'pay with Pay2S';
let order_desc = 'DH{{orderid}}';
let partnerCode = 'PAY2S72MLKFJFURCGPEM';
let redirectUrl = 'https://webhook.site/dd3de633-0a13-40e8-996d-ccd195d7237b';
let ipnUrl = 'https://webhook.site/dd3de633-0a13-40e8-996d-ccd195d7237b';
let amount = '50000';
let bank_accounts = "9877644888|vcb";
let orderId = Date.now() + '';
let requestId = Date.now() + '';
let extraData = '';
let requestType = 'pay2s';
let partnerName = 'Pay2S Payment';
let lang = 'vi';

// Dữ liệu POST
accessKey = 'yourAccessKey'; // Thay thế bằng giá trị từ form POST
secretKey = 'yourSecretKey'; // Thay thế bằng giá trị từ form POST
orderInfo = 'pay with Pay2S';
partnerCode = 'yourPartnerCode'; // Thay thế bằng giá trị từ form POST
redirectUrl = 'https://your-redirect-url.com';
amount = '50000'; // Thay thế bằng giá trị từ form POST
orderId = Date.now() + '';
order_desc = order_desc.replace('{{orderid}}', orderId);
bank_accounts = '9877644888|vcb'; // Thay thế bằng giá trị từ form POST

// Chuyển đổi danh sách tài khoản ngân hàng
const lines = bank_accounts.split('\n');
const bankList = lines.map(line => {
    const [accountNumber, bankId] = line.trim().split('|');
    return {
        account_number: accountNumber.trim(),
        bank_id: bankId.trim(),
    };
});

// Tạo chữ ký HMAC SHA256
const rawHash = `accessKey=${accessKey}&amount=${amount}&bankAccounts=Array&ipnUrl=${ipnUrl}&orderId=${orderId}&orderInfo=${orderInfo}&partnerCode=${partnerCode}&redirectUrl=${redirectUrl}&requestId=${requestId}&requestType=${requestType}`;
const signature = crypto.createHmac('sha256', secretKey).update(rawHash).digest('hex');

// Dữ liệu gửi đi
const data = {
    accessKey: accessKey,
    partnerCode: partnerCode,
    partnerName: merchantName,
    requestId: requestId,
    amount: amount,
    orderId: orderId,
    orderInfo: orderInfo,
    orderType: requestType,
    bankAccounts: bankList,
    redirectUrl: redirectUrl,
    ipnUrl: ipnUrl,
    requestType: requestType,
    signature: signature,
};

// Hàm thực hiện POST request
async function execPostRequest(url, data) {
    try {
        const response = await axios.post(url, data, {
            headers: {
                'Content-Type': 'application/json',
            },
        });
        return response.data;
    } catch (error) {
        console.error('Error:', error.response ? error.response.data : error.message);
    }
}

// Gửi yêu cầu tới API
execPostRequest(endpoint, data).then(result => {
    console.log('Result:', result);
});
```
```js [ASP]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

namespace Pay2SExample.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class Pay2SController : ControllerBase
    {
        private readonly HttpClient _httpClient;

        public Pay2SController(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }

        [HttpPost("create-payment")]
        public async Task<IActionResult> CreatePayment()
        {
            string endpoint = "https://payment.pay2s.vn/v1/gateway/api/create";
            string merchantName = "TEST";
            string accessKey = "yourAccessKey";
            string secretKey = "yourSecretKey";
            string orderInfo = "pay with Pay2S";
            string orderDesc = "DH{{orderid}}";
            string partnerCode = "PAY2S72MLKFJFURCGPEM";
            string redirectUrl = "https://your-redirect-url.com";
            string ipnUrl = "https://your-ipn-url.com";
            string amount = "50000";
            string bankAccounts = "9877644888|vcb";
            string orderId = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            string requestId = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
            string requestType = "pay2s";
            string partnerName = "Pay2S Payment";

            // Tạo danh sách tài khoản ngân hàng
            var bankList = bankAccounts.Split("\n")
                .Select(line =>
                {
                    var parts = line.Split('|');
                    return new
                    {
                        account_number = parts[0].Trim(),
                        bank_id = parts[1].Trim()
                    };
                }).ToList();

            // Tạo chuỗi chữ ký (rawHash)
            string rawHash = $"accessKey={accessKey}&amount={amount}&bankAccounts=Array&ipnUrl={ipnUrl}&orderId={orderId}&orderInfo={orderInfo}&partnerCode={partnerCode}&redirectUrl={redirectUrl}&requestId={requestId}&requestType={requestType}";

            // Tạo chữ ký HMAC SHA256
            string signature = CreateSignature(rawHash, secretKey);

            // Chuẩn bị dữ liệu POST
            var requestData = new
            {
                accessKey,
                partnerCode,
                partnerName = merchantName,
                requestId,
                amount,
                orderId,
                orderInfo,
                orderType = requestType,
                bankAccounts = bankList,
                redirectUrl,
                ipnUrl,
                requestType,
                signature
            };

            // Gửi yêu cầu POST tới API
            var response = await _httpClient.PostAsync(endpoint, new StringContent(JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json"));

            // Xử lý phản hồi
            string result = await response.Content.ReadAsStringAsync();
            return Ok(JsonConvert.DeserializeObject(result));
        }

        // Hàm tạo chữ ký HMAC SHA256
        private string CreateSignature(string rawData, string secretKey)
        {
            var key = Encoding.UTF8.GetBytes(secretKey);
            using (var hmac = new HMACSHA256(key))
            {
                var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(rawData));
                return BitConverter.ToString(hash).Replace("-", "").ToLower();
            }
        }
    }
}
```
```python [Python]
import requests
import hmac
import hashlib
import json
import time

def create_signature(raw_data, secret_key):
    """Tạo chữ ký HMAC SHA256"""
    signature = hmac.new(
        secret_key.encode('utf-8'),
        raw_data.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return signature

def create_payment():
    endpoint = 'https://payment.pay2s.vn/v1/gateway/api/create'
    merchant_name = "TEST"
    access_key = "yourAccessKey"
    secret_key = "yourSecretKey"
    order_info = "pay with Pay2S"
    partner_code = "PAY2S72MLKFJFURCGPEM"
    redirect_url = "https://your-redirect-url.com"
    ipn_url = "https://your-ipn-url.com"
    amount = "50000"
    bank_accounts = "9877644888|vcb"
    order_id = str(int(time.time()))
    request_id = str(int(time.time()))
    request_type = "pay2s"

    # Tạo danh sách tài khoản ngân hàng
    bank_list = []
    for line in bank_accounts.split('\n'):
        parts = line.strip().split('|')
        bank_list.append({
            'account_number': parts[0].strip(),
            'bank_id': parts[1].strip()
        })

    # Tạo chuỗi chữ ký
    raw_hash = f"accessKey={access_key}&amount={amount}&bankAccounts=Array&ipnUrl={ipn_url}&orderId={order_id}&orderInfo={order_info}&partnerCode={partner_code}&redirectUrl={redirect_url}&requestId={request_id}&requestType={request_type}"
    
    # Tạo chữ ký
    signature = create_signature(raw_hash, secret_key)

    # Chuẩn bị dữ liệu
    data = {
        'accessKey': access_key,
        'partnerCode': partner_code,
        'partnerName': merchant_name,
        'requestId': request_id,
        'amount': amount,
        'orderId': order_id,
        'orderInfo': order_info,
        'orderType': request_type,
        'bankAccounts': bank_list,
        'redirectUrl': redirect_url,
        'ipnUrl': ipn_url,
        'requestType': request_type,
        'signature': signature,
    }

    # Gửi yêu cầu
    response = requests.post(endpoint, json=data, headers={'Content-Type': 'application/json'})
    
    if response.status_code == 200:
        result = response.json()
        print(json.dumps(result, indent=2))
        return result
    else:
        print(f"Error: {response.status_code}")
        return None

if __name__ == "__main__":
    create_payment()
```
```java [Java]
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;

public class Pay2SPayment {
    
    public static String createSignature(String rawData, String secretKey) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(
            secretKey.getBytes(StandardCharsets.UTF_8),
            0,
            secretKey.getBytes(StandardCharsets.UTF_8).length,
            "HmacSHA256"
        );
        mac.init(secretKeySpec);
        byte[] hash = mac.doFinal(rawData.getBytes(StandardCharsets.UTF_8));
        
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static void main(String[] args) throws Exception {
        String endpoint = "https://payment.pay2s.vn/v1/gateway/api/create";
        String merchantName = "TEST";
        String accessKey = "yourAccessKey";
        String secretKey = "yourSecretKey";
        String orderInfo = "pay with Pay2S";
        String partnerCode = "PAY2S72MLKFJFURCGPEM";
        String redirectUrl = "https://your-redirect-url.com";
        String ipnUrl = "https://your-ipn-url.com";
        String amount = "50000";
        String bankAccounts = "9877644888|vcb";
        String orderId = String.valueOf(System.currentTimeMillis());
        String requestId = String.valueOf(System.currentTimeMillis());
        String requestType = "pay2s";

        // Tạo danh sách tài khoản ngân hàng
        JsonArray bankList = new JsonArray();
        for (String line : bankAccounts.split("\\n")) {
            String[] parts = line.trim().split("\\|");
            JsonObject bank = new JsonObject();
            bank.addProperty("account_number", parts[0].trim());
            bank.addProperty("bank_id", parts[1].trim());
            bankList.add(bank);
        }

        // Tạo chuỗi chữ ký
        String rawHash = String.format(
            "accessKey=%s&amount=%s&bankAccounts=Array&ipnUrl=%s&orderId=%s&orderInfo=%s&partnerCode=%s&redirectUrl=%s&requestId=%s&requestType=%s",
            accessKey, amount, ipnUrl, orderId, orderInfo, partnerCode, redirectUrl, requestId, requestType
        );

        String signature = createSignature(rawHash, secretKey);

        // Chuẩn bị dữ liệu
        JsonObject data = new JsonObject();
        data.addProperty("accessKey", accessKey);
        data.addProperty("partnerCode", partnerCode);
        data.addProperty("partnerName", merchantName);
        data.addProperty("requestId", requestId);
        data.addProperty("amount", amount);
        data.addProperty("orderId", orderId);
        data.addProperty("orderInfo", orderInfo);
        data.addProperty("orderType", requestType);
        data.add("bankAccounts", bankList);
        data.addProperty("redirectUrl", redirectUrl);
        data.addProperty("ipnUrl", ipnUrl);
        data.addProperty("requestType", requestType);
        data.addProperty("signature", signature);

        // Gửi yêu cầu
        URL url = new URL(endpoint);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setDoOutput(true);

        String jsonData = new Gson().toJson(data);
        try (OutputStream os = conn.getOutputStream()) {
            os.write(jsonData.getBytes(StandardCharsets.UTF_8));
        }

        int responseCode = conn.getResponseCode();
        System.out.println("Response Code: " + responseCode);
    }
}
```
```go [Go]
package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type BankAccount struct {
	AccountNumber string `json:"account_number"`
	BankID        string `json:"bank_id"`
}

type PaymentRequest struct {
	AccessKey     string         `json:"accessKey"`
	PartnerCode   string         `json:"partnerCode"`
	PartnerName   string         `json:"partnerName"`
	RequestID     string         `json:"requestId"`
	Amount        string         `json:"amount"`
	OrderID       string         `json:"orderId"`
	OrderInfo     string         `json:"orderInfo"`
	OrderType     string         `json:"orderType"`
	BankAccounts  []BankAccount  `json:"bankAccounts"`
	RedirectURL   string         `json:"redirectUrl"`
	IPNURL        string         `json:"ipnUrl"`
	RequestType   string         `json:"requestType"`
	Signature     string         `json:"signature"`
}

func createSignature(rawData, secretKey string) string {
	h := hmac.New(sha256.New, []byte(secretKey))
	h.Write([]byte(rawData))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func main() {
	endpoint := "https://payment.pay2s.vn/v1/gateway/api/create"
	merchantName := "TEST"
	accessKey := "yourAccessKey"
	secretKey := "yourSecretKey"
	orderInfo := "pay with Pay2S"
	partnerCode := "PAY2S72MLKFJFURCGPEM"
	redirectURL := "https://your-redirect-url.com"
	ipnURL := "https://your-ipn-url.com"
	amount := "50000"
	bankAccounts := "9877644888|vcb"
	orderID := fmt.Sprintf("%d", time.Now().UnixMilli())
	requestID := fmt.Sprintf("%d", time.Now().UnixMilli())
	requestType := "pay2s"

	// Tạo danh sách tài khoản ngân hàng
	var bankList []BankAccount
	for _, line := range strings.Split(bankAccounts, "\n") {
		parts := strings.Split(strings.TrimSpace(line), "|")
		bankList = append(bankList, BankAccount{
			AccountNumber: strings.TrimSpace(parts[0]),
			BankID:        strings.TrimSpace(parts[1]),
		})
	}

	// Tạo chuỗi chữ ký
	rawHash := fmt.Sprintf(
		"accessKey=%s&amount=%s&bankAccounts=Array&ipnUrl=%s&orderId=%s&orderInfo=%s&partnerCode=%s&redirectUrl=%s&requestId=%s&requestType=%s",
		accessKey, amount, ipnURL, orderID, orderInfo, partnerCode, redirectURL, requestID, requestType,
	)

	signature := createSignature(rawHash, secretKey)

	// Chuẩn bị dữ liệu
	payment := PaymentRequest{
		AccessKey:    accessKey,
		PartnerCode:  partnerCode,
		PartnerName:  merchantName,
		RequestID:    requestID,
		Amount:       amount,
		OrderID:      orderID,
		OrderInfo:    orderInfo,
		OrderType:    requestType,
		BankAccounts: bankList,
		RedirectURL:  redirectURL,
		IPNURL:       ipnURL,
		RequestType:  requestType,
		Signature:    signature,
	}

	// Gửi yêu cầu
	jsonData, _ := json.Marshal(payment)
	response, err := http.Post(endpoint, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)
	fmt.Println(string(body))
}
```
```ruby [Ruby]
require 'net/http'
require 'json'
require 'openssl'
require 'time'

def create_signature(raw_data, secret_key)
  OpenSSL::HMAC.hexdigest('SHA256', secret_key, raw_data)
end

endpoint = 'https://payment.pay2s.vn/v1/gateway/api/create'
merchant_name = 'TEST'
access_key = 'yourAccessKey'
secret_key = 'yourSecretKey'
order_info = 'pay with Pay2S'
partner_code = 'PAY2S72MLKFJFURCGPEM'
redirect_url = 'https://your-redirect-url.com'
ipn_url = 'https://your-ipn-url.com'
amount = '50000'
bank_accounts = '9877644888|vcb'
order_id = (Time.now.to_f * 1000).to_i.to_s
request_id = (Time.now.to_f * 1000).to_i.to_s
request_type = 'pay2s'

# Tạo danh sách tài khoản ngân hàng
bank_list = bank_accounts.split("\n").map do |line|
  parts = line.strip.split('|')
  {
    account_number: parts[0].strip,
    bank_id: parts[1].strip
  }
end

# Tạo chuỗi chữ ký
raw_hash = "accessKey=#{access_key}&amount=#{amount}&bankAccounts=Array&ipnUrl=#{ipn_url}&orderId=#{order_id}&orderInfo=#{order_info}&partnerCode=#{partner_code}&redirectUrl=#{redirect_url}&requestId=#{request_id}&requestType=#{request_type}"

signature = create_signature(raw_hash, secret_key)

# Chuẩn bị dữ liệu
data = {
  accessKey: access_key,
  partnerCode: partner_code,
  partnerName: merchant_name,
  requestId: request_id,
  amount: amount,
  orderId: order_id,
  orderInfo: order_info,
  orderType: request_type,
  bankAccounts: bank_list,
  redirectUrl: redirect_url,
  ipnUrl: ipn_url,
  requestType: request_type,
  signature: signature
}

# Gửi yêu cầu
uri = URI(endpoint)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
request.body = data.to_json

response = http.request(request)
puts response.body
```
:::



## Request và response đối chiếu ngày 11/10/2026

Các mẫu dưới đây giữ cấu trúc trường và kiểu dữ liệu. Khóa, chữ ký, URL phiên đã được thay bằng placeholder; danh sách chỉ giữ tối đa hai phần tử và dữ liệu ảnh/PDF/XML dài được rút gọn. Không sao chép placeholder để gọi API thật.

### Collection Link V1 · Tạo thanh toán

<div class="doc-api-actions" data-doc-api-actions><a class="try-button" data-doc-playground href="/playground/?api=collection-v1">Thử API trong Playground ↗</a><a class="try-button experience-button" data-doc-experience href="/demos/?flow=payment&api=collection-v1">Trải nghiệm thanh toán & IPN ↗</a></div>

**Đã gọi API demo/UAT.** 

`POST /v1/gateway/api/create`

Body:

```json
{
  "accessKey": "[REDACTED]",
  "partnerCode": "PAY2S7EPF0SB1ZP27W71",
  "partnerName": "Cửa hàng trải nghiệm",
  "requestId": "DEVd33eb1381791659971923e7ba11",
  "amount": 250000,
  "orderId": "DEVd33eb1381791659971923e7ba11",
  "orderInfo": "TT81791659971923e7ba11",
  "bankAccounts": [
    {
      "account_number": "P2S99999999",
      "bank_id": "ACB"
    }
  ],
  "redirectUrl": "https://developer.example.com/demos/?mode=live",
  "ipnUrl": "https://developer.example.com/sandbox/live-receiver/ipn",
  "requestType": "pay2s",
  "signature": "<SIGNATURE>"
}
```

HTTP 200. Response:

```json
{
  "partnerCode": "PAY2S7EPF0SB1ZP27W71",
  "requestId": "DEVd33eb1381791659971923e7ba11",
  "orderId": "DEVd33eb1381791659971923e7ba11",
  "orderInfo": "TT81791659971923e7ba11",
  "amount": 250000,
  "message": "Thành công",
  "lang": "vi",
  "resultCode": 0,
  "qrList": [
    {
      "bank_id": "ACB",
      "account_number": "P2S99999999",
      "account_name": "TAI KHOAN DEMO ACB",
      "qrCode": "<QRCODE_OMITTED>",
      "qrData": "00020101021238550010A000000727012500069704160111P2S999999990208QRIBFTTA52040000530370454062500005802VN62260822TT81791659971923e7ba11630497F4",
      "qrUrl": "https://sandbox-payment.pay2s.vn/quicklink/ACB/P2S99999999/TAI%20KHOAN%20DEMO%20ACB?amount=250000&memo=TT81791659971923e7ba11&is_mask=0"
    }
  ],
  "payUrl": "https://sandbox-payment.pay2s.vn/v2/gateway/pay?t=<REDACTED>",
  "storeId": null,
  "credentialScope": "owner",
  "isDemo": true,
  "environment": "demo"
}
```