# 🎯 Khởi tạo OneQR - Tạo QR động

## 📱 Tổng quan

Để tạo một mã QR động cho giao dịch, bạn gọi API **Create QR Code** của OneQR. Mỗi lần gọi sẽ sinh ra **1 QR mới** với các thông tin giao dịch cụ thể.

---

## 🔌 Endpoint

```
POST http://api.pay2s.vn/api/{bank_code}/v1/qr/create
```

| Tham số | Ví dụ | Mô tả |
|--------|-------|-------|
| `{bank_code}` | `vcb` | Mã ngân hàng (vcb = Vietcombank, acb = ACB Bank, ...) |

---

## 📤 Request

### Headers

```json
{
  "Content-Type": "application/json",
  "Authorization": "Bearer <token>"
}
```

> **Lưu ý**: `<token>` là Bearer token được cấp từ Pay2S

### Body Parameters (JSON)

| Tham số | Loại | Bắt buộc | Mô tả |
|--------|------|---------|-------|
| `orderId` | String | ✓ | ID đơn hàng trong hệ thống của bạn |
| `amount` | Number | ✓ | Số tiền (VND) - ví dụ: 18000, 500000 |
| `merchantName` | String | ✓ | Tên cửa hàng/thương nhân |
| `merchantId` | String | ✓ | Mã thương nhân do ngân hàng cấp |
| `terminalId` | String | ✓ | ID thiết bị/terminal |
| `description` | String | ✓ | Nội dung thanh toán |
| `template` | String | - | Kiểu template hiển thị (ví dụ: `frame`) |
| `maskAccount` | Boolean | - | Ẩn số tài khoản (default: false) |
| `frameId` | Number | - | ID khung hình để hiển thị QR |

### ✅ Ví dụ Request (cURL)

```bash
curl --location 'http://api.pay2s.vn/api/vcb/v1/qr/create' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_BEARER_TOKEN' \
  --data '{
    "orderId": "123456",
    "amount": 10000,
    "merchantName": "CONG TY CO PHAN FUTE",
    "merchantId": "091000000900000",
    "terminalId": "60000000",
    "description": "THANH TOAN DON HANG",
    "template": "frame",
    "maskAccount": true,
    "frameId": 1
  }'
```

---

## 📥 Response

### ✅ Thành công (200 OK)

```json
{
  "code": "00",
  "desc": "Succeed",
  "data": {
    "qrDataURL": "<QRDATAURL_OMITTED>",
    "qrImageUrl": "<QRIMAGEURL_OMITTED>",
    "template": "frame",
    "decodedQrCode": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "deeplink": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "signature": "<SIGNATURE>",
    "timeStamp": "1791659974931",
    "orderId": "DEMO17916599748852455",
    "amount": 100000,
    "status": "processing",
    "traceNumber": "DEMOQR50269d422b61",
    "qrData": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "transactionId": "da58fde344a1e0c9280207e1143c6f40",
    "requestID": "DEMO-6e40f8301889"
  }
}
```

| Trường | Mô tả |
|--------|-------|
| `code` | Mã lỗi: `00` = Thành công |
| `desc` | Mô tả: `Succeed` = Thành công |
| `qrDataURL` | Chuỗi QR mã (EMV-QR format) - dùng để sinh hình ảnh QR |
| `traceNumber` | Mã định danh duy nhất của QR được tạo ra |
| `transactionId` | Mã kiểm tra trạng thái QR |


---

## 💻 Code mẫu - Tạo QR cho từng đơn hàng

::: code-group

```php [PHP]
<?php
$bearerToken = "YOUR_BEARER_TOKEN";
$url = "http://api.pay2s.vn/api/vcb/v1/qr/create";

$data = [
    'orderId' => "123456",
    'amount' => 10000,
    'merchantName' => "CONG TY CO PHAN FUTE",
    'merchantId' => "091000000900000",
    'terminalId' => "60000000",
    'description' => "THANH TOAN DON HANG",
    'template' => "frame",
    'maskAccount' => true,
    'frameId' => 1
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer " . $bearerToken,
    "Content-Type: application/json"
]);

$response = curl_exec($ch);
$result = json_decode($response, true);

if ($result['code'] === '00') {
    $qrData = $result['data'];
    echo "QR Code: " . $qrData;
} else {
    echo "Error: " . $result['desc'];
}

curl_close($ch);
?>
```

