Thanh toán tập trung (MiniApp)
Tài liệu này mô tả luồng thanh toán tập trung cho MiniApp – một cải tiến so với luồng thanh toán MiniApp chuẩn nhằm tăng trải nghiệm người dùng và đơn giản hóa phần tích hợp promotion/VPoint ở phía MiniApp, trong đó:
- MiniApp vẫn tích hợp qua JS API của V-App SDK (không gọi trực tiếp Payment Hub).
- SDK mở một màn hình thanh toán tập trung nơi user có thể:
- Apply/tiêu VPoint.
- Apply voucher/khuyến mãi.
- Chọn và thực hiện thanh toán online (thẻ, ví, v.v.).
- MiniApp Backend vẫn là nơi tạo và quản lý đơn hàng, nhận IPN từ Payment Service và cập nhật trạng thái đơn.
Luồng này là một cải tiến của luồng thanh toán MiniApp chuẩn trong Tích hợp thanh toán, nhưng centralize việc xử lý promotion/VPoint/thanh toán về phía SDK để mang lại trải nghiệm thống nhất và giảm phức tạp cho MiniApp.
Luồng thanh toán tập trung được thiết kế theo mô hình Centralized Payment Domain with Embedded Benefit Engine: miền thanh toán tập trung (Payment Session, gọi provider, IPN) và (Benefit Engine) — tính toán/áp dụng VPoint, voucher, khuyến mãi. MiniApp chỉ cần truyền order + amount gốc; việc áp dụng benefit và quyết định số tiền cuối thuộc Payment/SDK, đảm bảo logic thống nhất và giảm trùng lặp giữa các PnL.
Yêu cầu tích hợp & quy trình onboard
Quy trình onboard MiniApp, cấp paymentApiKey / secretKey, cấu hình webhook và DevCenter cho luồng thanh toán tập trung này HOÀN TOÀN GIỐNG với tài liệu Tích hợp thanh toán:
- Không có bước onboard riêng hoặc thêm tham số đặc biệt cho luồng tập trung.
- Các thông tin:
- Merchant, Terminal.
paymentApiKey,secretKey.- Webhook/IPN endpoint.
- Cấu hình DevCenter.
được dùng chung cho cả luồng MiniApp hiện tại và luồng thanh toán tập trung.
- Header
X-MiniApp-Id: Giống luồng thanh toán chuẩn, khi MiniApp Backend gọi các API Payment Hub (bao gồm API liên quan payment session) có thể gửi headerX-MiniApp-Idvới giá trị miniAppId (MiniApp ID trong SuperApp). Hiện tại optional (khuyến nghị gửi khi tích hợp mới).
Khái niệm Payment Session
Trong luồng thanh toán tập trung, hệ thống tạo và quản lý một thực thể trung tâm là Payment Session:
paymentSessionId: ID duy nhất đại diện cho phiên thanh toán.- Liên kết với order:
orderId,referenceId. - Trạng thái:
PENDING: Session vừa tạo, user đang thao tác (chọn phương thức, tiêu VPoint, chọn voucher…).PROCESSING: Đang thực hiện thanh toán online với provider.COMPLETED: Thanh toán thành công, số tiền cuối cùng được xác nhận.CANCELLED: User huỷ hoặc session bị huỷ (timeout/hủy thao tác).EXPIRED: Session hết hạn do user không thao tác trong thời gian cho phép.
- Dữ liệu trong session (minh hoạ):
- Số VPoint khả dụng & số VPoint đã tiêu trong session.
- Danh sách voucher có thể áp dụng & voucher user đã chọn.
- Phương thức thanh toán online được chọn (card/wallet/QR…).
- Số tiền gốc, số tiền giảm giá, số tiền phải trả cuối cùng.
SDK sẽ nhận paymentSessionId (hoặc tạo ngầm) và mọi thao tác:
- Tiêu/bỏ tiêu VPoint.
- Chọn/bỏ voucher.
- Chọn phương thức thanh toán online.
đều tương ứng với việc update Payment Session trên backend Payment. Khi user confirm thanh toán:
- Payment tính toán số tiền cuối cùng dựa trên session (VPoint, voucher, phương thức thanh toán).
- Payment thực hiện thanh toán với provider.
- Sau khi có kết quả cuối cùng, Payment:
- Cập nhật trạng thái
paymentSessionsangCOMPLETED/FAILED/CANCELLED. - Gửi IPN về MiniApp Backend với số tiền cuối cùng và thông tin liên quan.
- Cập nhật trạng thái
Luồng tổng quan
- User thao tác trong MiniApp để đặt hàng.
- MiniApp Backend tạo order như hiện tại (bao gồm amount gốc, thông tin khách hàng, items…).
- MiniApp gọi JS API của SDK để khởi tạo Payment Session và mở màn hình thanh toán tập trung (init payment session):
- SDK hiển thị thông tin đơn hàng.
- SDK cho phép user tiêu VPoint, áp dụng voucher và chọn phương thức thanh toán online.
- Sau khi user xác nhận:
- SDK thực hiện thanh toán qua hệ thống Payment (theo cấu hình merchant/terminal của MiniApp).
- Payment Service gửi IPN về MiniApp Backend với số tiền thực thu sau khi áp dụng VPoint/voucher.
- MiniApp Backend cập nhật trạng thái đơn hàng và số tiền cuối cùng, sau đó MiniApp hiển thị kết quả cho user.
Chi tiết luồng xử lý (tương tự payment.md)
Luồng dưới đây giữ nguyên các bước tạo order ở MiniApp Backend, nhưng thay đổi từ bước khởi tạo thanh toán:
1. Tạo đơn hàng (MiniApp ↔ MiniApp Backend)
- MiniApp gửi request "create order" đến MiniApp Backend với thông tin đơn hàng.
- MiniApp Backend xử lý và tạo đơn hàng trong hệ thống:
- Tạo order trong database.
- Sinh
secureHashcho đơn hàng theo hướng dẫn Tạo SecureHash cho đơn hàng.
- MiniApp Backend trả về thông tin đơn hàng (orderId, referenceId, amount, secureHash, v.v.) cho MiniApp.
2. Khởi tạo phiên thanh toán (MiniApp ↔ SDK)
- MiniApp gọi JS API của SDK để khởi tạo Payment Session (ví dụ
initPaymentSession()), truyền thông tin order,paymentApiKey, và truyền thêmminiAppId(optional). - Nếu cần lưu thông tin seller phục vụ hạch toán kế toán trong mô hình marketplace/multi-seller, truyền thêm
sellerMerchantIdtrong payload request. Trường này chỉ mang ý nghĩa metadata/accounting, không đổi luồng tiền; tiền vẫn chuyển về merchant mặc định theoX-Payment-API-Key. - Nếu cần giới hạn danh sách thẻ hiển thị theo BIN, có thể truyền thêm
allowedCardPrefixes(optional, ví dụ["970436", "970418"]) để SDK filter card options ngay trong màn hình thanh toán tập trung. - Nếu cần giới hạn số tiền VPoint tối đa user được phép tiêu trong session, truyền thêm
maxVpointAmount(optional, VND minor unit, phải nhỏ hơnamount). Xem chi tiết tại initPaymentSession (JS API). - SDK tạo
paymentSessionId(hoặc nhận lại từ Payment Service) và mở màn hình thanh toán tập trung.
3. User thao tác trên màn hình thanh toán tập trung (SDK)
Trên màn hình chung của SDK, user có thể:
- Tiêu/bỏ tiêu VPoint (theo hạn mức và rule nội bộ).
- Chọn/bỏ voucher/khuyến mãi khả dụng.
- Chọn phương thức thanh toán online (thẻ/ ví/ QR/ v.v.).
Các thao tác này tương ứng với việc update Payment Session để tính ra số tiền cuối cùng.
4. Thực hiện thanh toán online & nhận kết quả
- User bấm Confirm/Pay trên màn SDK.
- SDK thực hiện thanh toán online qua hệ thống Payment.
- Payment Service gửi IPN về MiniApp Backend với:
- Trạng thái giao dịch.
- Số tiền thực thu cuối cùng sau khi áp dụng VPoint/voucher (nếu có).
- MiniApp Backend cập nhật trạng thái order và cung cấp trạng thái cho MiniApp (polling/API) để hiển thị cho user.
Sequence diagram (luồng thanh toán tập trung)
Diagram bên dưới giữ nguyên các bước tạo order (tương đương “step < 10” của luồng hiện tại) và thay đổi từ bước khởi tạo thanh toán:
- Thay vì gọi
initPayment(), MiniApp gọiinitPaymentSession()để tạopaymentSessionId. - SDK mở màn hình thanh toán tập trung để user tiêu VPoint/apply voucher, sau đó mới thanh toán online.
So sánh với luồng thanh toán MiniApp hiện tại
-
Giống nhau:
- Vẫn cần onboard MiniApp để cấp
paymentApiKey/secretKeynhư mô tả trong Tích hợp thanh toán. - MiniApp Backend vẫn:
- Tạo đơn hàng trong DB.
- Nhận và xử lý IPN từ Payment Service.
- Là source of truth về trạng thái và số tiền cuối cùng của order.
- Vẫn cần onboard MiniApp để cấp
-
Khác nhau:
- Luồng hiện tại (
payment.md):- MiniApp tự điều khiển luồng chọn phương thức thanh toán và có thể tự kết hợp luật promotion/VPoint ở tầng MiniApp/MiniApp Backend.
- SDK chủ yếu hiển thị chọn phương thức và khởi tạo thanh toán theo order đã tính toán sẵn.
- Luồng tập trung (file này):
- SDK chịu trách nhiệm chính trong việc:
- Tính toán và apply VPoint.
- Apply/cộng gộp voucher/khuyến mãi tương thích.
- Lựa chọn provider/phương thức thanh toán online phù hợp.
- MiniApp tập trung vào luồng nghiệp vụ chính, chuyển thông tin order sang SDK và xử lý kết quả trả về.
- SDK chịu trách nhiệm chính trong việc:
- Luồng hiện tại (
Trách nhiệm các thành phần
MiniApp (Frontend)
- Thu thập thông tin order từ user.
- Gọi JS API SDK để:
- Mở màn hình thanh toán tập trung.
- Nhận callback kết quả (thành công/thất bại/huỷ).
- Hiển thị trạng thái thanh toán cuối cùng dựa trên dữ liệu từ MiniApp Backend.
MiniApp Backend
- Tạo và lưu order trong hệ thống.
- Nhận IPN từ Payment Service:
- Với luồng thanh toán tập trung, chỉ có 1 IPN duy nhất được gửi sau khi kết thúc Payment Session (không gửi nhiều IPN trung gian).
- IPN ngoài các field chuẩn còn có thể kèm
breakdown(chi tiết cấu trúc: IPN — Breakdown) để biết rõ tiền qua cổng, voucher, VPoint… - Cập nhật trạng thái order (COMPLETED/FAILED/CANCELLED…) và số tiền thực thu.
- Cung cấp API cho MiniApp để:
- Lấy trạng thái hiện tại của order.
- Hiển thị số tiền cuối cùng, số VPoint đã tiêu, khuyến mãi đã áp dụng… (nếu cần).
IPN trong luồng thanh toán tập trung
Đối với luồng thanh toán tập trung:
- Payment Service gửi một IPN kết thúc khi payment session kết thúc (thành công / failed / cancelled). Xử lý bất đồng bộ và payload tuân Xử lý kết quả thanh toán (IPN) (verify
secureHash, retry, v.v.). - Khi giao dịch có nhiều nguồn tiền, IPN có thể kèm
breakdown. Toàn bộ định nghĩabreakdown(gồmstatustừng item:PENDING|SUCCESS|FAILED|CANCELLED),details,referenceId,referenceType, quy tắcamounttop-level so với tổng các dòng: mục Breakdown trong IPN. paymentMethod/paymentProvidertrên payload là primary (VSF Promotion, Vinclub, cổng PSP…); không thay chobreakdown: mục Primary payment method và allocations.
Payment Service / SDK
- Quản lý cấu hình merchant/terminal, mapping
paymentApiKey. - Thực hiện:
- Hiển thị màn hình thanh toán tập trung.
- Tích hợp với hệ thống VPoint/voucher nội bộ.
- Gọi Payment Provider để thực hiện thanh toán online.
- Gửi IPN về MiniApp Backend sau khi có kết quả thanh toán cuối cùng.
Refund khi đơn hàng từ Payment Session
Khi đơn hàng được thanh toán qua luồng tập trung (Payment Session), refund có hai dạng:
- FULL: Hoàn trả đầy đủ Promotion (voucher), VPoint và tiền. Không cần truyền chi tiết từng phần.
- PARTIAL: Chỉ hoàn trả phần VPoint và phần tiền (money); không hoàn Promotion. Order Backend bắt buộc truyền đúng số tiền (
amount) và số điểm VPoint (refundVpoint) cần hoàn khi gọi API refund.
Chi tiết API và secureHash: Quản lý giao dịch thanh toán (mục Refund Transaction, phần "Refund khi giao dịch từ Payment Session").
Liên kết liên quan
- Tích hợp thanh toán – Luồng thanh toán MiniApp chuẩn và các yêu cầu tích hợp.
- Lấy chi tiết Payment Session (Backend) – API query trạng thái và chi tiết payment session (PENDING, COMPLETED, breakdown, v.v.).
- Khởi tạo thanh toán từ Backend – API initPayment từ backend qua Mule.
- initPaymentSession (JS API) – API SDK khởi tạo payment session (bao gồm tham số
allowedCardPrefixesnếu cần filter BIN thẻ). - Quản lý giao dịch thanh toán – Các API cancel, refund, confirm.
- Xử lý kết quả thanh toán (IPN) – Nhận và xử lý IPN sau thanh toán.