Khách đổi ý lúc checkout đang mở; nhân viên nhấn hủy trong khi một khoản chuyển có thể đang được xử lý. Một nút hủy đơn vì thế không chỉ đổi nhãn trên màn hình. Backend cần biết yêu cầu còn được phép hủy hay không, nhận kết quả đúng và giữ đường xử lý nếu tiền đến sau đó.
Hướng dẫn trên hoadontudong.com.vn đi từ điều kiện hủy đến cuộc đua giữa thao tác hủy và thanh toán. Có thể đọc giới thiệu Pay2S API trước, rồi đối chiếu đặc tả API hủy Collection Link khi triển khai.
Cancel trong cổng thanh toán tự động Pay2S là gì?
Cancel là thao tác yêu cầu hủy một đơn thanh toán chưa trả. Nó liên quan đến đơn đã tạo, nên cần giữ đúng mã và phạm vi khóa từ luồng tạo Collection Link. Không tạo mã đơn mới để biểu diễn việc hủy mã cũ.

API đối tác dùng POST https://payment.pay2s.vn/v1/gateway/api/cancel. Bộ khóa tương ứng với API create; Secret Key chỉ dùng ký tại backend. Đây là contract khác API app dùng Bearer token, nên không trộn thông tin xác thực hoặc lấy một mẫu request của ứng dụng quản trị để gọi từ website merchant.
Trong phần mềm bán hàng, trạng thái yêu cầu hủy nên tách với kết quả đã hủy. Nếu người dùng bấm nút, hệ thống có thể ghi nhận đang xử lý và chờ response. Chỉ đổi sang kết quả cuối khi có căn cứ, thay vì hiển thị thành công ngay lúc request vừa rời ứng dụng.

Lịch sử hủy cần giữ người yêu cầu, thời điểm, lý do và đơn liên quan. Những dữ liệu này phục vụ tra soát khi khách thanh toán gần cùng lúc. Một thao tác xóa bản ghi sẽ làm mất thông tin cần để giải thích khoản tiền nhận muộn.
Khi nào được hủy đơn?

