Liên kết tài khoản ngân hàng qua API Pay2S: OpenAPI, RPA và OTP

Minh họa liên kết tài khoản ngân hàng qua API Pay2S

Liên kết tài khoản ngân hàng là nghiệp vụ trung tâm của BankHub. API thanh toán ngân hàng Pay2S cho phép backend đối tác thêm tài khoản, xử lý OTP khi cần, xem danh sách, bật tắt trạng thái và xóa liên kết. Sau khi tài khoản hoạt động, ID bản ghi có thể được gắn với webhook để nhận giao dịch tiền vào hoặc tiền ra.

Tài liệu Pay2S phân biệt nhiều kiểu kết nối như OpenAPI và Internet Banking qua RPA, đồng thời có mẫu khác nhau cho cá nhân, doanh nghiệp hoặc hộ kinh doanh. Vì schema và bước OTP phụ thuộc ngân hàng, bài viết trên hoadontudong.com.vn tập trung vào quy trình kiểm tra an toàn thay vì coi một request mẫu là cam kết cho mọi ngân hàng.

Chuẩn bị token và dữ liệu đầu vào

Trước khi gọi /v1/banks, backend phải lấy Bearer Token theo luồng xác thực Partner API. Header chung gồm Authorization: Bearer và Content-Type application/json cho request có body. Số tài khoản, số điện thoại, CCCD, mã số thuế và OTP phải được giữ dạng chuỗi để bảo toàn số 0 ở đầu. Không đưa mật khẩu Internet Banking hoặc OTP qua frontend của đối tác nếu có thể dùng Hosted Link.

Dữ liệu thêm tài khoản thường có type, bankShortName, accountNumber và các trường bổ sung theo ngân hàng. OpenAPI có thể cần accName, accMobile, accEmail, cccd hoặc merchantId. RPA cá nhân và doanh nghiệp có username, password, còn ACB doanh nghiệp có thể dùng username ACB OneBiz. Đây là các mẫu tài liệu; validation thật cần đối chiếu với backend và đúng loại tài khoản.

OpenAPI và RPA khác nhau thế nào

Minh họa so sánh OpenAPI và RPA khi liên kết tài khoản ngân hàng
OpenAPI và RPA trong liên kết ngân hàng

OpenAPI là hướng kết nối mà Pay2S trao đổi với dịch vụ ngân hàng theo hồ sơ tích hợp. Tài liệu minh họa ACB, MBBank và BIDV với các trường nhận diện chủ tài khoản, số điện thoại, CCCD, mã số thuế hoặc merchantId. BIDV có mô tả tài khoản ảo và yêu cầu giữ merchantId khi xác nhận. Khi dùng tài khoản ảo, hệ thống phải lấy giá trị Pay2S hoặc ngân hàng trả về, không tự suy diễn.

RPA dùng thông tin đăng nhập Internet Banking cho một số ngân hàng và có thể có OTP. Mật khẩu phải được xử lý trong vùng bảo mật, hạn chế lưu và không ghi vào log. Không giả định mọi RPA đều có cùng màn hình, thời gian chờ hoặc bước OTP. Nếu doanh nghiệp không muốn thu thập credential ngân hàng, Hosted Link là hướng thay thế phù hợp hơn vì khách nhập thông tin trên form do Pay2S cung cấp.

Xử lý OTP và xác nhận tài khoản

Minh họa OTP và xác nhận tài khoản ngân hàng an toàn
OTP và xác nhận tài khoản

Sau request thêm tài khoản, nếu phản hồi báo OTP bằng giá trị OTP = 1, backend tiếp tục gọi /v1/banks/confirm-otp với cùng type, bankShortName và accountNumber. Với BIDV cần giữ merchantId; với RPA cá nhân có thể phải giữ username và password theo mẫu. OTP phải là chuỗi và không được dùng lại cho một yêu cầu khác. Thời hạn OTP, số lần thử và cách gửi lại cần xác nhận theo từng ngân hàng.

Không dùng riêng việc request trả status true hoặc thiếu trường OTP để kết luận tài khoản đã hoạt động. Sau xác nhận, gọi GET /v1/banks và đọc trạng thái bản ghi. Nếu vẫn có lỗi hoặc yêu cầu OTP tiếp tục xuất hiện, giữ trạng thái chờ xử lý. Việc đánh dấu tài khoản hoạt động quá sớm có thể khiến webhook được tạo cho một liên kết chưa sẵn sàng và làm sai quy trình thanh toán.

