Lưu ý: Bài viết mang tính cảnh báo, việc sử dụng lỗi đã nêu cho mục đích gây thiệt hại cho cá nhân/tổ chức là vi phạm pháp luật và chủ tus sẽ không chịu trách nhiệm
1. Tôi vô tình hack 500k của sàn S
Các ace mỗi dịp 11/11,12/12... lại đổ dồn đi săn sale. Và đương nhiên mình cũng nằm trong số đấy. Chuyện là mình có đặt 1 đơn hàng của sàn S ( ai cũng biết là sàn nào đấy). Giá trị hơn 500k gì đó, đúng ngày 12/12/2023 luôn. Và thanh toán bằng thẻ tín dụng của VPBank. Mua thì mình cũng mua nhiều rồi, trả góp 0% bằng thẻ tín dụng thì cũng rồi. Thứ tự lần lượt là chọn hàng -> chọn phương thức thanh toán -> link tới webview thanh toán của VPB và nhập OTP đã gửi qua SMS đến sdt. Chuyện vốn diễn ra bình thường, Cơ mà xui rủi làm sao đúng hôm đấy ( có thể quá đông người thanh toán cùng lúc chẳng hạn), web view bình thường trả về thành công thì hôm nay quay mòng mòng vài phút và trả về SESSION TIMEOUT.
Chậc, mình tặc lưỡi tự nhủ chắc phải thanh toán lại rồi. Ấn back lại thì.. bất ngờ chưa => Đơn hàng đang ở trạng thái thanh toán thành công . Quái. Là dev đã làm ở các tổ chức tài chính rồi. Mình nghĩ chắc trường hợp này là Timeout thành công rồi => Thôi kệ nó đi Nhưng mọi chuyện là diễn ra nó không đúng dự tính. Mình mua hàng lúc 9:25AM. Sau đó lúc 9:28AM ngân hàng nhắn tin trừ tiền, 9:30AM ngân hàng nhắn tin hủy giao dịch và hoàn lại tiền.)) Thôi mình tự nhủ là chắc sàn S khác xử lý thôi, làm sao để lọt cái lỗ như con voi này được. Vậy mình kệ đó, hàng vẫn giao, nhận xong rồi, confirm đã nhận hàng. Vẫn không thấy động tĩnh gì. Chậc chậc, không dám nuốt 500k, sợ tự nhiên một ngày đẹp trời các anh áo xanh mời đi uống trà thì chớt.Mình quyết định viết mở case để thông báo cho sàn S về lỗi trên để họ check. Cơ mà mình cũng k biết cụ thể là họ đã xử lý chưa, cái mail trả lời khá chung chung sau khi xin một loạt thông tin từ mình.
2. Và câu chuyện về xử lý case Timeout(504)
Như lỗi bên trên, mình bàn một chút về trạng thái Timeout của 1 giao dịch( đơn giản là qua API chẳng hạn)
Gọi api thì thành công hoặc thất bại là đủ rồi chứ?
Câu hỏi trên thì đa số các dự án nhỏ hoặc các bạn mới ra trường sẽ gật, cơ bản vậy là đủ rồi, check kỹ làm gì, mệt ra. Cơ mà đời thường không như mơ, trong các giao dịch quan trọng, SUCCESS và FAILED chưa phải là xong. Còn ông nội TIMEOUT bất ký lúc nào có cũng có thể nhảy ra. Lý do gây ra case này thì có mấy cái chính như sau:
1. Mạng quá tải => lỗi ông cung cấp mạng
2. Server quá tải => nhiều người truy cập quá
3. Code lởm => server xử lý quá lâu
4. Config thời gian chờ phía FE quá ngắn
5. Lỗi data=> Data test và data thực tế chênh lệnh quá xa
Timeout đơn giản có nghĩa là người dùng nhìn thấy trạng thái này sẽ không biết chính xác là giao dịch đã thành công hay chưa. Với các case thường gặp (VD: Chuyển tiền..) => Chúng ta đi kiểm tra lại số dư là được. Có thể server đã xử lý xong nhưng thời gian chờ của FE quá ngắn( thường thì không quá 30s) => dẫn đến trạng thái timeout ngoài màn hình.
TIMEOUT thành công và TIMEOUT thất bại
Tuy vậy. trong giao dịch tài chính, phía server ( cụ thể là BackEnd) cần xử lý case này khá cẩn thận. Với các tổ chức tài chính, đa số hệ thống được tổ chức theo mô hình micoservice. Các service phục vụ thanh toán thường sẽ đứng độc lập. Khi nhận được trạng thái timeout. Việc quan trọng nhất là xác định lại trường hợp này là timeout thành công hay timeout thất bại => Như trường hợp mình gặp phải trên, Timeout là thất bại nhưng có thể sàn S ghi nhận là thành công => vậy là mất tiền rồi.
Vậy thì nên xử lý như nào để tránh tối đa rủi ro?
Có một số cách mình hay áp dụng cho trường hợp Timeout
-
Kiểm tra lại trạng thái từ phía thanh toán
Cách nhanh nhất và realtime nhất là ngay lập tức check lại với bên thanh toán, gọi 1 api kiểm tra trạng thái giao dịch là được. Bạn sẽ biết chính xác giao dịch này là thành công hay thất bại. Nếu thành công thì đi tiếp, nếu thất bại thì có thể retry giao dịch hoặc thông báo người dùng thử lại
=> Nhược điểm: khi bạn gọi lại để kiểm tra trạng thái mà bên thanh toán vẫn chưa xử lý xong => ngất ngất
-
Tạo job quét timeout
Giao dịch giờ cao điểm bị timeout đúng không => ta giữ nguyên trạng thái Timeout và xếp nó đấy, chờ tới giờ thấp điểm ( trong ngày thôi). Ta gọi 1 api kiểm tra trạng thái giao dịch và cập nhật lại trạng thái cho giao dịch.
=> Nhược điểm: Phải vẽ thêm 1 trạng thái không xác định và gây hoang mang cho người dùng -> cái này cần thông báo rõ ràng với người dùng là được
Sử dụng cách nào hoặc sử dụng cả hai cách là phụ thuộc vào đặc thù của sản phẩm và từng hệ thống khác nhau. bạn nào còn các nào hay hơn thì chia sẻ giúp mình nhé.
Bài viết đến đây là hết, các bạn có đóng góp hay chia sẻ thêm về kinh nghiệm làm việc thì cmt bên dưới giúp mình nhé. Chúc các bạn năm mới may mắn, code ít bug ạ.