VietQR.com

Hướng dẫn các bước test kết nối API VietQR Banknet - Hub

1.1. Tài liệu này dùng để làm gì

Đây là hướng dẫn thực hành, mô tả trình tự các bước cần làm để đưa dịch vụ thanh toán VietQR vào hệ thống của Đối tác.

Tài liệu này không thay thế bản đặc tả kỹ thuật. Đặc tả mô tả từng API có những trường nào; hướng dẫn này mô tả thứ tự làm, cách làm, và những chỗ dễ sai.

Khi cần tra cứu chi tiết trường dữ liệu, giới hạn độ dài hay mẫu phản hồi đầy đủ, hãy dùng tài liệu BLC-API-SPEC-PROD-VIETQR v1.0.

1.2. Những gì cần nhận trước khi bắt đầu

Hạng mục

Mô tả

Nguồn cấp

username / password

Thông tin xác thực tài khoản API. Có hai bộ riêng biệt cho Sandbox và Production.

VietQR

merchantName

Tên thương nhân trên hệ thống VietQR. Đối tác không được tự đặt giá trị này.

VietQR

secretKey

Khóa bí mật riêng cho tính năng hoàn tiền. Khác với password tài khoản API.

VietQR — kênh an toàn riêng

bankAccount / bankCode

Tài khoản thụ hưởng đã đăng ký. Mã ngân hàng hiện áp dụng: MB.

VietQR

Endpoint callback

Hai endpoint do Đối tác xây dựng, phải đăng ký với VietQR trước khi kiểm thử.

Đối tác cung cấp

Để cấu hình kết nối API với VietQR, đối tác vui lòng cung cấp và đối chiếu các thông tin dưới đây trước khi bắt đầu.

Thông tin đối tác cần cung cấp

Thông tin VietQR cung cấp

Tên merchant (tên cửa hàng/doanh nghiệp muốn hiển thị)

Username: VietQR cấp username cho đối tác

URL kết nối (địa chỉ API để kết nối)

Password: VietQR cấp mật khẩu cho đối tác

URL Path / Suffix (đường dẫn mở rộng nếu có)

Hoặc: mở tài khoản VietQR, ký tài khoản và tự khai báo trong link liên kết

Khóa Key kết nối truyền dữ liệu — Username: tự đặt theo nhu cầu của khách hàng

Khóa Key kết nối truyền dữ liệu — Password: tự đặt theo nhu cầu của khách hàng

Quy tắc bảo mật quan trọng nhất

Mật khẩu của VietQR được sinh ra từ chính tên đăng nhập theo quy tắc base64. Vì vậy, lộ username đồng nghĩa với lộ password.

Phải đối xử với cặp username và password như một bí mật duy nhất: không đưa vào mã nguồn, không lưu trong kho mã, không ghi vào nhật ký, không đưa vào tài liệu hay thư điện tử.

Liên kết tham khảo

Nhóm Zalo hỗ trợ test: https://zalo.me/g/wbclso803

Biểu mẫu thông tin ký hợp đồng

Đăng ký merchant VietQR

Tài liệu API service

1.3. Ba điều cần biết trước khi thiết kế

1.  Callback không phải kênh duy nhất. Có tình huống ngân hàng không báo giao dịch sang VietQR; khi đó VietQR không có gì để gửi cho Đối tác. Hệ thống bắt buộc phải có tác vụ đối soát chủ động, xem Bước 4.

2.  Callback sẽ đến trùng. VietQR thử lại 10 lần trong 5 phút khi gặp lỗi. Cơ chế chống trùng ở tầng cơ sở dữ liệu là bắt buộc, không phải tùy chọn.

3.  Sandbox và Production không giống nhau. Hai môi trường dùng mô hình đối soát khác nhau, và một số API chỉ tồn tại ở một môi trường. Xem Mục 9.

2. Lộ trình tích hợp

Trình tự dưới đây được thiết kế để mỗi giai đoạn đều có kết quả kiểm chứng được trước khi sang giai đoạn kế tiếp. Không nên làm song song các giai đoạn 1 đến 3.

Nội dung

Môi trường

Tiêu chí hoàn thành

1

Xác thực, lấy access\_token

Sandbox

Nhận được token; cơ chế cache và tự làm mới hoạt động đúng

2

Sinh mã QR và hiển thị

Sandbox

Ứng dụng ngân hàng quét được mã, hiển thị đúng số tiền và tài khoản thụ hưởng

3

Tiếp nhận callback

Sandbox

Nhận được dữ liệu giao dịch; gọi trùng hai lần chỉ trả dịch vụ một lần

4

Đối soát chủ động

Production

Tác vụ nền phát hiện được giao dịch đã thanh toán mà chưa nhận callback

5

Hoàn tiền

Production

Hoàn toàn phần và hoàn từng phần đều thành công, đối soát khớp

Vì sao giai đoạn 4 và 5 phải làm trên Production

API Check Transaction và API Refund không tồn tại trên Sandbox. Đây là hạn chế của dịch vụ, không phải lựa chọn thiết kế của Đối tác.

Khuyến nghị dự trù một khoản ngân sách nhỏ để chạy kiểm thử bằng giao dịch tiền thật giá trị thấp trong giai đoạn nghiệm thu, trước khi mở dịch vụ cho người dùng cuối.

2.1. Ghi chú về khối lượng công việc

Bảng dưới là nhận định của Bluecom dựa trên kinh nghiệm tích hợp cổng thanh toán nói chung, dùng để tham khảo khi lập kế hoạch. Đây không phải cam kết tiến độ.

