Skip to content
  • Our Product
    • Namazu Elements
      • What is Elements?
      • Why open source?
      • Docs
        • Elements in Five Minutes or Less
        • RESTful APIs Library
        • Security Model
        • Accessing the Web UI (CMS)

    Our Product

    A logomark with three layered rhombuses adorning the lettermark that says Elements in bold all-caps sans-serif letters.
    • What is Namazu Elements? Discover our easy-to-use backend network solution built for online games. Rapidly enables full-scale multiplayer games or online solo adventures.
    • Why open source? Is there a truly open source server backend for connected games? There is now. Download and run a local copy of Namazu Elements and try it for yourself.
    Download Namazu Elements

    Get started

    • Quick start Read our Elements 5-minute quick start guide
    • Documentation Read our developer docs for learning more about Elements
    • RESTful APIs A full list of core API specs for working with the Elements framework
    • Security An overview of the server-authoritative security model of Elements
    • Accessing the CMS Manage your game with ease via the Namazu Elements CMS.

    Co-development Reimagined

    • Reduce your costs Would you rather outsource your backend development? Hire Namazu Studios to build your server backend with the power of Namazu Elements.
      Co-dev

    Recent Posts

    • The watercolor-styled Namazu Studios logo over a giant namazu lurking in the depth
      Namazu Studios Featured in San Diego Business Journal
      22 Sep 2025 Press
    • Namazu Elements 3.1 Released – Service Layer Fixes, Secure APIs, and Steam Bug Fix
      22 Apr 2025 Release Notes
  • Case Studies
  • About Us
  • News
  • Services
  • Book a call
namazu-studios-logo
Book a call

Getting Started

  • Elements in Five Minutes or Less
  • Accessing the Web UI (CMS)
  • General Concepts
  • N-Tier Architecture
  • Security Model

Namazu Elements Core

  • User Authentication / Sign In
    • What is a User?
    • User Authentication in Elements
    • Auth Schemes
      • Auth Schemes
      • OAuth2
      • OIDC
  • Features
    • Applications
    • Sessions
    • Users and Profiles
    • Digital Goods
    • Progress and Missions
    • Progress and Missions (3.4+)
    • Leaderboards
    • Matchmaking – Comprehensive Guide
    • Followers
    • Friends
    • Receipts
    • Reward Issuance
    • Save Data
    • Metadata
    • Metadata (3.4+)
    • Queries
    • Web3
      • Wallets
      • Vaults
      • Omni Chain Support
      • Smart Contracts
        • Smart Contracts
  • Queries
    • Advanced Operators
    • Object Graph Navigation
    • Boolean Queries
    • Base Query Syntax
  • Advanced Operators
    • .name
    • .ref

Custom Code

  • Custom Code Overview
  • Windows Setup
  • Mac OS Setup
  • Ubuntu Linux Setup
  • Introduction to Guice and Jakarta in Elements
  • Structuring your Element
  • Packaging an Element with Maven
  • Deploying an Element
  • Preparing for code generation
  • Properties
  • Websockets
  • RESTful APIs
  • Direct MongoDB Access (3.5+)

Releases

  • 3.5 Release Notes
  • 3.4 Release Notes
  • 3.3 Release Notes
  • 3.2 Release Notes
  • 3.1 Release Notes

Configuration

  • Matchmaking – Comprehensive Guide
  • Direct Database Access and Batch Configuration
  • Batch Samples
    • Mission Upload Bash Script Sample
    • Item Upload Bash Script Sample

RESTful APIs

  • RESTful APIs Library
  • Swagger and Swagger UI

Add-Ons

  • Custom Elements
    • Crossplay
      • Namazu Crossfire (Multiplayer)
      • Deploying Namazu Crossfire in your game
  • Game Engines
    • Unity
      • Elements Codegen
      • Crossfire
    • Roblox
      • Roblox Overview
      • Secure Player Authentication & Registration
      • Global Matchmaking
      • Roblox Security Best Practices

Troubleshooting

  • Common Issues with Docker
  • Local SDK
    • Unable to deploy application : dev.getelements.elements.sdk.exception.SdkElementNotFoundException
    • Could not load class : java.lang.NoClassDefFoundError
  • Namazu Elements Community Edition
    • Common Issues with Docker
    • Unable to deploy application : dev.getelements.elements.sdk.exception.SdkElementNotFoundException
View Categories
  • Home
  • Docs
  • Namazu Elements Core
  • Features
  • Receipts

Receipts

Est. read time: 6 min read

