Tác giả: Sourav Mansingh
Trong bài viết này, tôi đề xuất ‘thiết kế một hệ thống thanh toán’ – trong đó tôi sẽ giải thích các thuật ngữ cụ thể, quy trình thực hiện và chức năng, thiết kế API và mô hình dữ liệu.
Điều này sẽ giúp bạn hiểu rõ hơn về cách hoạt động của hệ thống thanh toán. Ngoài ra, tài liệu tham khảo về các mô-đun, tài liệu API và blog kỹ thuật khác nhau mà tôi đã liên kết trong bài viết này sẽ giúp bạn hiểu sâu hơn về hệ thống thanh toán kỹ thuật số.
Thiết kế này gắn liền với việc thanh toán được thực hiện qua thẻ. Đối với phương thức thanh toán khác, thiết kế sẽ giống nhau với những thay đổi tối thiểu trong mô hình API và mô hình cơ sở dữ liệu.
Hệ thống thanh toán là gì?
Hệ thống thanh toán là một hệ thống được sử dụng để giải quyết các giao dịch tài chính thông qua việc chuyển giao tiền tệ, bao gồm các nguyên lý, công cụ, con người, quy tắc, thủ tục, tiêu chuẩn và công nghệ giúp cho việc giao dịch có thể được thực hiện thông suốt.
Để thực hiện mọi giao dịch, hệ thống thanh toán phải đáng tin cậy, có thể mở rộng và linh hoạt.
Yêu cầu chức năng của hệ thống thanh toán:
(i). Luồng thanh toán vào (Pay-in-flow).
(ii). Luồng thanh toán ra (Pay-out-flow).
Yêu cầu phi chức năng:
(i). Độ tin cậy và khả năng chịu lỗi.
(ii). Quy trình đối chiếu giữa các dịch vụ nội bộ và bên ngoài.
Thiết kế cấp cao: Luồng thanh toán vào (Pay-in-flow)
Những thuật ngữ mà chúng ta cần lưu ý khi thiết kế hệ thống thanh toán và các bên liên quan là một phần của hệ thống này.
Dịch vụ thanh toán (Payment service):
Dịch vụ thanh toán chấp nhận các sự kiện thanh toán từ người dùng và điều phối quá trình thanh toán. Nó xử lý các khoản thanh toán ‘vượt qua bước kiểm tra rủi ro này’ bằng cách sử dụng nhà cung cấp bên thứ ba. Điều này đánh giá việc tuân thủ các quy định và bằng chứng về hoạt động gian lận.
Người thực hiện thanh toán (Payment Executor):
Người thực hiện thanh toán thực hiện một lệnh thanh toán duy nhất thông qua nhà cung cấp dịch vụ thanh toán (PSP). Một sự kiện thanh toán có thể chứa nhiều lệnh thanh toán.
Các chương trình thẻ (Card Schemes):
Các chương trình thẻ là các tổ chức xử lý các hoạt động thẻ. Một số chương trình thẻ nổi tiếng là Visa, MasterCard, American Express, Rupay, …
Sổ cái (Ledger):
Sổ cái lưu giữ hồ sơ tài chính của giao dịch thanh toán. Giao dịch như ghi nợ (debited) hoặc ghi có (credited) cho người dùng luôn được theo dõi, giúp phân tích ‘sau thanh toán’.
Ví (Wallet):
‘Ví’ giữ số dư tài khoản của người bán, đồng thời có thể ghi lại tổng số tiền mà một người dùng nhất định đã thanh toán.
Quy trình làm việc: Luồng thanh toán vào (Pay-In-Flow)
1. Khi người dùng nhấp vào nút “đặt hàng”, một sự kiện thanh toán sẽ được kích hoạt và gửi đến dịch vụ thanh toán (payment service). Sau đó, dịch vụ thanh toán sẽ lưu trữ sự kiện thanh toán này vào cơ sở dữ liệu.
2. Một sự kiện thanh toán có thể chứa nhiều lệnh thanh toán. Giả sử bạn đã đặt hàng tại BlinkIt, nơi bạn đã thêm vào giỏ hàng một số loại rau, đồ làm bánh và một số loại trái cây.
Ở đây đơn đặt hàng giao dịch với những người bán khác nhau. Nếu BlinkIt chia thanh toán ‘thành nhiều lệnh thanh toán’ thì dịch vụ thanh toán sẽ ‘gọi’ (xác định) người thực hiện thanh toán cho mỗi lệnh thanh toán.
3. Người thực hiện thanh toán lưu trữ lệnh thanh toán trong cơ sở dữ liệu để sau này ‘yêu cầu’ (gọi) PSP bên ngoài cho việc xử lý thanh toán.
4. Sau khi ‘người thực hiện thanh toán’ (payment executor) xử lý khoản thanh toán thành công, dịch vụ thanh toán sẽ cập nhật ‘ví’ để ghi lại số tiền mà người bán nhận được.
5. Máy chủ ‘ví’ lưu trữ thông tin số dư cập nhật trong cơ sở dữ liệu. Sau khi được cập nhật, dịch vụ thanh toán sẽ ‘gọi’ sổ cái để cập nhật.
6. Dịch vụ ‘sổ cái’ sẽ thêm thông tin sổ cái mới vào cơ sở dữ liệu.
API (giao diện lập trình ứng dụng) cho dịch vụ thanh toán
Chúng tôi sẽ sử dụng thiết kế ‘RESTful’ API để triển khai dịch vụ thanh toán.
POST/v1/Payments
Điểm cuối này sẽ thực thi một sự kiện thanh toán có thể chứa nhiều lệnh thanh toán. Nó tương tự như một API có trong tài liệu của RazorPay.
https://razorpay.com/docs/api/ Payments/capture/.
Tham số yêu cầu được liệt kê dưới đây.
Payment_orders sẽ có các tham số được liệt kê bên dưới.
Khi người thực hiện thanh toán gửi yêu cầu thanh toán đến PSP bên thứ ba, payment_order_id được PSP sử dụng làm ID chống trùng lặp được gọi là idempotency key.
Lưu ý: “Kiểu dữ liệu của trường số lượng là ‘chuỗi’, không phải là ‘đôi’ (a double).
Lý do: Các giao thức, phần mềm và hệ thống khác nhau có thể hỗ trợ các ‘độ chính xác số’ khác nhau trong tuần tự hóa (serialization) và giải tuần tự hóa (deserialization).
Sự khác biệt này có thể gây ra ‘lỗi làm tròn’ (rounding errors) ngoài ý muốn, có thể cực kỳ lớn hoặc nhỏ tùy thuộc vào giá trị tiền tệ.
GET/v1/Payments/{:id}
Điểm cuối này trả về trạng thái thực thi của một lệnh thanh toán dựa trên payment_order_id. Nó tương tự như một API có trong tài liệu Razorpay được sử dụng trong biến đường dẫn để tìm nạp chi tiết thanh toán là ‘ID xác định duy nhất’ (unique global identifier id). Để phản hồi, chúng tôi có thể ‘tìm nạp’ (fetch) tham số bên dưới – dưới dạng JSON.
Để khám phá thêm các API điểm cuối bao gồm các trường hợp và kịch bản khác, bạn có thể xem tài liệu API này từ Razorpay.
Mô hình dữ liệu cho dịch vụ thanh toán
Chúng ta cần có hai bảng cho dịch vụ thanh toán: Payment_event và Payment_order.
Khi chọn giải pháp lưu trữ cho hệ thống thanh toán, hiệu suất thường không phải là yếu tố chính. Đó là sự ổn định của hệ thống lưu trữ, hỗ trợ các công cụ giám sát, điều tra và các quản trị viên cơ sở dữ liệu có kinh nghiệm (experienced DBAs). Thông thường, cơ sở ‘dữ liệu quan hệ truyền thống’ với giao dịch ACID được hỗ trợ qua NoSQL.
The checkout_id is the foreign key. Một lần thanh toán duy nhất (A single checkout) sẽ tạo ra một sự kiện thanh toán có thể chứa nhiều lệnh thanh toán.
Khi PSP bên thứ ba được yêu cầu ‘trừ tiền từ thẻ’ của người mua, số tiền này không chuyển trực tiếp cho người bán.
Đầu tiên nó được chuyển vào tài khoản của người bán (người bán trên sàn thương mại điện tử). Quá trình này được gọi là thanh toán bên trong (pay-in).
Sau khi sản phẩm được giao hoặc xác nhận giao hàng được phát hành – thì người bán sẽ bắt đầu nhận thanh toán (pay-out), trong đó tiền sẽ được chuyển vào tài ‘khoản của người bán’ từ ‘tài khoản của người bán’.
Luồng thanh toán bên trong (pay-in) xử lý thông tin người mua chứ không phải thông tin tài khoản ngân hàng của người bán.
The payment_order_status là loại liệt kê hay đếm (enumerated type – enum) giữ trạng thái thực hiện của lệnh thanh toán.
Trạng thái thực thi bao gồm NOT_STARTED, EXECUTING, SUCCESS, FAILED. Logic cập nhật là:
1. Trạng thái ban đầu của payment_order_status là NOT_STARTED.
2. Khi dịch vụ thanh toán gửi lệnh thanh toán đến người thực hiện thanh toán thì payment_order_status đang thực hiện (Executing).
3. Dịch vụ thanh toán cập nhật trạng thái đơn hàng thanh toán thành công hoặc thất bại tùy thuộc vào phản hồi của người thực hiện thanh toán.
Khi payment_order_status là thành công, dịch vụ thanh toán sẽ gọi dịch vụ ‘ví’ để cập nhật số dư của người bán và cập nhật wallet_updated filed to TRUE.
Sau khi hoàn tất, bước tiếp theo là payment_service ‘gọi’ sổ cái (the ledger service) để cập nhật cơ sở dữ liệu sổ cái, bằng cách cập nhật trường ledger_updated field to TRUE.
Khi tất cả các lệnh thanh toán có cùng một check_id được xử lý thành công, dịch vụ thanh toán sẽ cập nhật is_ payment_done thành TRUE trong bảng payment_event.
Công việc đã lên lịch thường chạy theo một khoảng thời gian cố định để theo dõi trạng thái của các lệnh thanh toán đang được thực hiện. Nó sẽ gửi cảnh báo khi lệnh thanh toán không hoàn thành trong ngưỡng để các kỹ sư công nghệ có thể kiểm tra.
Xem thêm: Quá trình thanh toán thẻ (tín dụng và ghi nợ) diễn ra như thế nào?
Hệ thống sổ cái kép (Double Entry Ledger)
Hệ thống sổ cái kép (A double entry ledger system) là một thực thể quan trọng còn được gọi là ‘kế toán ghi sổ’ hoặc ‘kế toán ghi sổ kép’ (double-entry accounting), trong đó nó ghi lại mọi giao dịch thanh toán vào 2 tài khoản sổ cái riêng biệt với cùng số tiền. Một tài khoản bị ghi nợ (debited) trong khi tài khoản kia được ghi có (credited) cùng số tiền.
Hệ thống sổ cái kép ‘nêu rõ rằng’ tổng của tất cả các ‘mục nhập giao dịch’ phải bằng 0.
Nó cung cấp khả năng truy xuất nguồn gốc từ đầu đến cuối và đảm bảo tính nhất quán trong suốt chu kỳ thanh toán.
Đây là một blog sẽ cung cấp cho bạn cái nhìn sâu sắc hơn về cách chúng tôi có thể triển khai ‘hệ thống sổ cái kép’.
Trang thanh toán được lưu trữ
Hầu hết các công ty không thích lưu trữ ‘chi tiết thẻ’ theo cách nội bộ, vì họ phải đối mặt với các quy định phức tạp như ‘tiêu chuẩn bảo mật dữ liệu ngành thẻ thanh toán’ ở Hoa Kỳ. Để tránh xử lý thông tin thẻ, các công ty sử dụng các trang thẻ tín dụng được lưu trữ do các PSP cung cấp.
Đối với trang web, đó là tiện ích hoặc iframe, trong khi đối với ứng dụng dành cho thiết bị di động, đó có thể là trang được tạo sẵn từ SDK thanh toán (the payment SDK).
Điểm mấu chốt ở đây là PSP cung cấp một trang thanh toán được lưu trữ – để nắm bắt trực tiếp thông tin thẻ của khách hàng thay vì dựa vào dịch vụ thanh toán.
Luồng thanh toán ra (Pay-out Flow)
Các thành phần của luồng thanh toán ra (pay-out flow) tương tự như luồng thanh toán vào (pay-in flow). Điểm khác biệt duy nhất là thay vì sử dụng PSP để chuyển tiền từ thẻ của người mua sang tài khoản ngân hàng của người bán, luồng thanh toán ra (pay-out flow)sử dụng nhà cung cấp dịch vụ thanh toán bên thứ ba để chuyển số tiền từ ‘tài khoản ngân hàng của người bán’ (merchant’s bank account) sang ‘tài khoản ngân hàng của người bán’ (seller’s bank account) – luồng thanh toán vào (pay-in).
Tôi đã thảo luận về yêu cầu chức năng ở mức rất cao. Trong phần sắp tới, tôi sẽ đi sâu vào thiết kế và thảo luận về các chủ đề:
(1) Tích hợp PSP – PSP Integration
(2) Đối chiếu và điều hòa – Reconciliation
(3) Xử lý sự chậm trễ trong xử lý thanh toán – Handling Payment Processing Delays
(4) Giao tiếp giữa các dịch vụ nội bộ – Communication among internal services
(5) Xử lý các khoản thanh toán không thành công – Handling failed payments
(6) Phân phối một lần chính xác – Exact-once delivery
7) Tính nhất quán – Consistency
8) Bảo mật – Security.
Tôi hy vọng bài viết này sẽ cung cấp một cái nhìn cơ bản về cách hoạt động của hệ thống thanh toán.
Tôi đã đạt được kiến thức này từ kinh nghiệm trong ngành và từ sách.
Có thể có cách khác tốt hơn để thiết kế hệ thống thanh toán.
Hình minh họa: Hệ thống thanh toán. Ảnh Freepik