Giai đoạn

Ghi chú

Giai đoạn 1 và 2

Khối lượng nhỏ. Chủ yếu là gọi API và dựng ảnh QR từ chuỗi qrCode.

Giai đoạn 3

Khối lượng trung bình. Phần khó nằm ở cơ chế chống trùng và xử lý bất đồng bộ, không nằm ở việc nhận request.

Giai đoạn 4

Khối lượng trung bình. Cần dùng chung luồng xử lý với callback, không viết nhánh riêng.

Giai đoạn 5

Phụ thuộc vào quy trình nghiệp vụ hoàn tiền phía Đối tác nhiều hơn là vào bản thân API.

3. Bước 1 — Xác thực

3.1. Quy tắc sinh chuỗi Basic Auth

Đây là điểm sai nhiều nhất khi bắt đầu. Mật khẩu không phải một chuỗi ngẫu nhiên do VietQR cấp phát riêng, mà chính là tên đăng nhập được mã hóa base64.

password      = base64(username)

Authorization = "Basic " + base64(username + ":" + password)

Quy tắc đã được Bluecom kiểm chứng bằng cách giải mã đối chiếu với payload của token trả về.*  |  

Ví dụ mã nguồn

// Java

String password = Base64.getEncoder()

        .encodeToString(username.getBytes(StandardCharsets.UTF\_8));

String basic = Base64.getEncoder()

        .encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF\_8));

headers.set("Authorization", "Basic " + basic);

# Python

password = base64.b64encode(username.encode()).decode()

basic    = base64.b64encode(f"{username}:{password}".encode()).decode()

headers  = {"Authorization": f"Basic {basic}"}

3.2. Quản lý vòng đời token

Token có hiệu lực 300 giây. Không gọi Get Token trước mỗi request nghiệp vụ, vì cách làm đó nhân đôi số lượng request và làm tăng độ trễ không cần thiết.

Yêu cầu triển khai

·       Cache token trong bộ nhớ tiến trình và tái sử dụng.

·       Chủ động làm mới khi token còn 30 đến 60 giây hiệu lực, thay vì đợi đến khi nhận lỗi.

·       Dùng khóa đồng bộ quanh thao tác làm mới, tránh nhiều luồng cùng gọi Get Token.

·       Khi gặp lỗi xác thực, làm mới token và thử lại đúng một lần. Thất bại tiếp thì ghi nhật ký và cảnh báo, không thử lại vô hạn.

·       Không ghi token vào nhật ký ở bất kỳ mức nào.

Lưu ý về mã lỗi

VietQR chưa cung cấp bảng mã lỗi. Trong giai đoạn kiểm thử Sandbox, hãy ghi lại nguyên văn mọi phản hồi khác HTTP 200 kèm phần thân phản hồi.

Tập hợp các bản ghi này chính là bảng mã lỗi thực nghiệm, hiện là nguồn thông tin đáng tin cậy nhất mà Đối tác có.

4. Bước 2 — Sinh mã QR

4.1. Chọn đúng loại mã QR

Quyết định này ảnh hưởng trực tiếp đến khả năng đối soát tự động và phải được chốt trước khi viết mã.

Tiêu chí

QR động (0)

QR tĩnh (1)

QR bán động (3)

Số tiền

Gắn sẵn

Người trả tự nhập

Gắn sẵn

Gắn orderId

Có, bắt buộc

Không

Không

Vòng đời

15 phút, một lần

Dài hạn, nhiều lần

Dài hạn, nhiều lần

Đối soát tự động theo đơn hàng

Không

Không

VietQR chống thanh toán lặp

Không

Không

Phù hợp với

Thương mại điện tử, đơn hàng có giá trị xác định

Quầy thu ngân, cửa hàng nhỏ

Trạm sạc, máy bán hàng tự động

Khuyến nghị của Bluecom

Nếu nghiệp vụ cần đối soát chính xác đến từng đơn hàng, QR động là lựa chọn duy nhất phù hợp.

Với QR tĩnh và QR bán động, dữ liệu callback không mang orderId. Hệ thống sẽ phải suy luận đơn hàng từ tổ hợp số tiền, thời điểm và điểm bán. Cơ chế này không đảm bảo chính xác khi có hai giao dịch cùng số tiền phát sinh gần nhau.

4.2. Bốn ràng buộc dễ vi phạm nhất

Trường

Ràng buộc

Ví dụ

amount

Số nguyên dương, đơn vị VND. Không dấu phân cách hàng nghìn, không dấu thập phân, không ký hiệu tiền tệ.

Đúng: 10000, 250000 Sai: 10.000 · 10,000 · 10000.00

content

Tối đa 23 ký tự, áp dụng cho cả ba loại QR.

Cắt chuỗi ở phía Đối tác trước khi gửi

orderId

Tối đa 13 ký tự. Phải duy nhất toàn cục trong hệ thống Đối tác.

Đây là khóa đối soát tự động quan trọng nhất

4.3. Dựng ảnh QR từ chuỗi qrCode

Trường qrCode trong phản hồi là một chuỗi dữ liệu theo chuẩn EMVCo. Đối tác tự dựng ảnh QR từ chuỗi này bằng thư viện mã QR bất kỳ.

Lưu ý khi dựng ảnh

·       Mã hóa chuỗi ở chế độ văn bản, không thêm khoảng trắng hay ký tự xuống dòng.

·       Mức sửa lỗi khuyến nghị là M hoặc Q. Mức H làm mã dày hơn, khó quét trên màn hình nhỏ.