Overview #

  • The Receipt API stores generic receipt objects containing basic metadata and raw receipt payloads. It supports admin/support operations (search, inspect, delete) while concrete provider-specific APIs (Apple, Google Play, Facebook, Oculus) parse and operate on the raw receipt body for user-level flows (validation, redeeming).

Receipt model #

  • Description: A generic receipt that stores user purchase information.
  • Fields:
    • id (String): The DB id of this receipt.
    • originalTransactionId (String): ID of the original transaction from the payment processor.
    • schema (String): Receipt provider id in reverse-DNS notation (e.g. com.company.platform).
    • user (User): The user associated with this receipt.
    • purchaseTime (long): Purchase time in ms since Unix epoch.
    • body (String): String representation of the raw receipt data (JSON).

Intended usage #

  • General Receipt API (admin/support): manage receipts, search by schema, view raw body, delete.
  • Concrete provider APIs (user-level): detect provider by receipt.schema, parse JSON in body into provider-specific models (e.g. AppleIapReceipt, GooglePlayIapReceipt, OculusIapReceipt) and perform validation/redeem operations. See Application Configurations for more information on how to map a SKU or product id to an Item in Elements.

DAO interface (ReceiptDao) #

  • Key constants:
    • RECEIPT_CREATED = “dev.getelements.elements.sdk.model.dao.receipt.created”
  • Important methods:
    • Pagination getReceipts(User user, int offset, int count, String search)
      • Use search to filter by schema when supporting multiple IAP providers.
    • Pagination getReceipts(User user, int offset, int count)
    • Receipt getReceipt(String id)
    • Receipt getReceipt(String schema, String originalTransactionId)
    • Receipt createReceipt(Receipt receipt)
      • Throws InvalidDataException or DuplicateException if invalid/duplicate.
      • Emits RECEIPT_CREATED event (see events below).
    • void deleteReceipt(String receiptId)

Transaction usage (recommended) #

  • Always prefer DAO operations inside a transaction to ensure consistency and automatic retry on failure.
  • Example:
@Inject
private Provider<Transaction> transactionProvider;

final var createdReceipt = transactionProvider.get().performAndClose(tx -> {
    final var receiptDao = tx.getDao(ReceiptDao.class);
    return receiptDao.createReceipt(receipt);
});

Events #

  • RECEIPT_CREATED fires when any new receipt is created.
  • Events for specific receipt types are also fired if you only want to handle a specific type and receive the converted receipt for that type (i.e. the parsed raw receipt JSON). These include:
    • OCULUS_IAP_RECEIPT_CREATED
    • APPLE_IAP_RECEIPT_CREATED
    • GOOGLE_PLAY_IAP_RECEIPT_CREATED
    • FACEBOOK_IAP_RECEIPT_CREATED
  • Event parameters variants:
    • (Receipt)
    • (Receipt, Transaction)
  • Use this event for downstream processing (e.g., kicking off parsing, validation, fulfillment). Event handlers should inspect receipt.schema to determine provider-specific parsing. See Events for more information on how to register event callbacks and create your own custom events.

Provider mapping (existing) #

  • Use schema to detect provider:
    • GOOGLE_IAP_SCHEME -> GooglePlayIapReceipt
    • OCULUS_PLATFORM_IAP_SCHEME -> OculusIapReceipt
    • APPLE_IAP_SCHEME -> AppleIapReceipt
    • FACEBOOK_IAP_SCHEME -> FacebookIapReceipt
  • Concrete API implementations parse the JSON in Receipt.body into the corresponding provider model and provide validation/redeem endpoints.

Integrating a new payment provider #

If you want to add support for a payment provider or are creating a custom Element for your own solution, here are some steps to follow:

  • Select a schema string
    • Use reverse-DNS notation: e.g. com.example.myprovider
    • Add a constant: String MYPROVIDER_IAP_SCHEME = “com.example.myprovider”;
  • Define a provider-specific receipt model
    • Create a POJO class that represents the JSON structure of the provider’s receipt payload (e.g., MyProviderIapReceipt).
    • Add @Schema annotations for clarity in client side generated code.
  • Implement parsing and validation logic
    • Add a parser that takes Receipt.body (string JSON) and maps to MyProviderIapReceipt.
    • Implement validation routines (signature checks, timestamps, server-to-server verification endpoints, etc.) according to provider docs.
  • Add concrete API endpoints / service
    • Provide user-level APIs to:
      • Submit a receipt for validation/redeem.
      • Query validated receipts for a user.
    • These APIs should:
      • Locate the generic Receipt (by schema + originalTransactionId or by DB id).
      • Parse Receipt.body to MyProviderIapReceipt.
      • Validate and execute fulfillment (redeem digital goods, record consumptions).

Hint

With dev.getelements.elements.auth.enabled=true set in your Element attributes, you can inject the UserService and then use userService.getCurrentUser() to get the User that made the request. See the example-element project for an example of this.

  • Add admin API endpoints/service
    • Provide superuser-level APIs to:
      • Map product ids or SKUs to Items in Elements
      • View receipts for all users
  • Persist receipts via DAO
    • When creating receipts (e.g., incoming from client or server webhook), use ReceiptDao.createReceipt(…) inside a transaction.
    • Example create flow:

Example:

Receipt r = new Receipt();
r.setOriginalTransactionId(providerTxId);
r.setSchema(MYPROVIDER_IAP_SCHEME);
r.setUser(user);
r.setPurchaseTime(System.currentTimeMillis());
r.setBody(rawJson);

final var saved = transactionProvider.get().performAndClose(tx -> {
    return tx.getDao(ReceiptDao.class).createReceipt(r);
});
  • Handle duplicates and errors
    • createReceipt may throw DuplicateException if schema + originalTransactionId already exist.
    • Catch and handle InvalidDataException for malformed receipts.
    • ReceiptDao handles idempotency: on retries, it will detect duplicates and return the existing receipt.
  • Subscribe to RECEIPT_CREATED (optional)
    • Use the event to trigger asynchronous parsing/validation or analytics.
    • Event handlers should be resilient: validate schema, parse body, and record results; do not assume body is well-formed.

Best practices and recommendations #

  • Always validate schema value before parsing.
  • Keep raw body immutable in DB; parse into separate model objects for business logic and caching parsed values if needed.
  • Use transactions around DAO writes to ensure consistency.
  • Enforce idempotency in validation/redeem flows based on originalTransactionId + schema.
  • Log parsing and validation failures, and surface helpful errors to support team via admin tools.
  • When adding new providers, document the provider schema constant, payload model, parsing rules, and any external verification endpoints.

Example: reading a receipt and parsing per schema

ReceiptDao dao = tx.getDao(ReceiptDao.class);
Receipt receipt = dao.getReceipt("com.example.myprovider", originalTransactionId);

switch (receipt.getSchema()) {
    case MYPROVIDER_IAP_SCHEME:
        MyProviderIapReceipt parsed = myProviderParser.parse(receipt.getBody());
        myProviderValidator.validate(parsed);
        // proceed with redeem/fulfill
        break;
    case APPLE_IAP_SCHEME:
        AppleIapReceipt apple = appleParser.parse(receipt.getBody());
        // ...
        break;
    // other cases
}

Support/admin considerations #

  • The built in Elements CMS will parse the OpenAPI spec for your custom Element and generate UI for it. This allows you to interact with the endpoints, manage receipts, and create your SKU to Item mappings without writing any frontend code. That said, you may want to:
    • Allow searching/filtering by schema to focus on a specific provider’s receipts.
    • Provide the ability to re-trigger parsing/validation from admin tools when needed (Items can be added to a User’s inventory manually through the CMS as well).

FAQ (short) #

  • Q: Where to store parsed provider models?
    • A: Store parsed results in separate tables/models; keep Receipt.body as the immutable raw source.
  • Q: How to handle provider changes to payload format?
    • A: Version parsed models, add migration/compatibility logic, and keep raw JSON to reparse historical receipts if necessary.
  • Q: When should I use the concrete APIs vs the general Receipt API?
    • A: Use concrete APIs for user-level validation/redeem flows. Use the general Receipt API for admin/support and cross-provider management.
What are your Feelings
Still stuck? How can we help?

How can we help?

Updated on January 9, 2026
Metadata (3.4+)
Table of Contents
  • Overview
  • Receipt model
  • Intended usage
  • DAO interface (ReceiptDao)
    • Transaction usage (recommended)
    • Events
    • Provider mapping (existing)
  • Integrating a new payment provider
    • Best practices and recommendations
    • Support/admin considerations
  • FAQ (short)
  • Documentation
  • Terms of Service
  • Privacy Policy
  • Contact us
  • Linkedin
  • Join our Discord

Namazu Studios LLC is powered by Namazu Elements, an Elemental Computing Inc. product.

Elements
  • Download
  • About Elements
  • Open source
  • Documentation
  • Support
About Namazu
  • Case Studies
  • About Us
  • News
Get in Touch
  • info@namazustudios.com
  • Book a call
  • (619) 862-2890
  • Linkedin
  • Discord

©2008-2025 Namazu Studios. All Rights Reserved.