Đọc danh sách và phân biệt ID

GET /v1/banks trả danh sách tài khoản đã liên kết. Trường id là ID bản ghi trên Pay2S, dùng cho bật tắt, xóa và gắn webhook. accountNumber là số tài khoản hoặc giá trị do môi trường trả về; không dùng accountNumber thay cho id. Các trường như bankName, shortBankName, status, statusText, vaNumber hoặc customer_reference có thể hỗ trợ hiển thị và định tuyến nhưng cần xử lý theo schema thực tế.

Sau khi có id, backend có thể gọi PATCH /v1/banks/{id}/status để bật hoặc tắt. Phản hồi có newStatus là trạng thái sau cập nhật; nên đọc lại danh sách để xác nhận. Khi xóa, DELETE có thể yêu cầu OTP qua phản hồi OTP = 1; lúc đó gọi endpoint delete-confirm với cùng id. Không coi response đầu tiên là xóa hoàn tất nếu còn bước xác nhận.

Gắn tài khoản vào webhook giao dịch

Khi tài khoản đã hoạt động, POST /v1/webhooks dùng user_bank_id để gắn URL nhận giao dịch. Tên trường này nhắc lại rằng phải truyền ID bản ghi từ danh sách ngân hàng, không truyền số tài khoản. type có thể là IN, OUT hoặc ALL. Nếu chỉ xử lý tiền vào, chọn IN để giảm dữ liệu không cần thiết; nếu hệ thống cần theo dõi chi trả, chọn OUT hoặc ALL theo nghiệp vụ.

Mỗi webhook có token riêng. Receiver cần xác thực Authorization Bearer với token của webhook, lưu payload, chống trùng theo id hoặc checksum và trả response đúng quy ước. Nếu URL lỗi, lịch sử webhook cho phép kiểm tra status_code và gửi lại. Chi tiết transaction payload, paymentCode và extraData nằm trong bài webhook giao dịch ngân hàng Pay2S.

Kiểm thử và các điểm chưa nên tự suy luận

Một bộ test tối thiểu nên gồm thêm tài khoản hợp lệ, tài khoản cần OTP, OTP sai, danh sách sau xác nhận, bật tắt, xóa cần OTP và request lặp khi chưa biết kết quả. Mỗi test lưu request ID, thời điểm, ngân hàng, loại tài khoản, HTTP status và thông báo đã che dữ liệu nhạy cảm. Kiểm thử UAT không thể thay cho Production vì URL, dữ liệu mô phỏng và quyền có thể khác.

Trước khi triển khai từng ngân hàng, cần chốt schema response, thời hạn OTP, số lần thử, mặc định bank_type và cách xử lý request lặp với bên cung cấp API. Adapter theo bankShortName nên chỉ nhận các trường đã xác nhận cho loại tài khoản đó; một mẫu request chưa đủ để suy ra toàn bộ validation. Phần xác thực và quản lý token giúp kiểm tra lỗi quyền trước khi tìm lỗi ở dữ liệu ngân hàng.

Góc nhìn triển khai thực tế

Mô hình dữ liệu cho liên kết ngân hàng nên lưu tách thông tin hiển thị và định danh kỹ thuật. Tên ngân hàng, tên chủ tài khoản và số tài khoản đã che có thể phục vụ giao diện; còn bank record ID, bankShortName, user_bank_id, trạng thái và thời điểm đồng bộ phục vụ API. Không dùng số tài khoản làm khóa duy nhất nếu tài khoản có thể được liên kết lại hoặc có nhiều mapping. Khi người dùng thêm tài khoản lần thứ hai, hệ thống cần phát hiện bản ghi đang chờ, đã hoạt động, bị vô hiệu hóa hay đã xóa để tránh tạo các liên kết khó đối soát.

OTP làm cho luồng liên kết có trạng thái trung gian và thời hạn, vì vậy giao diện phải nói rõ người dùng đang chờ xác nhận chứ chưa hoàn tất. Backend không nên lưu OTP lâu hơn cần thiết, không log mã OTP và không cho một nút bấm gửi lại tạo nhiều phiên song song. Nếu người dùng thoát giữa chừng, hãy cho phép tiếp tục hoặc hủy theo trạng thái thực tế thay vì tự đoán đã thành công. Sau khi xác nhận, gọi lại danh sách hoặc endpoint trạng thái để đồng bộ; đừng chỉ dựa vào thông báo từ trình duyệt.

Adapter giúp cô lập khác biệt giữa OpenAPI và RPA. Sau khi xác định bankShortName, backend chọn bộ validation và payload tương ứng rồi chuyển kết quả về trạng thái nội bộ như pending, active, failed hoặc needs_action. Các tên trạng thái này là gợi ý thiết kế của ứng dụng, không phải enum bắt buộc của Pay2S. Khi schema thay đổi, hãy cập nhật adapter cùng bộ test của ngân hàng liên quan trước khi mở lại tính năng.

Kiểm soát chất lượng và vận hành

Khi một phiên liên kết bị bỏ dở, màn hình hỗ trợ cần trả lời được nó đang chờ ai và chờ bước nào. Lưu dấu mốc bắt đầu, lần xác nhận gần nhất, trạng thái đọc lại từ Pay2S và lỗi đã che dữ liệu. Một lượt bấm xác nhận bị gửi hai lần không được sinh hai mapping nội bộ. Nếu ứng dụng không biết request trước đã hoàn tất hay chưa, đọc trạng thái trước khi cho phép khởi tạo lại; lịch sử giao dịch vẫn cần giữ khi liên kết bị tắt hoặc xóa.

Màn hình hỗ trợ có thể hiển thị ngân hàng, tên gợi nhớ, vài chữ số cuối và trạng thái đồng bộ. Nhân viên không cần nhìn Secret Key hay OTP để tìm một phiên bị kẹt. Nhãn của user_bank_id và account.id cần tách khỏi nhãn số tài khoản để tránh copy nhầm. Với khách có nhiều tài khoản cùng ngân hàng, thao tác bật tắt phải yêu cầu chọn đúng bản ghi; sau đó hiển thị trạng thái đã đọc lại, thay vì chỉ hiện thông báo request được gửi.

Lập ma trận kiểm thử theo bankShortName và phương thức thực sự được cấp quyền. Với RPA, kiểm tra phiên đăng nhập hết hạn, timeout và lỗi bước xác minh; với OpenAPI, kiểm tra lỗi mạng và response thiếu trường. Dùng dữ liệu được phép thử, không lấy tài khoản của khách chạy tự động. Ghi rõ khi nào phải khóa nút tiếp tục, khi nào cho nhập lại OTP và khi nào chuyển hỗ trợ. Nhờ vậy người vận hành có hành động cụ thể khi kết nối chưa sẵn sàng.

Quy trình triển khai API thanh toán ngân hàng Pay2S

  1. Lấy Bearer Token đúng môi trường.
  2. Xác định bankShortName, loại tài khoản và kiểu kết nối.
  3. Gửi request thêm tài khoản với trường dữ liệu phù hợp.
  4. Nếu có OTP, xác nhận bằng đúng bộ thông tin của request.
  5. Gọi GET /v1/banks để đọc id và trạng thái thực tế.
  6. Dùng id làm user_bank_id khi tạo webhook giao dịch.
  7. Đọc lại trạng thái sau bật tắt hoặc xóa.
  8. Lưu log an toàn và xử lý các response chưa rõ bằng hàng chờ.

Câu hỏi thường gặp

user_bank_id là gì?

Đó là ID bản ghi tài khoản ngân hàng trên Pay2S, lấy từ trường id trong danh sách /v1/banks. Không thay bằng số tài khoản.

Có phải ngân hàng nào cũng cần OTP không?

Không chắc. Bước xác minh phụ thuộc loại ngân hàng và phương thức kết nối; không nên giả định cùng một luồng cho mọi ngân hàng.

Có thể xóa ngay khi DELETE trả status true không?

Nếu phản hồi còn OTP = 1 thì chưa xóa hoàn tất. Phải gọi endpoint xác nhận xóa với đúng ID.

RPA có nên lưu mật khẩu ngân hàng không?

Nếu dùng RPA, credential phải được bảo vệ ở backend và không ghi log. Có thể cân nhắc Hosted Link để khách nhập trên form Pay2S.

Có thể tự ghép số tài khoản ảo không?

Không. Khi có vaNumber, dùng giá trị API trả về và giữ nguyên kiểu chuỗi.

Đọc tiếp trong cụm BankHub Pay2S

Leave your comment