```javascript [Node.js]
const axios = require('axios');

const bearerToken = "YOUR_BEARER_TOKEN";

const payload = {
  orderId: "123456",
  amount: 10000,
  merchantName: "CONG TY CO PHAN FUTE",
  merchantId: "091000000900000",
  terminalId: "60000000",
  description: "THANH TOAN DON HANG",
  template: "frame",
  maskAccount: true,
  frameId: 1
};

axios.post("http://api.pay2s.vn/api/vcb/v1/qr/create", payload, {
  headers: {
    "Authorization": `Bearer ${bearerToken}`,
    "Content-Type": "application/json"
  }
})
  .then(response => {
    if (response.data.code === '00') {
      console.log("QR Code:", response.data.data);
    } else {
      console.error("Error:", response.data.desc);
    }
  })
  .catch(err => console.error(err));
```

```python [Python]
import requests
import json

bearer_token = "YOUR_BEARER_TOKEN"

payload = {
    'orderId': "123456",
    'amount': 10000,
    'merchantName': "CONG TY CO PHAN FUTE",
    'merchantId': "091000000900000",
    'terminalId': "60000000",
    'description': "THANH TOAN DON HANG",
    'template': "frame",
    'maskAccount': True,
    'frameId': 1
}

headers = {
    "Authorization": f"Bearer {bearer_token}",
    "Content-Type": "application/json"
}

response = requests.post("http://api.pay2s.vn/api/vcb/v1/qr/create", 
                         data=json.dumps(payload), 
                         headers=headers)
result = response.json()

if result['code'] == '00':
    print("QR Code:", result['data'])
else:
    print("Error:", result['desc'])
```

:::

---

## ⚡ Best Practices

1. **Validate input**: Kiểm tra `amount > 0` trước khi request
2. **Error handling**: Kiểm tra `code` trước xử lý `data`
3. **Lưu QR data**: Lưu chuỗi QR vào database để regenerate ảnh nếu cần
4. **Timeout QR**: Đặt QR có hiệu lực 15-30 phút
5. **MaskAccount**: Sử dụng `maskAccount: true` để bảo mật thông tin
6. **Template**: Chọn `template: "frame"` để hiển thị với UI frame
7. **TerminalId**: Đảm bảo terminalId hợp lệ từ ngân hàng
8. **Retry logic**: Nếu request fail, retry sau 2-3 giây
9. **Database record**: Lưu `orderId`, `amount`, `qr_status` để tracking
10. **Rate limit**: Giới hạn số lượng request tạo QR mỗi phút

---

## 📌 Luồng tạo QR

```
1. Khách order → 2. Hệ thống tạo QR → 3. Hiển thị ảnh QR + frame → 
4. Khách scan QR → 5. Chọn ngân hàng → 6. Xác nhận → 
7. Thanh toán → 8. Webhook notify → 9. Cập nhật status = paid
```

---

> **Tiếp theo**: Xem [Webhook](/webhook/tai-lieu-ky-thuat.html) để nhận thông báo thanh toán tự động


## 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.

### OneQR · Tạo QR động

<div class="doc-api-actions" data-doc-api-actions><a class="try-button" data-doc-playground href="/playground/?api=oneqr-create">Thử API trong Playground ↗</a><a class="try-button experience-button" data-doc-experience hidden>Trải nghiệm ↗</a></div>

**Mô phỏng; chưa xác minh với API nhà cung cấp.** Giữ mô phỏng theo cấu hình demo. Chưa có API OneQR thật để xác minh lại hợp đồng nhà cung cấp.

`POST /api/{bank_code}/v1/qr/create`

Body:

```json
{
  "orderId": "DEMO17916599748852455",
  "amount": 100000,
  "merchantName": "CUA HANG DEMO",
  "merchantId": "DEMO_MERCHANT",
  "terminalId": "DEMO_TERMINAL",
  "description": "THANHTOANDEMO",
  "template": "frame",
  "maskAccount": false,
  "frameId": 1
}
```

HTTP 200. Response:

```json
{
  "code": "00",
  "desc": "Succeed",
  "data": {
    "qrDataURL": "<QRDATAURL_OMITTED>",
    "qrImageUrl": "<QRIMAGEURL_OMITTED>",
    "template": "frame",
    "decodedQrCode": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "deeplink": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "signature": "<SIGNATURE>",
    "timeStamp": "1791659974931",
    "orderId": "DEMO17916599748852455",
    "amount": 100000,
    "status": "processing",
    "traceNumber": "DEMOQR50269d422b61",
    "qrData": "https://developer.example.com/payment/?qr=da58fde344a1e0c9280207e1143c6f40",
    "transactionId": "da58fde344a1e0c9280207e1143c6f40",
    "requestID": "DEMO-6e40f8301889"
  }
}
```
