HƯỚNG DẪN TÍCH HỢP VIETQR
Tóm tắt
Việt QR cung cấp một cách thức mới để đối soát giao dịch tự động giữa thương mại điện tử và ngân hàng. Đối tác phải xây dựng và công bố hai endpoint: một endpoint để Việt QR lấy token truy cập hệ thống đối tác, và một endpoint để đẩy dữ liệu giao dịch. Các yêu cầu của Việt QR bao gồm: - Không ghi token vào nhật ký ở bất kỳ mức nào. - 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. - Token có hiệu lực 300 giây, phải được refresh khi còn hiệu lực dưới 30 đến 60 giây. Việt QR khuyến nghị các đối tác phải: - Đảm bảo dữ liệu callback không mang orderId để tránh suy luận đơn hàng từ tổ hợp số tiền và thời điểm và điểm bán. - Giữ vùng trắng viền quanh mã QR, nếu thiếu sẽ khiến ứng dụng ngân hàng không quét được. - Sử dụng thư viện mã QR bất kỳ để dựng ảnh QR từ chuỗi qrCode.
DỊCH VỤ THANH TOÁN VietQR
VietQR 支付服务
Tài liệu song ngữ Việt — Trung, dành cho đội phát triển của Đối tác
越南语—中文双语文档,供合作伙伴开发团队使用
Thông tin tài liệu 文档信息 | Nội dung 内容 |
|---|---|
Mã tài liệu 文档编号 | BLC-IMPL-GUIDE-VIETQR |
Phiên bản 版本 | 1.0 |
Ngày phát hành 发布日期 | 10/08/2026 |
Đơn vị biên soạn 编制单位 | Công ty Bluecom — Khối Giải pháp Tích hợp Bluecom 公司 — 集成解决方案部 |
Đối tượng sử dụng 适用对象 | Đội phát triển và vận hành của Đối tác 合作伙伴的开发与运维团队 |
Nhà cung cấp dịch vụ 服务提供方 | VietQR · Ngân hàng thụ hưởng: MB Bank VietQR · 收款银行:MB Bank(越南军队银行) |
Tài liệu tham chiếu 参考文档 | BLC-API-SPEC-PROD-VIETQR v1.0 — Đặc tả kỹ thuật BLC-API-SPEC-PROD-VIETQR v1.0 — 技术规范 |
Phân loại 密级 分类 | BẢO MẬT — Lưu hành nội bộ 保密 — 内部流转 |
Bluecom — better technology, better future
Mục lục · 目录
Mục lục là trường tự động của Microsoft Word. Nếu hiển thị trống, nhấn Ctrl+A rồi F9 để cập nhật. | 目录为 Microsoft Word 自动字段。若显示为空,请按 Ctrl+A 后按 F9 更新。 |
|---|
1. Trước khi bắt đầu · 1. 开始之前
1.1. Tài liệu này dùng để làm gì · 1.1. 本文档的用途
Đâ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. | 本文档是实操指南,说明将 VietQR 支付服务接入合作伙伴系统所需的步骤顺序。 本文档不能替代技术规范文档。技术规范说明每个接口包含哪些字段;本指南说明按什么顺序做、怎么做,以及哪些地方容易出错。 如需查阅字段明细、长度限制或完整响应示例,请参阅 BLC-API-SPEC-PROD-VIETQR v1.0。 |
|---|
1.2. Những gì cần nhận trước khi bắt đầu · 1.2. 开始前需要获取的内容
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. API 账号鉴权信息。沙箱环境(Sandbox)与生产环境(Production)各有一套,互相独立。 | VietQR 经 Bluecom 转交 |
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 系统中的商户名称。合作伙伴不得自行设定该值。 | VietQR 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. 退款功能专用密钥,与 API 账号密码不同。 | VietQR — kênh an toàn riêng VietQR — 单独安全渠道 |
bankAccount / bankCode | Tài khoản thụ hưởng đã đăng ký. Mã ngân hàng hiện áp dụng: MB. 已登记的收款账户。当前适用银行代码:MB。 | VietQR 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ử. 由合作伙伴自建的两个接口,测试前须先在 VietQR 登记。 | Đối tác cung cấp 合作伙伴提供 |
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ử. | 最重要的安全规则 VietQR 的密码由用户名按 base64 规则生成。因此,泄露 username 等同于泄露 password。 必须将 username 与 password 视为同一个机密:不得写入源代码、不得提交到代码仓库、不得记入日志、不得写入文档或电子邮件。 |
|---|
1.3. Ba điều cần biết trước khi thiết kế · 1.3. 系统设计前必须了解的三件事
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. | 1. 回调不是唯一通道。存在银行未将交易通知 VietQR 的情况,此时 VietQR 没有数据可推送给合作伙伴。系统必须具备主动对账任务,详见步骤四。 2. 回调一定会重复到达。VietQR 在失败时会在 5 分钟内重试 10 次。数据库层的幂等去重机制是必须项,而非可选项。 3. 沙箱与生产环境并不一致。两个环境采用不同的对账模型,且部分接口仅存在于其中一个环境。详见第 9 章。 |
|---|
2. Lộ trình tích hợp · 2. 集成路线图
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. | 以下顺序的设计原则是:每个阶段都能得到可验证的结果后再进入下一阶段。不建议并行推进第 1 至第 3 阶段。 |
|---|
GĐ 阶段 | Nội dung 内容 | Môi trường 环境 | Tiêu chí hoàn thành 完成标准 |
|---|---|---|---|
1 | Xác thực, lấy access_token 鉴权,获取 access_token | Sandbox 沙箱 | Nhận được token; cơ chế cache và tự làm mới hoạt động đúng 成功获取token令牌;cache缓存与自动刷新机制运行正常 |
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 银行 App 可扫码,且正确显示金额与收款账户 |
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. | 为什么第 4、5 阶段必须在生产环境进行 交易查询接口与退款接口在沙箱环境中不存在。这是服务本身的限制,而非合作伙伴的设计取舍。 建议预留少量预算,在验收阶段用小额真实交易完成测试,然后再对最终用户开放服务。 |
|---|
2.1. Ghi chú về khối lượng công việc · 2.1. 关于工作量的说明
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 độ. | 下表为 Bluecom 基于支付网关集成经验给出的判断,仅供排期参考,不构成进度承诺。 |
|---|
Giai đoạn 阶段 | Ghi chú 备注 |
|---|---|
Giai đoạn 1 và 2 第 1、2 阶段 | Khối lượng nhỏ. Chủ yếu là gọi API và dựng ảnh QR từ chuỗi qrCode. 工作量较小。主要是调用接口,并根据 qrCode 字符串生成二维码图片。 |
Giai đoạn 3 第 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 第 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 第 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. 更多取决于合作伙伴自身的退款业务流程,而非接口本身。 |
Rủi ro tiến độ lớn nhất 最大进度风险 | Chờ VietQR cung cấp đặc tả callback bằng văn bản. Xem Phụ lục B, mục A-01. 等待 VietQR 提供书面回调规范。详见附录 B 第 A-01 项。 |
3. Bước 1 — Xác thực · 3. 步骤一:鉴权
3.1. Quy tắc sinh chuỗi Basic Auth · 3.1. 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. | 这是接入初期最容易出错的地方。密码并不是 VietQR 单独分配的随机字符串,而是用户名经 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ề. | 该规则已由 Bluecom 通过解码返回令牌的 payload 交叉验证。
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 · 3.2. 令牌生命周期管理
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
| 令牌有效期为 300 秒。不要在每次业务请求前都调用 Get Token,因为这种做法会使请求量翻倍,并带来不必要的延迟。 实现要求
|
|---|
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ó. | 关于错误码的提示 VietQR 尚未提供错误码对照表。在沙箱测试阶段,请原样记录所有非 HTTP 200 的响应及其响应体。 这些记录汇总起来即为实测错误码表,目前这是合作伙伴能获得的最可靠信息来源。 |
|---|
4. Bước 2 — Sinh mã QR · 4. 步骤二:生成二维码
4.1. Chọn đúng loại mã QR · 4.1. 选择正确的二维码类型
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) 动态码(0) | QR tĩnh (1) 静态码(1) | QR bán động (3) 半动态码(3) |
|---|---|---|---|
Số tiền 金额 | Gắn sẵn 已内置 | Người trả tự nhập 付款人自行输入 | Gắn sẵn 已内置 |
Gắn orderId 携带 orderId | Có, bắt buộc 有,必填 | Không 无 | Không 无 |
Vòng đời 有效期 | 15 phút, một lần 15 分钟,一次性 | 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 按订单自动对账 | Có 支持 | Không 不支持 | Không 不支持 |
VietQR chống thanh toán lặp VietQR 防重复支付 | Có 有 | 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. | Bluecom 的建议 若业务需要精确到每一笔订单的对账,动态码是唯一合适的选择。 静态码与半动态码的回调数据不携带 orderId。系统只能通过金额、时间和门店的组合来推断订单。当两笔金额相同的交易在相近时间发生时,该方式无法保证准确。 |
|---|
4.2. Bốn ràng buộc dễ vi phạm nhất · 4.2. 最容易违反的四项约束
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 正确:10000、250000 错误:10.000、10,000、10000.00 |
content | Tối đa 23 ký tự, áp dụng cho cả ba loại QR. 最多 23 个字符,三种二维码类型均适用。 | 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. 最多 13 个字符。在合作伙伴系统内必须全局唯一。 | Đây là khóa đối soát tự động quan trọng nhất 这是最关键的自动对账键 |
userBankName | Viết HOA và không dấu tiếng Việt. 全部大写,且不得带越南语声调符号。 | Đúng: NGUYEN VAN A Sai: Nguyễn Văn A 正确:NGUYEN VAN A 错误:Nguyễn Văn A |
4.3. Dựng ảnh QR từ chuỗi qrCode · 4.3. 由 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
| 响应中的 qrCode 字段是一串符合 EMVCo 标准的数据。合作伙伴使用任意二维码库自行生成图片即可。 生成图片时的注意事项
|
|---|
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. | 继续编码前的快速验证 生成二维码图片,用任意银行 App 试扫。若 App 正确显示收款账户和金额,则步骤二已完成。 在此验证环节中请勿确认支付。 |
|---|
5. Bước 3 — Tiếp nhận callback · 5. 步骤三:接收回调
5.1. Đảo chiều vai trò · 5.1. 角色反转
Ở 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. | 在前面的步骤中,合作伙伴系统是调用方。而在回调流程中,VietQR 是调用方,合作伙伴是服务提供方。 合作伙伴需自行搭建并对外提供两个接口:一个供 VietQR 获取访问合作伙伴系统的令牌,另一个供 VietQR 推送交易数据。 |
|---|
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. | 开始本步骤前需 VietQR 提供的内容 VietQR 目前仅提供了这两个接口规范的参考链接,尚未提供书面规范内容。 Bluecom 不会自行编造示例报文,因为凭空拟定的回调结构会导致接口开发方向错误,且往往要到集成完成后才会暴露。 建议将获取该规范作为承诺进度的前置条件。详见附录 B 第 A-01 项。 |
|---|
5.2. Sáu yêu cầu bắt buộc · 5.2. 六项强制要求
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. | 下列要求之所以列为强制项,是因为在 10 次重试机制下,忽略它们几乎必然引发运维事故。 |
|---|
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. | 1. 幂等处理。系统必然会收到重复回调。请以 referenceNumber 作为去重键,写入带唯一约束的数据库表。仅在应用层判重会漏掉同时到达的两次回调。 2. 快速响应,异步处理。将回调写入队列后立即返回 HTTP 200,不要在请求内完成全部业务处理。响应过慢可能被判定为失败并触发重试。 3. 发放服务前核对金额。务必将回调中的 amount 与数据库中订单金额进行比对。不得仅凭回调存在就发放服务。 4. 记录完整原始报文。原样保存每一次回调的请求体,包括被拒绝或处理失败的回调。这是日后与 VietQR 或银行对质时唯一的凭据。 5. 限制来源 IP 段。仅接受来自 VietQR 所使用 IP 段的请求。这是在令牌机制之外的附加防护层。 6. 不要把回调当作唯一通道。必须按步骤四建设主动对账任务。 |
|---|
5.3. Mẫu xử lý callback khuyến nghị · 5.3. 推荐的回调处理模式
@Transactional public void handleCallback(CallbackPayload p) { // 1. Chong trung / 幂等去重 — dua vao rang buoc UNIQUE cua CSDL // Bat exception vi pham rang buoc duy nhat, KHONG dung SELECT truoc INSERT try { txnLogRepo.insert(p.getReferenceNumber(), rawBody); } catch (DuplicateKeyException e) { log.info("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 · 5.4. 在沙箱环境测试回调
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
| 沙箱环境提供 Test Callback 接口,可模拟用户扫码并确认支付,无需真实交易。 最常见的错误 传入 Test Callback 接口的 content 字段,必须使用生成二维码接口返回的值,即已带对账前缀的值,而不是合作伙伴发送上去的原始值。 本步骤必须完成的事项
|
|---|
6. Bước 4 — Đối soát chủ động · 6. 步骤四:主动对账
6.1. Vì sao bước này bắt buộc · 6.1. 本步骤为何是必须项
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. | VietQR 的 10 次重试机制,只能覆盖合作伙伴系统暂时无法接收数据的情形。 它无法覆盖银行未将交易通知 VietQR 的情形,因为此时 VietQR 根本没有数据可推送。 根据 VietQR 的说明,当收款银行系统负载过高时,银行只会保存交易信息而不执行对账,因此不会将交易通知 VietQR。这种情况完全超出重试机制的作用范围。 若省略本步骤,后果是:款项已到账但用户未收到服务,且系统无法自行发现。 |
|---|
6.2. Thiết kế tác vụ đối soát · 6.2. 对账任务设计
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 đề. | 1. 每 2 至 5 分钟运行一次,扫描处于待支付状态且已创建满 3 分钟的订单。 2. 对每笔订单,以 type = 0、value = orderId 调用交易查询接口。 3. 若查到已支付的交易,走与回调完全相同的处理流程:同一个处理函数,同一套基于 referenceNumber 的去重机制。 4. 订单超过时限后停止对账,建议时限为 20 分钟;将其置为超时状态并记录,纳入日终对账。 5. 当本任务补救的订单占比超过阈值时触发告警。这是回调通道出现问题的早期信号。 |
|---|
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 · 6.3. 需提前了解的限制
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. | 交易查询接口在沙箱环境中不可用。因此整个主动对账任务无法在上线前完成端到端测试。 建议将 API 访问层设计为可替换为 Mock 对象,以便至少能在沙箱环境验证业务逻辑部分。 |
|---|
7. Bước 5 — Hoàn tiền · 7. 步骤五:退款
7.1. Hai ràng buộc an toàn của VietQR · 7.1. 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. | 1. 退款必须关联原始交易。不能创建独立的退款指令;每一笔退款都必须引用已支付交易的 referenceNumber。 2. 累计退款金额不得超过原交易金额。可以多次退款,但各次退款金额之和受原交易金额限制。该机制使部分退款可以安全进行。 |
|---|
So tien con co the hoan = amount - amountRefunded 可退余额 = amount - amountRefunded (lay tu API Check Transaction / 取自交易查询接口) |
|---|
7.2. Luồng hoàn tiền khuyến nghị · 7.2. 推荐的退款流程
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. | 1. 调用交易查询接口获取原始交易的实际状态,重点关注 refundCount 与 amountRefunded 两个字段。 2. 计算可退余额。若待退金额超过该值,则中止并返回业务错误,不要调用退款接口。 3. 在合作伙伴侧生成并保存一个退款申请编号,用以区分「退款申请」与「接口调用次数」。一个申请可能对应多次调用。 4. 调用退款接口。原样保存请求与响应内容。 5. 成功时,响应中的 message 字段包含银行生成的退款交易号。请保存该值用于与银行对账。 6. 等待 transType = "D" 的回调以确认最终状态,并再次通过交易查询接口核对。 |
|---|
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. | 两处容易误解的地方 其一:成功响应中的 message 字段并非描述性提示,而是退款交易号。VietQR 尚未说明失败时该字段的内容,因此必须先判断 status,再解读 message。 其二:退款接口返回 HTTP 200 并不代表款项已到达用户账户,它仅表示 VietQR 已受理并将指令转交银行。 |
|---|
7.3. Xử lý khi hoàn tiền thất bại · 7.3. 退款失败的处理
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
| VietQR 未为退款接口提供自动重试机制。5 分钟内重试 10 次的机制适用于回调,不适用于退款指令。 强制要求
|
|---|
8. Mười lỗi thường gặp · 8. 十大常见错误
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) 自行编造密码,而未使用 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ề. 按第 3.1 节规则实现。可通过解码返回令牌中的 user 字段进行验证。 |
2 | Gọi Get Token trước mỗi request nghiệp vụ 每次业务请求前都调用 Get Token | Cache token trong bộ nhớ, làm mới khi còn 30 đến 60 giây. 将令牌缓存在内存中,剩余 30 至 60 秒时刷新。 |
3 | Gửi amount có dấu phân cách, ví dụ 10.000 amount 带分隔符,例如 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. 发送前统一转为整数。在 API 调用层增加校验。 |
4 | content vượt 23 ký tự, orderId vượt 13 ký tự content 超过 23 字符、orderId 超过 13 字符 | Cắt chuỗi ở phía Đối tác. Không dựa vào việc VietQR tự cắt. 在合作伙伴侧先行截断,不要指望 VietQR 自动截断。 |
5 | Gửi userBankName có dấu tiếng Việt userBankName 带越南语声调符号 | 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 调用 Test Callback 时使用了未带对账前缀的 content | Dùng đúng giá trị content lấy từ phản hồi của API sinh QR. 使用生成二维码接口响应中返回的 content 值。 |
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. 改用数据库唯一约束并捕获冲突异常。详见第 5.3 节。 |
8 | Bóc tách tiền tố VQR, SQR, SMQR từ trường content để đối soát 通过截取 content 中的 VQR、SQR、SMQR 前缀来对账 | Cách này chỉ đúng trên Sandbox. Trên Production phải đối soát theo orderId hoặc referenceNumber. 该做法仅在沙箱环境成立。生产环境须按 orderId 或 referenceNumber 对账。 |
9 | Đặt thời hạn đơn hàng ngắn hơn hoặc bằng 15 phút 订单时限设置为小于或等于 15 分钟 | Đặ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. 应长于二维码有效期,建议 20 分钟,以避免款项已到而订单已取消的情况。 |
10 | Tự động thử lại lệnh hoàn tiền khi gặp lỗi 退款失败后自动重试 | Không thử lại tự động. Kiểm tra refundCount qua Check Transaction trước, sau đó xử lý thủ công có phê duyệt. 不得自动重试。先通过交易查询接口核对 refundCount,再走人工审批流程。 |
9. Chuyển từ Sandbox sang Production · 9. 从沙箱切换到生产环境
9.1. Khác biệt về tập tính năng · 9.1. 功能范围差异
API 接口 | Sandbox 沙箱 | Production 生产 | Hệ quả 影响 |
|---|---|---|---|
Get Token | Có 有 | Có 有 | — |
Generate QR Code | Có 有 | Có 有 | — |
Create terminalCode | Có 有 | Có 有 | Giá trị tid khác nhau giữa hai môi trường; không cứng hóa trong cấu hình 两个环境的 tid 值不同;不要在配置中写死 |
Check Transaction | Không 无 | Có 有 | Tác vụ đối soát chủ động không kiểm thử được trên Sandbox 主动对账任务无法在沙箱验证 |
Refund | Không 无 | Có 有 | Toàn bộ luồng hoàn tiền phải kiểm thử trên Production 整个退款流程必须在生产环境测试 |
Test Callback | Có 有 | Không 无 | Trên Production phải thanh toán thật mới kích hoạt được callback 生产环境只能通过真实支付触发回调 |
9.2. Khác biệt về mô hình đối soát · 9.2. 对账模型差异
Đâ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 content 字段 | Bị VietQR chèn tiền tố VQR, SQR hoặc SMQR 被 VietQR 加上 VQR、SQR 或 SMQR 前缀 | Giữ nguyên giá trị gửi lên 保持发送时的原值 |
Trường vaAccount vaAccount 字段 | Rỗng 为空 | Có giá trị, 13 ký tự 有值,13 个字符 |
Trường userBankName 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. | 切换环境前的强制检查 所有依赖 content、vaAccount、userBankName 三个字段取值的代码都必须重新审查。 截取 content 前缀的代码在沙箱环境正确,但在生产环境会出错。反之,按 vaAccount 对账的逻辑无法在沙箱验证,因为该字段始终为空。 建议动态码按 orderId 对账,或统一按 referenceNumber 对账,这两个键在两个环境下都稳定。 |
|---|
9.3. Danh mục kiểm tra khi chuyển môi trường · 9.3. 环境切换检查清单
Hạng mục 检查项 | Trạng thái 状态 |
|---|---|
Đã thay domain sang api.vietqr.org ở toàn bộ điểm gọi 所有调用点已切换到 api.vietqr.org 域名 | ☐ |
Đã dùng bộ username và password của Production, tách biệt hoàn toàn với Sandbox 已使用生产环境的 username 与 password,与沙箱完全隔离 | ☐ |
Đã nhận secretKey dùng cho hoàn tiền qua kênh an toàn 已通过安全渠道获取退款用 secretKey | ☐ |
Đã rà soát logic phụ thuộc vào content, vaAccount, userBankName 已审查依赖 content、vaAccount、userBankName 的逻辑 | ☐ |
Đã đăng ký endpoint callback Production với VietQR 已向 VietQR 登记生产环境回调接口地址 | ☐ |
Đã đăng ký lại terminalCode trên Production và cập nhật giá trị tid mới 已在生产环境重新登记 terminalCode 并更新新的 tid 值 | ☐ |
Đã thiết lập danh sách cho phép theo dải IP nguồn của callback 已按回调来源 IP 段配置白名单 | ☐ |
Đã 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ỏ 已用小额真实交易测试退款流程 | ☐ |
Đã kiểm thử chống thanh toán lặp trên Production 已在生产环境测试防重复支付 | ☐ |
10. Kiểm thử và nghiệm thu · 10. 测试与验收
10.1. Bộ ca kiểm thử tối thiểu · 10.1. 最小测试用例集
Mã 编号 | 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 返回 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 返回 qrCode,orderId 与发送值一致 | SB 沙箱 |
TC-05 | Sinh QR với amount có dấu phân cách 生成二维码时 amount 带分隔符 | 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ự 生成二维码时 content 长度为 24 字符 | 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 生成二维码图片并用银行 App 扫描 | 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 以正确的 content 调用 Test Callback | 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 用相同数据调用两次 Test Callback | 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ế VietQR 发起重试。记录实际次数与间隔 | 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ị 银行 App 拒绝。记录显示的提示信息 | PR 生产 |
TC-13 | Quét mã QR động đã để quá 15 phút 扫描已超过 15 分钟的动态码 | Ứng dụng ngân hàng từ chối. Ghi lại thông báo hiển thị 银行 App 拒绝。记录显示的提示信息 | PR 生产 |
TC-14 | Hoàn tiền toàn phần 全额退款 | status = SUCCESS, message chứa mã giao dịch hoàn status = SUCCESS,message 含退款交易号 | PR 生产 |
TC-15 | Hoàn tiền từng phần, chia hai lần 分两次部分退款 | refundCount = 2, amountRefunded đúng tổng refundCount = 2,amountRefunded 等于两次之和 | 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 收到 transType = "D",系统正确分类 | 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. | 测试阶段的强制交付物 在沙箱环境实际观测到的全部回调报文,必须原样记录并作为正式文档交付。 所有非 HTTP 200 的响应必须记录下来,用于编制实测错误码表。 由于 VietQR 尚未以书面形式提供这两项内容,实测结果就是最可靠的参考资料。 |
|---|
11. Danh mục kiểm tra trước khi golive · 11. 上线前检查清单
11.1. Hạng mục phụ thuộc VietQR · 11.1. 依赖 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 已明确 sign、urlLink、note、additionalData 四个参数的含义 | ☐ |
Đã làm rõ bảng ánh xạ giá trị trường status 已明确 status 字段的取值对照表 | ☐ |
Đã kiểm chứng thực nghiệm cả ba công thức checkSum 三个 checkSum 公式均已实测验证 | ☐ |
Đã làm rõ cơ chế chống trùng lặp lời gọi phía VietQR 已明确 VietQR 侧的调用幂等机制 | ☐ |
Đã nhận dải IP nguồn của callback 已获取回调来源 IP 段 | ☐ |
11.2. Hạng mục phía Đối tác · 11.2. 合作伙伴侧的事项
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 基于 referenceNumber 的去重已在数据库层设置唯一约束 | ☐ |
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 订单时限已设置为长于 15 分钟 | ☐ |
Endpoint callback xử lý bất đồng bộ, trả HTTP 200 nhanh 回调接口采用异步处理并快速返回 HTTP 200 | ☐ |
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 已为运维指标配置监控与告警 | ☐ |
Đã có quy trình xử lý hoàn tiền thất bại có người phê duyệt 已建立含人工审批的退款失败处理流程 | ☐ |
11.3. Chỉ số cần giám sát sau golive · 11.3. 上线后需监控的指标
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. 异常升高说明银行或 VietQR 负载过高。 |
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. 用于确认去重机制正常工作。长期为 0 可能说明该机制未真正生效。 |
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. 直接影响最终用户体验与信任度。 |
Số đơn hàng quá hạn chưa xác định trạng thái 状态未明的超时订单数 | Hàng đợi cần xử lý thủ công. Cần duy trì ở mức thấp. 需人工处理的队列,应保持在低位。 |
Phụ lục A. Bảng thuật ngữ đối chiếu · 附录 A. 术语对照表
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. | 动态二维码。qrType = 0。已内置金额与订单号,一次性使用,有效期 15 分钟。 |
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. | 静态二维码。qrType = 1。门店固定二维码,由付款人自行输入金额。 |
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. | 半动态二维码。qrType = 3。内置金额及门店、服务信息,可长期使用。 |
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. | 订单号。由合作伙伴生成,最多 13 个字符。自动对账的主键。 |
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. | 虚拟账户。13 个字符,生产环境下每个二维码独立分配。 |
terminalCode | Mã điểm bán, 10 ký tự, Đối tác tự đặt, phải đăng ký trước. | 门店编码。10 个字符,由合作伙伴自行设定,须提前登记。 |
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. | 交易方向。"C" 为贷记,即收款;"D" 为借记,即出款,退款时产生。 |
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. | 校验和。用于校验请求完整性的 MD5 摘要,各接口公式不同。 |
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. | 回调 / 交易同步。VietQR 主动调用合作伙伴系统推送交易数据的机制。 |
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. | EMVCo 商户呈现模式。商户展示、顾客扫描的二维码数据格式国际标准。 |
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 · 附录 B. 待 VietQR 确认事项
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. | 以下事项 VietQR 尚未提供,或提供的信息不足以直接实现。开发团队不应基于猜测为这些部分编写代码。 |
|---|
B.1. Ưu tiên cao · B.1. 高优先级
Mã 编号 | 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. 两个回调接口的完整书面规范:报文结构、字段清单、VietQR 期望收到的响应、失败判定标准、重试间隔。 | 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. 所有接口的 HTTP 状态码与业务错误码对照表。 | 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. sign、urlLink、note、additionalData 四个参数的含义。尤其是 sign,若其为防篡改签名则尤为重要。 | 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. 交易查询接口响应中 status 字段的完整取值对照表。 | 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. 确认各 checkSum 公式:拼接顺序、是否含分隔符、大小写形式、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 存在重复退款风险 |
A-07 | Cơ chế chống trùng lặp lời gọi: API có hỗ trợ khóa định danh yêu cầu hay không. 调用幂等机制:接口是否支持请求唯一标识。 | Lệnh hoàn tiền gửi lại sau lỗi mạng có thể hoàn hai lần 网络异常后重发退款指令可能导致重复退款 |
B.2. Ưu tiên trung bình · B.2. 中优先级
Mã 编号 | Nội dung cần làm rõ 待确认内容 |
|---|---|
A-08 | Danh mục mã ngân hàng được hỗ trợ, ngoài MB. 除 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. VietQR 发起回调所使用的来源 IP 段。 |
A-11 | Giới hạn độ dài của userBankName, terminalName, terminalAddress, serviceCode, và content của API Refund. userBankName、terminalName、terminalAddress、serviceCode 以及退款接口 content 的长度限制。 |
A-12 | Ý nghĩa các trường phản hồi chưa được mô tả: existing, imgId, transactionId, subTerminalCode, type. 未说明的响应字段含义:existing、imgId、transactionId、subTerminalCode、type。 |
A-13 | Hành vi hệ thống khi gửi trùng terminalCode ở API Generate QR. 生成二维码接口收到重复 terminalCode 时的系统行为。 |
A-14 | Kiểu dữ liệu chuẩn của qrType và của amount ở API Refund. qrType 以及退款接口 amount 的标准数据类型。 |
A-15 | Múi giờ tham chiếu của timeCreated và timePaid. timeCreated 与 timePaid 的参照时区。 |
A-16 | Nội dung trường message của API Refund trong trường hợp thất bại. 退款接口失败时 message 字段的内容。 |
A-17 | Khả năng cung cấp đặc tả OpenAPI cho toàn bộ các API. 能否为全部接口提供 OpenAPI 规范文件。 |
12. Hỗ trợ kỹ thuật · 12. 技术支持
12.1. Phạm vi hỗ trợ của Bluecom · 12.1. Bluecom 的支持范围
|
|
|---|
12.2. Thông tin liên hệ · 12.2. 联系方式
Hạng mục 项目 | Thông tin 信息 |
|---|---|
Đơn vị 单位 | Công ty Bluecom — Khối Giải pháp Tích hợp Bluecom 公司 — 集成解决方案部 |
Đầu mối kỹ thuật 技术对接人 | [Họ tên — chức danh] [姓名 — 职务] |
Thư điện tử 电子邮箱 | [邮箱地址] |
Đ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ện khác biệt so với nội dung tài liệu này. | 结语 本文档依据 VietQR 提供的规范,并结合 Bluecom 的独立技术分析编制而成。 VietQR 的规范可能随时间调整。若发现与本文档内容存在差异,建议及时联系 Bluecom。 |
|---|
Bluecom — better technology, better future