1. Bối cảnh doanh nghiệp & phạm vi
Một studio game di động vận hành tựa game nhập vai theo lượt (turn-based RPG) với 4 triệu người chơi hoạt động hằng tháng, trong đó khoảng 6% người chơi thực hiện ít nhất một giao dịch mua trong ứng dụng (IAP) mỗi tháng, đóng góp phần lớn doanh thu của studio. Nền kinh tế trong game gồm hai loại tiền tệ (vàng kiếm được miễn phí qua chơi game, và kim cương mua bằng tiền thật hoặc nhận thưởng hiếm), cùng hàng trăm loại vật phẩm có thể giao dịch giữa người chơi (trang bị, thẻ bài, vật phẩm sự kiện giới hạn). Vì tiền và vật phẩm có thể quy đổi gián tiếp thành giá trị thực (qua chợ giao dịch của bên thứ ba hoặc trao đổi ngoài luồng), bất kỳ lỗ hổng nào cho phép nhân đôi (dupe) tiền hay vật phẩm đều tương đương với việc studio bị 'in tiền giả' ngay trong hệ thống của mình, phá vỡ toàn bộ cân bằng kinh tế và gây thiệt hại tài chính trực tiếp.
Phạm vi bài viết bao trùm toàn bộ vòng đời một giao dịch kinh tế trong game: mua IAP qua App Store/Google Play, xử lý callback xác nhận thanh toán (receipt validation), cộng tiền/vật phẩm vào ví và kho đồ của người chơi, giao dịch trao đổi vật phẩm giữa hai người chơi, tiêu tiền để mua vật phẩm trong shop nội bộ, và hậu kiểm đối soát toàn bộ dòng tiền/vật phẩm phát sinh trong ngày. Ràng buộc nghiệp vụ quan trọng: mọi giao dịch tiền tệ phải có thể truy vết ngược (auditable) tới nguồn gốc phát sinh, và hệ thống phải chịu được việc App Store gửi lại cùng một callback xác nhận thanh toán nhiều lần (do timeout hoặc retry mạng) mà không cộng trùng phần thưởng — đây là bài toán idempotency kinh điển nhưng có hậu quả tài chính trực tiếp nếu làm sai.
Phạm vi tự động hoá
- Kiểm thử API cho luồng IAP, xử lý callback, và ví/kho vật phẩm
- Kiểm thử Appium cho luồng mua hàng trên client di động thật
- Kiểm thử đồng thời cho giao dịch trade và chống dupe vật phẩm
2. Kiến trúc hệ thống & luồng nghiệp vụ
Kiến trúc gồm 5 thành phần chính: Store Gateway (nhận và xác thực receipt từ App Store/Google Play), Economy Service (xử lý logic cộng/trừ tiền và vật phẩm, là điểm trung tâm bắt buộc mọi thay đổi số dư phải đi qua), Anti-cheat Engine (phân tích tốc độ nhận vật phẩm, mẫu giao dịch bất thường), Wallet Ledger (sổ cái append-only ghi mọi biến động tiền tệ), và Inventory Store (kho vật phẩm của từng người chơi). Luồng IAP diễn ra như sau: người chơi bấm mua gói kim cương trên client, hệ thống thanh toán native của thiết bị xử lý giao dịch, sau đó cả client lẫn App Store đều có thể gửi xác nhận về Store Gateway — nghĩa là hệ thống backend phải chủ động coi việc nhận được 2 xác nhận cho cùng 1 giao dịch là tình huống BÌNH THƯỜNG, không phải ngoại lệ hiếm gặp.
Điểm khó khi kiểm thử
Điểm khó nhất là đảm bảo idempotency xuyên suốt toàn bộ chuỗi: từ receipt IAP, tới giao dịch trade giữa hai người chơi, tới việc tiêu tiền mua vật phẩm trong shop — mỗi thao tác đều có khả năng bị client gửi lại (do mất mạng, app bị kill giữa chừng, hoặc người chơi cố tình bấm nút nhiều lần) và hệ thống phải đảm bảo hiệu ứng cuối cùng giống hệt như chỉ xử lý đúng 1 lần. Một khó khăn khác là phân biệt hành vi 'farming' hợp lệ (người chơi cày cuốc chăm chỉ, có thể dùng bot hỗ trợ hợp pháp trong game) với hành vi khai thác lỗi (exploit) để nhân đôi vật phẩm — cả hai đều biểu hiện là 'nhận vật phẩm nhanh bất thường', nên anti-cheat cần phân tích thêm nguồn gốc giao dịch (có đi qua đúng luồng nghiệp vụ hợp lệ hay không) thay vì chỉ nhìn tốc độ. Cuối cùng, giao dịch trade giữa hai người chơi diễn ra đồng thời từ hai client độc lập, nên cần khoá đúng phạm vi (không khoá nhầm toàn bộ kho đồ mà chỉ khoá đúng vật phẩm đang giao dịch) để vừa chống dupe vừa không làm nghẽn hệ thống khi nhiều giao dịch diễn ra song song.
3. Mô hình dữ liệu & bất biến nghiệp vụ (oracle)
Mô hình dữ liệu cốt lõi gồm 5 thực thể: Wallet (playerId, goldBalance, gemBalance, version), WalletLedgerEntry (append-only, mỗi bản ghi có amount, currency, reason, sourceTransactionId, createdAt), InventoryItem (playerId, itemId, quantity, acquiredVia), IAPReceipt (receiptToken, productId, status VERIFIED/CONSUMED/REJECTED, processedAt), và AnomalySignal (playerId, loại bất thường, mức độ, có được soát thủ công hay chưa). Bất biến quan trọng nhất — cũng là oracle chính của toàn bộ bài toán — là: với mọi IAPReceipt, số dư được cộng vào ví chỉ được phát sinh đúng một lần cho mỗi receiptToken duy nhất, bất kể Store Gateway nhận được bao nhiêu lần callback xác nhận cho cùng token đó; và tổng số dư/vật phẩm hiện có của một người chơi tại bất kỳ thời điểm nào phải bằng đúng tổng các WalletLedgerEntry hợp lệ tính từ đầu, không được lệch dù chỉ một đơn vị.
- Bất biến 1: Mỗi receiptToken chỉ tạo đúng 1 WalletLedgerEntry cộng tiền, kể cả khi nhận N callback trùng
- Bất biến 2: goldBalance/gemBalance = Σ(mọi WalletLedgerEntry hợp lệ của ví đó), luôn khớp đối soát
- Bất biến 3: Không giao dịch trừ tiền nào được phép làm số dư âm (trừ ca refund có ghi nợ tường minh)
- Bất biến 4: Một InventoryItem chỉ thuộc về đúng 1 chủ sở hữu sau khi giao dịch trade hoàn tất, không tồn tại ở cả 2 phía
- Bất biến 5: Mọi AnomalySignal mức HIGH phải khoá giao dịch liên quan chờ soát, không tự động huỷ vật phẩm của người chơi
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!