Theo đặc tả, API áp dụng đơn Collection Link V1 và V2 chưa thanh toán. Đơn đã trả không đi qua luồng này để hoàn tiền. Backend nên kiểm tra trạng thái nội bộ trước khi gửi, đồng thời vẫn xử lý kết quả API vì trạng thái có thể thay đổi trong khoảng giữa kiểm tra và request.
Tại thời điểm gửi POST https://payment.pay2s.vn/v1/gateway/api/cancel, cần sử dụng đúng orderId merchant đã truyền lúc tạo. Secret Key thuộc bộ khóa của đơn; không thử lần lượt các khóa khác nhau để tìm một kết quả thành công. Phạm vi truy cập là một phần của kiểm soát, không phải lỗi cần vượt qua.
Doanh nghiệp cũng cần chính sách cho ai được yêu cầu hủy. Khách tự hủy khi chưa trả khác nhân viên hủy thay theo phản ánh. Với thao tác nội bộ, phân quyền và lý do giúp người khác hiểu quyết định mà không phải tìm lại hội thoại riêng.
Payload và chữ ký cancel
Payload có dữ liệu xác thực công khai, orderId, requestId riêng của lần hủy, requestType và chữ ký. Secret Key không được gửi trong body. Chuỗi ký cancel có thứ tự riêng; không dùng lại chữ ký create hoặc thêm trường của V2 để cố làm request tương thích.
extraData không thuộc request cancel. Khi tạo hàm dựng payload, nên xác định rõ các trường được phép thay vì sao chép nguyên object đã dùng lúc create. Cách tổ chức này hạn chế dữ liệu thừa và giúp kiểm thử contract bằng một tập đầu vào nhỏ.
Cũng không lấy extraData hoặc metadata hóa đơn làm căn cứ xác định đơn hủy. orderId cùng phạm vi bộ khóa là tham chiếu cần đúng. requestId của lần hủy được lưu riêng để đối chiếu response, không ghi đè dấu vết lần tạo đơn.
Trước khi gọi thật, kiểm tra giá trị ký khớp giá trị gửi và không bị URL-encode hoặc chèn khoảng trắng. Log phục vụ chẩn đoán cần che bí mật. Nếu chữ ký sai, sửa nguyên nhân ở cấu hình hoặc cách dựng chuỗi rồi mới gửi lại.
Race giữa cancel và thanh toán
Race condition xảy ra khi thao tác hủy và xác nhận thanh toán cùng tiến gần một thời điểm. Backend không thể đảm bảo kết quả chỉ bằng việc kiểm tra trạng thái vài giây trước đó. Nó cần áp dụng các chuyển trạng thái có điều kiện và xử lý response hoặc thông báo đến theo thứ tự thực tế.
Tình huống giả định: ứng dụng ghi đang hủy, sau đó nhận được kết quả thanh toán hợp lệ. Không được để một tác vụ hủy cũ ghi đè đơn đã trả. Ngược lại, khi hủy được xác nhận nhưng xuất hiện khoản tiền cần tra soát, phải giữ hồ sơ tiền nhận và giải quyết theo chính sách, không âm thầm kích hoạt lại đơn.
Phần mềm nên lưu cả yêu cầu và kết quả từng bước, với transaction phù hợp tại nơi cập nhật. Hướng dẫn state machine và chống trùng giúp đặt các điều kiện chuyển trạng thái thay vì dựa vào thao tác cuối cùng ghi database.
Khi API trả xung đột, đừng tự diễn giải thành đã hủy. Đọc kết quả, kiểm tra trạng thái và chuyển yêu cầu tới bước phù hợp. Việc người dùng muốn hủy không thay đổi sự thật một khoản đã được thanh toán.
Cancel không phải hoàn tiền
Cancel không hoàn tiền, không xóa đơn và không tự hủy hóa đơn điện tử. Đặc tả cũng nêu hủy trên Pay2S không vô hiệu hóa khả năng chuyển khoản tới tài khoản ngân hàng. Giao diện cần diễn đạt đúng giới hạn này, nhất là khi khách còn giữ QR hoặc thông tin thụ hưởng.
Vì vậy, cần một luồng riêng cho tiền đến sau hủy hoặc yêu cầu trả lại khoản đã nhận. Hồ sơ phải xác minh tiền thực tế, đơn liên quan, người thụ hưởng và quyền phê duyệt. Trạng thái hoàn tiền chỉ đổi khi có kết quả tài chính tương ứng, không chỉ vì nhân viên đã gửi yêu cầu.
Nếu đơn có hóa đơn, kế toán xác định cách xử lý theo nghiệp vụ và quy định áp dụng. Không nối một nút cancel thanh toán trực tiếp với việc hủy chứng từ theo suy đoán. Hai quy trình có điều kiện, dữ liệu và trách nhiệm khác nhau.
Runbook hủy đơn
Runbook nên bắt đầu bằng xác định đơn và lý do yêu cầu, kiểm tra quyền rồi kiểm tra trạng thái. Sau khi gửi request, ghi response có cấu trúc. API cancel trả kết quả trực tiếp; không chờ một webhook hủy để thay thế việc xử lý response của endpoint này.
Nếu request tới https://payment.pay2s.vn/v1/gateway/api/cancel timeout, giữ kết quả chưa xác định và thực hiện kiểm tra hoặc gọi lại theo đặc tả. Secret Key tiếp tục được giữ tại backend. Không đổi orderId hoặc xóa lịch sử để làm lại. Đơn đã hủy được gọi lại có thể trả thành công, nhưng ứng dụng vẫn cần tránh lặp các tác vụ nội bộ gắn với việc hủy.
Thông báo cho khách nên phân biệt đang xử lý, đã hủy và không thể hủy theo trạng thái hiện tại. Nếu chưa rõ tiền có đến hay không, hướng dẫn tra cứu và giữ mã đơn. Cách phản hồi cụ thể sẽ giảm việc khách thử chuyển lại hoặc gửi nhiều yêu cầu hỗ trợ cùng một vấn đề.
Ví dụ kỹ thuật an toàn cho Cổng thanh toán tự động Pay2S
Payload sau minh họa request cancel với dữ liệu giả. Secret Key dùng để tạo chữ ký ở backend, không được bổ sung thành trường gửi. Các placeholder phải được thay bằng dữ liệu đúng phạm vi khi thử trong môi trường phù hợp.
{
"accessKey": "YOUR_ACCESS_KEY",
"partnerCode": "YOUR_PARTNER_CODE",
"orderId": "ORDER_DEMO_001",
"requestId": "CANCEL_DEMO_001",
"requestType": "cancel",
"signature": "<SIGNATURE>"
}
Trước POST, đối chiếu mã đơn với bản ghi create và kiểm tra requestType. Không để khóa ký xuất hiện trong request hoặc log. Sau response, kiểm tra orderId và kết quả trả về trước khi cập nhật trạng thái; HTTP thành công cần được đọc cùng body.
Quy trình triển khai Cổng thanh toán tự động Pay2S
Nên triển khai nhánh hủy sau khi luồng tạo đơn và ghi nhận thanh toán đã rõ. Viết các điều kiện chuyển trạng thái, dựng request, ký, gửi rồi lưu kết quả. Đặt thao tác hủy sau kiểm tra quyền và giữ dấu vết người yêu cầu.
Tiếp theo, thử hủy đơn chờ, hủy lại đơn đã hủy và yêu cầu hủy đơn đã trả. Cho các tác vụ đến gần nhau để kiểm tra không hạ trạng thái thanh toán. Bài vai trò redirect và IPN giúp kiểm tra nguồn kết quả trong những kịch bản này.
Câu hỏi thường gặp về Cổng thanh toán tự động Pay2S
Cancel có áp dụng đơn paid không?
Không. Luồng cancel dành cho đơn chưa thanh toán. Với khoản đã nhận, doanh nghiệp cần quy trình hoàn hoặc xử lý nghiệp vụ riêng.
Cancel có hoàn tiền không?
Không. Kết quả hủy không chứng minh có một khoản chuyển trả cho khách. Phải xác minh và theo dõi hoàn tiền bằng hồ sơ tài chính tương ứng.
Hủy có xóa đơn không?
Không nên xóa đơn. Giữ lịch sử tạo, yêu cầu hủy và kết quả giúp tra soát nếu khách vẫn chuyển tiền hoặc cần hỗ trợ sau đó.
Đã hủy có gọi lại được không?
Theo contract, gọi lại đơn đã hủy trả thành công mà không ghi lại trạng thái. Phía merchant vẫn phải chống lặp tác vụ và giữ lịch sử lần gọi.
Có cần hủy hóa đơn không?
API cancel không tự xử lý hóa đơn điện tử. Kế toán cần xác định hồ sơ và cách xử lý phù hợp với trạng thái hóa đơn cùng nghiệp vụ thực tế.
Kết luận
Hủy đúng là một chuyển trạng thái có căn cứ, không phải cách xóa dấu vết của đơn không còn muốn bán. Khi giữ được lịch sử và phân biệt hủy với hoàn tiền, ứng dụng có thể xử lý được khoản đến muộn mà không làm sai số liệu hoặc gây hiểu nhầm cho khách.
Đọc tiếp theo nhu cầu trong cụm Pay2S
- Pay2S là gì? Tổng quan giải pháp thanh toán trực tuyến tự động
- Pay2S là gì? API Pay2S hoạt động như thế nào trong hệ thống thanh toán
- Pay2S là gì? Pay2S có phải là cổng thanh toán không?
- Pay2S là gì? Luồng thanh toán từ lúc tạo đơn đến khi xác nhận
- Pay2S là gì? Pay2S hỗ trợ thanh toán QR và ngân hàng như thế nào?
Bộ tiêu chí nghiệm thu Cổng thanh toán tự động Pay2S
Kiểm tra kết quả thực tế của từng tình huống, bao gồm sai khóa, sai chữ ký, không tìm thấy đơn và trạng thái không còn cho phép hủy. Backend phải giữ được lý do, không biến mọi lỗi thành thông báo đã hủy. Với timeout, hồ sơ cần còn khả năng tiếp tục tra cứu.
Thử gửi lại yêu cầu đã thành công và kiểm tra số lượng tác vụ nội bộ. Việc hủy lại không được gửi thêm thông báo không cần thiết hoặc chạy điều chỉnh kho lần hai. Nếu có khoản nhận sau đó, nó phải xuất hiện trong danh sách cần kiểm tra.
Bảng kiểm trước khi mở rộng Cổng thanh toán tự động Pay2S
Trước khi đưa vào Production, xác nhận quyền thao tác, phạm vi bộ khóa, endpoint và cách hỗ trợ khi có race. Đào tạo nhân viên phân biệt yêu cầu hủy đã gửi với kết quả cuối cùng, đồng thời chỉ rõ ai phê duyệt xử lý khoản đã nhận.
Khi chính sách đổi, cập nhật cả UI, điều kiện backend và runbook. Một giới hạn chỉ được ghi trong hướng dẫn nhưng không phản ánh ở phần mềm sẽ sớm bị bỏ qua trong lúc đông yêu cầu.