Define a unified receipt payload your game client sends to your backend: platform identifier (apple/google/steam), purchaseToken or transactionId, productId, and player ID
Route to the platform-specific validation logic: for Apple call the App Store Server API GET /inApps/v1/transactions/{transactionId}; for Google call androidpublisher purchases.products.get; for Steam call ISteamMicroTxn/QueryTxn after FinalizeTxn
On validation success, write an idempotent grant record keyed by (platform, transactionId/token) before granting the item — check for duplicates first to prevent replay attacks
Grant the item via your server-side inventory service (e.g. PlayFab AddInventoryItems or your own database) only after the duplicate check passes
Return a structured response to the client indicating success, already-claimed, or validation-failure; never reveal raw platform error messages to the client
Known gotchas
Each platform returns different data structures; abstract the validation layer so that product entitlement grants are driven by your internal catalog mapping, not raw platform product IDs
Replay attacks using valid receipts from one player's account on another player's account are common; always bind the validated platform account ID to the game player ID and reject mismatches
Network timeouts from platform validation APIs should result in a pending state, not a failure; queue retries with exponential backoff rather than immediately refusing the purchase
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp