From web store purchase to game wallet

Credit the wallet from a verified server webhook, then refresh the balance in the game. A checkout success screen or return URL is not proof of delivery. This walkthrough uses Appside's test integration; it does not activate live payments.

The full flow

  1. Your authenticated game backend issues a short-lived player token. Keep its private signing key on your server.
  2. The game opens the store with that token. The store uses the published catalogue and the verified player identity.
  3. A test purchase creates an order.paid event for your Fulfillment URL.
  4. Your receiver verifies the signature over the raw request body and checks timestamp freshness before parsing or granting anything.
  5. In one durable database transaction, record the event_id, add order.entitlements.total to the correct player's wallet, and write a ledger entry. Duplicate delivery must return success without another grant.
  6. Return a 2xx only after committing. The game reads the updated balance from your authenticated backend.

Configure your public JWK, issuer, Fulfillment URL and webhook secret in Studio → Integration. See the quickstart for SDK setup and webhooks for the exact payload and headers. Use the current application base URL, https://app.appside.build, when configuring SDK clients.

Verify the receiver before connecting checkout

Download the standalone webhook proof, then run:

node appside-webhook-proof.mjs

This local proof exercises signature validation, a paid grant, replay protection and a refund. It is an in-memory reference, not a hosted payment test or a production wallet. A real receiver needs persistent storage, an atomic transaction and authorization on balance reads.

Check the end-to-end integration

CheckExpected result
Studio test probeAcknowledge without changing balance
One test pack purchaseIncrease by the signed event's order.entitlements.total
Replay that same eventNo second grant
Invalid signature or stale timestampReject without changing balance
Receiver temporarily unavailableDelivery retries; eventual grant happens once
Refund and refund replayApply your refund policy once, never twice
Refund arrives before paid eventRecord it so a delayed paid event cannot restore the refunded purchase
Refresh the gameRead the server wallet, not a number from the checkout URL

Record the order ID, event ID and balance before and after each test. A payment acknowledgement and a wallet acknowledgement are different stages; keep both visible in your logs.

Daily rewards use a different payload

For reward.claimed, the grant amount is the top-level credits field. Deduplicate on event_id, not reward_id: the reward name repeats across days. The seven-day calendar uses these daily claims. See the daily reward payload.

Production considerations

Persist the event and wallet update together. Reject unexpected tenants, currencies or event types according to your integration contract. Decide explicitly how refunds affect already-spent currency; do not silently overwrite your game's economy policy. A successful local proof establishes receiver behavior, not live payment readiness.