·       Chừa vùng trắng viền quanh mã. Thiếu vùng trắng là nguyên nhân phổ biến khiến ứng dụng ngân hàng không quét được.

·       Kích thước hiển thị tối thiểu khuyến nghị là 200 x 200 điểm ảnh.

Kiểm chứng nhanh trước khi viết tiếp

Dựng ảnh QR, mở ứng dụng ngân hàng bất kỳ và quét thử. Nếu ứng dụng hiển thị đúng tài khoản thụ hưởng và đúng số tiền, bước 2 đã hoàn thành.

Không xác nhận thanh toán ở bước kiểm chứng này.

5. Bước 3 — Tiếp nhận callback

5.1. Đảo chiều vai trò

Ở các bước trước, hệ thống Đối tác là bên gọi. Trong luồng callback, VietQR là bên gọi và Đối tác là bên cung cấp dịch vụ.

Đối tác phải tự xây dựng và công bố hai endpoint: một endpoint để VietQR lấy token truy cập hệ thống Đối tác, và một endpoint để VietQR đẩy dữ liệu giao dịch.

Hạng mục cần VietQR cung cấp trước khi bắt đầu bước này

VietQR hiện chỉ cung cấp đường dẫn tham chiếu tới đặc tả của hai endpoint này, chưa cung cấp nội dung đặc tả bằng văn bản.

Bluecom không dựng payload mẫu giả định, vì một cấu trúc callback tự chế sẽ dẫn đến việc xây dựng sai endpoint và chỉ phát hiện ra khi đã tích hợp xong.

Khuyến nghị coi việc nhận được đặc tả này là điều kiện tiên quyết trước khi cam kết tiến độ. Xem Phụ lục B, mục A-01.

5.2. Sáu yêu cầu bắt buộc

Các yêu cầu dưới đây được đưa vào vì cơ chế thử lại 10 lần khiến việc bỏ qua chúng gần như chắc chắn gây sự cố vận hành.

1.  Bất biến theo lần gọi. Hệ thống chắc chắn sẽ nhận trùng callback. Dùng referenceNumber làm khóa chống trùng, lưu vào bảng có ràng buộc duy nhất ở tầng cơ sở dữ liệu. Kiểm tra trùng chỉ ở tầng ứng dụng sẽ để lọt hai callback đến đồng thời.

2.  Phản hồi nhanh, xử lý bất đồng bộ. Ghi nhận callback vào hàng đợi và trả HTTP 200 ngay, thay vì xử lý toàn bộ nghiệp vụ trong request. Trả lời chậm có thể bị coi là thất bại và kích hoạt thử lại.

3.  Đối chiếu số tiền trước khi trả dịch vụ. Luôn so khớp amount trong callback với số tiền của đơn hàng trong cơ sở dữ liệu. Không trả dịch vụ chỉ dựa trên sự tồn tại của callback.

4.  Ghi nhật ký toàn bộ payload thô. Lưu nguyên văn phần thân của mọi callback, kể cả callback bị từ chối hay xử lý lỗi. Đây là bằng chứng duy nhất khi cần đối chất với VietQR hoặc ngân hàng.

5.  Giới hạn dải địa chỉ IP nguồn. Chỉ chấp nhận request từ dải IP mà VietQR sử dụng. Đây là lớp phòng vệ bổ sung bên cạnh cơ chế token.

6.  Không tin cậy callback là kênh duy nhất. Bắt buộc xây dựng tác vụ đối soát chủ động ở Bước 4.

5.3. Mẫu xử lý callback khuyến nghị

@Transactional

public void handleCallback(CallbackPayload p) {

    // 1. Chong trung /

    //    Bat exception vi pham rang buoc duy nhat, KHONG dung SELECT truoc INSERT

    try {

        txnLogRepo.insert(p.getReferenceNumber(), rawBody);

    } catch (DuplicateKeyException e) {

        [log.info**](https://vietqr.com/huong-dan-tich-hop-vietqr#)**("Callback trung, bo qua: {}", p.getReferenceNumber());

        return;                       // van tra HTTP 200

    }

    // 2. Doi chieu don hang /

    Order order = orderRepo.findByOrderId(p.getOrderId());

    if (order == null)                     { alert("Khong tim thay don hang"); return; }

    if (order.getAmount() != p.getAmount()) { alert("Lech so tien"); return; }

    if (order.isPaid())                     { return; }   // da xu ly

    // 3. Cap nhat va tra dich vu /

    order.markPaid(p.getReferenceNumber());

    serviceQueue.enqueue(order.getId());   // xu ly bat dong bo

}

Điểm mấu chốt: dựa vào ràng buộc duy nhất của cơ sở dữ liệu để chống trùng, không dùng mẫu kiểm tra rồi mới ghi.*  |  

Vì sao không dùng mẫu kiểm tra rồi mới ghi

Nếu hai callback cho cùng một giao dịch đến đồng thời, cả hai đều có thể vượt qua bước kiểm tra trước khi bất kỳ bản ghi nào được ghi xuống. Kết quả là dịch vụ được trả hai lần.

Ràng buộc duy nhất ở tầng cơ sở dữ liệu loại bỏ hoàn toàn khoảng trống này, vì việc kiểm tra và ghi diễn ra như một thao tác nguyên tử.

5.4. Kiểm thử callback trên Sandbox

Sandbox có API Test Callback để giả lập việc người dùng quét mã và xác nhận thanh toán, không cần giao dịch thật.

Lỗi thường gặp nhất

Trường content truyền vào API Test Callback phải là giá trị lấy từ phản hồi của API sinh QR, tức là giá trị đã có tiền tố đối soát, không phải giá trị mà Đối tác đã gửi lên.

Việc cần làm trong bước này

·       Ghi lại nguyên văn payload callback nhận được vào tài liệu nội bộ. Vì VietQR chưa cung cấp đặc tả bằng văn bản, payload thực tế quan sát được chính là đặc tả đáng tin cậy nhất mà Đối tác có.

6. Bước 4 — Đối soát chủ động

6.1. Vì sao bước này bắt buộc

Cơ chế thử lại 10 lần của VietQR chỉ bù trừ cho trường hợp hệ thống Đối tác tạm thời không nhận được dữ liệu.

Nó không bù trừ cho trường hợp ngân hàng không báo giao dịch sang VietQR, vì khi đó VietQR không có gì để gửi đi.

Theo mô tả của VietQR, khi hệ thống ngân hàng nhận quá tải, ngân hàng chỉ lưu thông tin giao dịch mà không thực hiện đối soát, do đó không thông báo giao dịch sang VietQR. Đây là tình huống nằm hoàn toàn ngoài phạm vi của cơ chế thử lại.

Hệ quả nếu bỏ qua bước này: tiền đã vào tài khoản nhưng người dùng không nhận được dịch vụ, và hệ thống không tự phát hiện được.

6.2. Thiết kế tác vụ đối soát

1.  Chạy mỗi 2 đến 5 phút, quét các đơn hàng ở trạng thái chờ thanh toán có tuổi đời từ 3 phút trở lên.

2.  Với mỗi đơn hàng, gọi API Check Transaction với type = 0 và value = orderId.

3.  Nếu tìm thấy giao dịch đã thanh toán, xử lý qua đúng luồng callback thông thường: cùng một hàm xử lý, cùng cơ chế chống trùng theo referenceNumber.

4.  Dừng đối soát khi đơn hàng vượt quá thời hạn, khuyến nghị 20 phút; chuyển sang trạng thái quá hạn và ghi nhận để đối soát cuối ngày.

5.  Thiết lập cảnh báo khi tỷ lệ đơn hàng được cứu bởi tác vụ này vượt ngưỡng. Đây là tín hiệu sớm cho thấy kênh callback đang gặp vấn đề.

Nguyên tắc quan trọng nhất của bước này

Không viết hai nhánh xử lý riêng cho callback và cho đối soát chủ động. Hai nhánh sẽ phân kỳ theo thời gian và tạo ra lỗ hổng rất khó phát hiện.

Đối soát chủ động chỉ nên là một nguồn dữ liệu đầu vào khác cho cùng một hàm xử lý đã dùng cho callback.

6.3. Hạn chế cần biết trước

API Check Transaction không khả dụng trên Sandbox. Do đó toàn bộ tác vụ đối soát chủ động không thể kiểm thử đầu-cuối trước khi golive.

Khuyến nghị thiết kế tầng truy cập API có thể thay thế bằng đối tượng giả lập, để ít nhất kiểm thử được phần logic nghiệp vụ trên Sandbox.

7. Bước 5 — Hoàn tiền

7.1. Hai ràng buộc an toàn của VietQR

1.  Hoàn tiền luôn gắn với một giao dịch gốc. Không thể tạo lệnh hoàn tiền độc lập; mọi lệnh hoàn đều phải tham chiếu referenceNumber của giao dịch đã thanh toán.

2.  Tổng số tiền hoàn không vượt quá số tiền gốc. Có thể hoàn nhiều lần, nhưng tổng giá trị các lần hoàn bị giới hạn bởi số tiền của giao dịch gốc. Cơ chế này cho phép hoàn từng phần một cách an toàn.

So tien con co the hoan  =  amount  -  amountRefunded

(lay tu API Check Transaction /

7.2. Luồng hoàn tiền khuyến nghị

1.  Gọi API Check Transaction để lấy trạng thái thực tế của giao dịch gốc, đặc biệt là hai trường refundCount và amountRefunded.

2.  Tính số tiền còn có thể hoàn. Nếu số tiền cần hoàn vượt quá giá trị này, dừng lại và báo lỗi nghiệp vụ, không gọi API Refund.

3.  Sinh và lưu một mã định danh yêu cầu hoàn tiền phía Đối tác, để phân biệt yêu cầu hoàn tiền với lần gọi API. Một yêu cầu có thể phát sinh nhiều lần gọi.

4.  Gọi API Refund. Lưu lại nguyên văn cả request và response.

5.  Nếu thành công, trường message trong phản hồi chứa mã giao dịch hoàn do ngân hàng sinh ra. Lưu giá trị này để đối soát với ngân hàng.

6.  Chờ callback với transType = "D" để xác nhận trạng thái cuối cùng. Đối soát lại bằng Check Transaction.

Hai điểm dễ hiểu nhầm

Thứ nhất: trong phản hồi thành công, trường message không chứa thông điệp mô tả mà chứa mã giao dịch hoàn. Nội dung trường này khi thất bại chưa được VietQR mô tả, nên phải kiểm tra status trước rồi mới diễn giải message.

Thứ hai: phản hồi HTTP 200 của API Refund không phải bằng chứng tiền đã về tài khoản người dùng. Nó chỉ xác nhận VietQR đã tiếp nhận và chuyển lệnh sang ngân hàng.

7.3. Xử lý khi hoàn tiền thất bại

VietQR không có cơ chế thử lại tự động cho API Refund. Cơ chế thử lại 10 lần trong 5 phút áp dụng cho callback, không áp dụng cho lệnh hoàn tiền.

Yêu cầu bắt buộc

·       Không tự động thử lại lệnh hoàn tiền khi chưa xác định được nguyên nhân thất bại. Nếu lệnh hoàn thứ nhất thực tế đã thành công nhưng phản hồi bị mất, việc thử lại sẽ hoàn tiền hai lần.

·       Trước mỗi lần thử lại, gọi Check Transaction và kiểm tra refundCount cùng amountRefunded để xác định trạng thái thực tế. Đây là nguồn dữ liệu đáng tin cậy hơn phản hồi của chính lệnh hoàn tiền.

·       Đưa lệnh hoàn tiền thất bại vào hàng đợi xử lý thủ công có người phê duyệt, kèm đầy đủ nhật ký request và response.

8. Mười lỗi thường gặp

Bảng tổng hợp các lỗi mà đội tích hợp hay mắc phải, kèm cách xử lý.

#

#

Lỗi

Cách xử lý

1

Tự sinh password thay vì dùng base64(username)

Áp dụng đúng quy tắc tại Mục 3.1. Kiểm chứng bằng cách giải mã trường user trong token trả về.

2

Gọi Get Token trước mỗi request nghiệp vụ

Cache token trong bộ nhớ, làm mới khi còn 30 đến 60 giây.

3

Gửi amount có dấu phân cách, ví dụ 10.000

Chuẩn hóa về số nguyên trước khi gửi. Thêm kiểm tra ở tầng gọi API.

4

content vượt 23 ký tự, orderId vượt 13 ký tự

Cắt chuỗi ở phía Đối tác. Không dựa vào việc VietQR tự cắt.

5

Gửi userBankName có dấu tiếng Việt

Chuyển về chữ HOA không dấu trước khi gửi.

6

Gọi Test Callback với content chưa có tiền tố đối soát

Dùng đúng giá trị content lấy từ phản hồi của API sinh QR.

7

Chống trùng callback bằng mẫu kiểm tra rồi mới ghi

Dùng ràng buộc duy nhất ở tầng cơ sở dữ liệu, bắt lỗi vi phạm ràng buộc. Xem Mục 5.3.

8

Bóc tách tiền tố VQR, SQR, SMQR từ trường content để đối soát

Cách này chỉ đúng trên Sandbox. Trên Production phải đối soát theo orderId hoặc referenceNumber.

9

Đặt thời hạn đơn hàng ngắn hơn hoặc bằng 15 phút

Đặt dài hơn vòng đời mã QR, khuyến nghị 20 phút, để tránh tình huống tiền đã vào nhưng đơn đã hủy.

10

9. Chuyển từ Sandbox sang Production

9.1. Khác biệt về tập tính năng

API

Sandbox

Production

Hệ quả

Get Token

Generate QR Code

Create terminalCode

Giá trị tid khác nhau giữa hai môi trường; không cứng hóa trong cấu hình

Check Transaction

Không

Tác vụ đối soát chủ động không kiểm thử được trên Sandbox

Refund

Không

Toàn bộ luồng hoàn tiền phải kiểm thử trên Production

9.2. Khác biệt về mô hình đối soát

Đây là khác biệt quan trọng nhất và là nguyên nhân gây lỗi phổ biến nhất khi chuyển môi trường.

Hạng mục

Sandbox

Production

Mã QR trỏ tới

Số tài khoản thụ hưởng

Tài khoản ảo riêng cho từng mã QR

Cơ chế đối soát

Theo tiền tố trong nội dung chuyển khoản

Theo tài khoản ảo

Trường content

Bị VietQR chèn tiền tố VQR, SQR hoặc SMQR

Giữ nguyên giá trị gửi lên

Trường vaAccount

Rỗng

Có giá trị, 13 ký tự

Trường userBankName

Viết HOA

Viết thường có hoa đầu từ

Rà soát bắt buộc trước khi chuyển môi trường

Mọi đoạn mã phụ thuộc vào giá trị của ba trường content, vaAccount và userBankName phải được rà soát lại.

Đoạn mã bóc tách tiền tố từ trường content sẽ chạy đúng trên Sandbox nhưng sai trên Production. Ngược lại, logic đối soát theo vaAccount không thể kiểm thử được trên Sandbox vì trường này luôn rỗng.

Khuyến nghị đối soát theo orderId với QR động, hoặc theo referenceNumber, vì hai khóa này ổn định trên cả hai môi trường.

9.3. Danh mục kiểm tra khi chuyển môi trường

Hạng mục

Trạng thái

Đã thay domain sang [api.vietqr.org](https://vietqr.com/huong-dan-tich-hop-vietqr#) ở toàn bộ điểm gọi

Đã dùng bộ username và password của Production, tách biệt hoàn toàn với Sandbox

Đã nhận secretKey dùng cho hoàn tiền qua kênh an toàn

Đã rà soát logic phụ thuộc vào content, vaAccount, userBankName

Đã đăng ký endpoint callback Production với VietQR

Đã đăng ký lại terminalCode trên Production và cập nhật giá trị tid mới

Đã thiết lập danh sách cho phép theo dải IP nguồn của callback

Đã kiểm thử luồng thanh toán bằng giao dịch tiền thật giá trị nhỏ

Đã kiểm thử luồng hoàn tiền bằng giao dịch tiền thật giá trị nhỏ

10. Kiểm thử và nghiệm thu

10.1. Bộ ca kiểm thử tối thiểu

Ca kiểm thử

Kết quả kỳ vọng

MT

TC-01

Lấy token với thông tin xác thực hợp lệ

Nhận access\_token, expires\_in = 300

SB

TC-02

Lấy token với thông tin xác thực sai

Nhận lỗi. Ghi lại mã trạng thái và phần thân phản hồi

SB

TC-03

Gọi API với token đã hết hạn

Cơ chế tự làm mới token hoạt động đúng

SB

TC-04

Sinh QR động với tham số hợp lệ

Nhận qrCode, orderId trả lại đúng giá trị gửi lên

SB

TC-05

Sinh QR với amount có dấu phân cách

Bị từ chối, hoặc hệ thống Đối tác đã chặn từ trước

SB

TC-06

Sinh QR với content dài 24 ký tự

Ghi lại hành vi thực tế: lỗi hay bị cắt bớt

SB

TC-07

Dựng ảnh QR và quét bằng ứng dụng ngân hàng

Hiển thị đúng tài khoản thụ hưởng và đúng số tiền

SB

TC-08

Gọi Test Callback với content đúng

Endpoint nhận được dữ liệu. Lưu nguyên văn payload

SB

TC-09

Gọi Test Callback hai lần với cùng dữ liệu

Chỉ trả dịch vụ một lần

SB

TC-10

Endpoint callback trả lỗi ở lần gọi đầu

VietQR thử lại. Ghi lại số lần và khoảng cách thực tế

SB

TC-11

Tác vụ đối soát phát hiện giao dịch chưa nhận callback

Đơn hàng được cập nhật qua cùng luồng xử lý với callback

PR

TC-12

Quét lại mã QR động đã thanh toán

Ứng dụng ngân hàng từ chối. Ghi lại thông báo hiển thị

PR

TC-13

Quét mã QR động đã để quá 15 phút

Ứng dụng ngân hàng từ chối. Ghi lại thông báo hiển thị

PR

TC-14

Hoàn tiền toàn phần

status = SUCCESS, message chứa mã giao dịch hoàn

PR

TC-15

Hoàn tiền từng phần, chia hai lần

refundCount = 2, amountRefunded đúng tổng

PR

TC-16

Hoàn tiền vượt quá số tiền gốc

Bị từ chối. Ghi lại mã lỗi và thông báo

PR

TC-17

Nhận callback của giao dịch hoàn tiền

Nhận được transType = "D", hệ thống phân loại đúng

PR

Hạng mục bàn giao bắt buộc của giai đoạn kiểm thử

Toàn bộ payload callback thực tế quan sát được trên Sandbox phải được ghi lại nguyên văn và bàn giao như một tài liệu chính thức.

Toàn bộ phản hồi khác HTTP 200 phải được ghi lại để lập bảng mã lỗi thực nghiệm.

Vì VietQR chưa cung cấp hai nội dung này bằng văn bản, kết quả thực nghiệm chính là tài liệu tham chiếu đáng tin cậy nhất.

11. Danh mục kiểm tra trước khi golive

11.1. Hạng mục phụ thuộc VietQR

Hạng mục

Trạng thái

Đã nhận đặc tả callback đầy đủ bằng văn bản

Đã nhận bảng mã lỗi, hoặc đã lập bảng mã lỗi thực nghiệm từ Sandbox

Đã làm rõ ý nghĩa bốn tham số sign, urlLink, note, additionalData

Đã làm rõ bảng ánh xạ giá trị trường status

Đã kiểm chứng thực nghiệm cả ba công thức checkSum

Đã làm rõ cơ chế chống trùng lặp lời gọi phía VietQR

11.2. Hạng mục phía Đối tác

Hạng mục

Trạng thái

Cơ chế chống trùng theo referenceNumber có ràng buộc duy nhất ở tầng cơ sở dữ liệu

Tác vụ đối soát chủ động đã hoàn thiện và được kiểm thử

Đối soát chủ động và callback dùng chung một hàm xử lý

Thời hạn đơn hàng đã đặt dài hơn 15 phút

Endpoint callback xử lý bất đồng bộ, trả HTTP 200 nhanh

Nhật ký lưu nguyên văn payload callback, có che dấu thông tin xác thực

Thông tin bí mật lưu trong kho bí mật, không nằm trong mã nguồn

Cấu hình Sandbox và Production tách biệt hoàn toàn

Đã thiết lập giám sát và cảnh báo cho các chỉ số vận hành

11.3. Chỉ số cần giám sát sau golive

Chỉ số

Ý nghĩa

Tỷ lệ sinh QR thất bại

Phát hiện sớm sự cố ở tầng API hoặc lỗi cấu hình tham số.

Độ trễ từ thanh toán đến callback

Tăng bất thường là dấu hiệu ngân hàng hoặc VietQR đang quá tải.

Tỷ lệ đơn hàng được cứu bởi tác vụ đối soát chủ động

Chỉ số quan trọng nhất. Tăng đột biến nghĩa là kênh callback đang gặp vấn đề.

Số callback trùng lặp bị chặn

Xác nhận cơ chế chống trùng đang hoạt động. Bằng 0 liên tục có thể là dấu hiệu cơ chế chưa được kích hoạt đúng.

Tỷ lệ hoàn tiền thất bại

Trực tiếp ảnh hưởng tới trải nghiệm và uy tín với người dùng cuối.

Phụ lục A. Bảng thuật ngữ đối chiếu

Tên trường / Thuật ngữ

Tiếng Việt

QR động

qrType = 0. Mã QR gắn sẵn số tiền và mã đơn hàng, dùng một lần, vòng đời 15 phút.

QR tĩnh

qrType = 1. Mã QR cố định cho một điểm bán, người trả tự nhập số tiền.

QR bán động

qrType = 3. Mã QR gắn số tiền và thông tin điểm bán, dịch vụ; dùng lâu dài.

orderId

Mã đơn hàng do Đối tác sinh, tối đa 13 ký tự. Khóa đối soát tự động chính.

referenceNumber

Mã giao dịch do ngân hàng thụ hưởng sinh. Khóa đối soát với ngân hàng và khóa chống trùng.

vaAccount

Tài khoản ảo, 13 ký tự, gắn riêng cho từng mã QR trên Production.

terminalCode

Mã điểm bán, 10 ký tự, Đối tác tự đặt, phải đăng ký trước.

serviceCode

Mã dịch vụ, Đối tác tự đặt, dùng phân tách doanh thu theo loại dịch vụ.

transType

"C" là Credit, tiền vào. "D" là Debit, tiền ra, phát sinh khi hoàn tiền.

checkSum

Chuỗi băm MD5 kiểm tra tính toàn vẹn của request. Mỗi API có công thức riêng.

Callback / Transaction Sync

Cơ chế VietQR chủ động gọi vào hệ thống Đối tác để đẩy dữ liệu giao dịch.

Bất biến theo lần gọi

Tính chất cho phép thực hiện nhiều lần mà kết quả không đổi. Bắt buộc với xử lý callback.

Đối soát chủ động

Tác vụ nền định kỳ gọi Check Transaction để tự phát hiện giao dịch chưa nhận callback.

EMVCo MPM

Chuẩn quốc tế định dạng dữ liệu trong mã QR mà cửa hàng hiển thị cho khách quét.

Sandbox / Production

Môi trường kiểm thử và môi trường vận hành thật. Hai bộ khóa hoàn toàn tách biệt.

Phụ lục B. Hạng mục chờ VietQR xác nhận

Các hạng mục dưới đây chưa được VietQR cung cấp hoặc chưa đủ rõ để hiện thực hóa. Đội phát triển không nên viết mã dựa trên suy đoán cho những phần này.

B.1. Ưu tiên cao

Nội dung cần làm rõ

Rủi ro

A-01

Đặc tả đầy đủ bằng văn bản của hai endpoint callback: cấu trúc payload, danh sách trường, phản hồi VietQR mong đợi, tiêu chí xác định thất bại, khoảng cách giữa các lần thử lại.

Xây dựng endpoint dựa trên suy đoán, chỉ phát hiện sai khi đã tích hợp xong

A-02

Bảng mã trạng thái HTTP và mã lỗi nghiệp vụ cho toàn bộ các API.

Không phân biệt được lỗi tạm thời với lỗi vĩnh viễn

A-03

Ý nghĩa của bốn tham số sign, urlLink, note, additionalData. Đặc biệt tham số sign, nếu là chữ ký chống giả mạo request.

Có thể bỏ sót một cơ chế bảo mật quan trọng

A-04

Bảng ánh xạ đầy đủ các giá trị của trường status trong phản hồi Check Transaction.

Không phân biệt được các trạng thái thất bại

A-05

Xác nhận các công thức checkSum: thứ tự nối chuỗi, có ký tự phân tách hay không, chữ hoa hay chữ thường, kiểu dữ liệu của amount.

Mọi lệnh hoàn tiền và đăng ký điểm bán bị từ chối

A-06

Cơ chế xử lý hoàn tiền thất bại: mã lỗi, cách phân biệt lỗi tạm thời và vĩnh viễn, điều kiện an toàn để thử lại.

Rủi ro hoàn tiền hai lần

B.2. Ưu tiên trung bình

Nội dung cần làm rõ

A-08

Danh mục mã ngân hàng được hỗ trợ, ngoài MB.

A-09

Giới hạn tần suất gọi của từng API và cơ chế phản hồi khi vượt hạn mức.

A-10

Dải địa chỉ IP nguồn mà VietQR dùng để gọi callback.

A-11

Giới hạn độ dài của userBankName, terminalName, terminalAddress, serviceCode, và content của API Refund.

A-12

Ý nghĩa các trường phản hồi chưa được mô tả: existing, imgId, transactionId, subTerminalCode, type.

A-13

Hành vi hệ thống khi gửi trùng terminalCode ở API Generate QR.

A-14

Kiểu dữ liệu chuẩn của qrType và của amount ở API Refund.

A-15

Múi giờ tham chiếu của timeCreated và timePaid.

A-16

Nội dung trường message của API Refund trong trường hợp thất bại.

12. Hỗ trợ kỹ thuật

12.1. Phạm vi hỗ trợ của Bluecom

·       Giải đáp thắc mắc kỹ thuật về nội dung tài liệu này và tài liệu đặc tả.

·       Làm việc với VietQR để giải quyết các hạng mục trong Phụ lục B.

·       Rà soát thiết kế tích hợp và mã nguồn phía Đối tác trước khi golive.

·       Đồng hành trong giai đoạn nghiệm thu và chuyển môi trường.

12.2. Thông tin liên hệ

Hạng mục

Thông tin

Đơn vị

Công ty Bluecom — Khối Giải pháp Tích hợp

Đầu mối kỹ thuật

[Họ tên — chức danh]

Thư điện tử

[[email protected]](https://vietqr.com/huong-dan-tich-hop-vietqr#)

Điện thoại

+84.939603636

Ngôn ngữ hỗ trợ

Tiếng Việt, tiếng Trung, tiếng Anh

Thời gian hỗ trợ

[Khung giờ hỗ trợ] Các trường trong ngoặc vuông cần được điền trước khi bàn giao tài liệu cho Đối tác.  |  

Ghi chú cuối

Tài liệu này được biên soạn dựa trên đặc tả do VietQR cung cấp, kết hợp với phân tích kỹ thuật độc lập của Bluecom.

Các đặc tả của VietQR có thể thay đổi theo thời gian. Khuyến nghị liên hệ Bluecom nếu phát hiệ

2. Cấu Trúc Triển Khai — 5 Phần

Quá trình triển khai và kiểm thử kết nối API VietQR gồm 5 phần chính, thực hiện tuần tự:

1.     Implement Get Token API — triển khai API lấy token xác thực

2.     Execute Transaction Sync API — đồng bộ giao dịch/biến động số dư

3.     Call Get Token API — gọi thử API lấy token

4.     Generate VietQR Code API — sinh mã VietQR

5.     Test Callback — kiểm thử luồng callback

3. Hướng Dẫn Thực Hiện Từng Bước

Bước 1 — Cấu hình và kết nối API

Khách hàng thực hiện lần lượt theo đúng thứ tự sau, sau đó mới bắt đầu test kết nối:

Bước 1: Triển khai API Get Token

Bước 2: Triển khai API Transaction Sync

Bước 3: Gọi thử API Get Token

Bước 4: Triển khai API Generate VietQR Code

Bước 5: Gọi thử API Test Callback

Bước 2 — Kiểm tra dữ liệu

•      Kiểm tra lại dữ liệu đã cấu hình tại Bước 1 và Bước 2 để đảm bảo tính chính xác.

•      Nếu phát hiện lỗi, cần chỉnh sửa trước khi tiếp tục các bước tiếp theo.

Lưu ý: Sau khi hoàn tất các bước trên, khách hàng có thể tiến hành kiểm thử toàn bộ quy trình để đảm bảo hệ thống hoạt động đúng yêu cầu.

4. Hướng Dẫn Sau Khi Hoàn Tất Test (Go-live)

Sau khi test thành công, khách hàng sẽ được nghiệm thu và triển khai trên môi trường dịch vụ thực của tài khoản ngân hàng.

Liên hệ bộ phận kinh doanh (Khối Khách hàng Doanh nghiệp số) để được hỗ trợ triển khai:

Cán bộ KD

Mobile

Email

Lê Hương

092233.3636

[email protected]

Tuấn Bùi (Nguyễn)

0923 006 234

[email protected]

Tạ Quang Tuấn

0966 266 049

[email protected]

Hoàng Văn Hiển

0565 606 789

[email protected]

Thịnh Nguyễn

0936 381 333

[email protected]

Tuấn Phạm

096838.3636

[email protected]

Hiếu Hà

0939 603 636

[email protected]

5. Mô Tả Chi Tiết Tài Liệu API

5.1. API Get Token

API xác thực, dùng để lấy token truy cập trước khi gọi các API khác (Transaction Sync, Generate VietQR Code, Test Callback).

5.2. API Transaction Sync

Áp dụng để đối tác đồng bộ biến động số dư do VietQR trả về, theo 5 bước sau:

Bước 1: Cấp quyền truy cập API

•      Đối tác cần cấp quyền cho VietQR bằng cách thiết lập quyền truy cập vào API Transaction Sync.

•      Cấu hình điểm nhận dữ liệu (webhook) để VietQR có thể gửi thông tin biến động số dư.

Bước 2: Cấu hình đầu hứng (webhook)

•      Đối tác cung cấp URL endpoint để nhận dữ liệu.

•      Đảm bảo endpoint hỗ trợ nhận dữ liệu từ VietQR qua phương thức POST.

•      Kiểm tra bảo mật, xác thực request gửi đến từ VietQR.

Bước 3: VietQR gửi dữ liệu biến động số dư

Khi có giao dịch mới, VietQR gửi thông tin biến động số dư theo thời gian thực đến webhook của đối tác. Dữ liệu bao gồm:

Trường dữ liệu

Mô tả

Số tiền thay đổi

Giá trị biến động của giao dịch

Số dư mới

Số dư tài khoản sau giao dịch

Thời gian giao dịch

Thời điểm giao dịch phát sinh

Mã giao dịch

Mã định danh giao dịch do VietQR cấp

Thông tin khác

Tùy theo cấu hình đã thống nhất với VietQR

Bước 4: Xác nhận và xử lý dữ liệu từ VietQR

•      Đối tác nhận request từ VietQR và xác thực dữ liệu.

•      Lưu trữ hoặc xử lý thông tin theo nhu cầu (cập nhật hệ thống, hiển thị trên ứng dụng, v.v.).

•      Trả về response 200 OK để xác nhận đã nhận dữ liệu thành công.

Bước 5: Kiểm tra và giám sát

•      Định kỳ kiểm tra log để đảm bảo không có lỗi kết nối.

•      Nếu có lỗi (mất kết nối, dữ liệu sai, v.v.), kiểm tra lại cấu hình webhook hoặc liên hệ bộ phận hỗ trợ của VietQR.

Lưu ý: VietQR có thể yêu cầu xác thực webhook bằng token hoặc chữ ký số để đảm bảo an toàn khi truyền dữ liệu.