Keewano Unity SDK
Loading...
Searching...
No Matches
In-App Purchases

Overview

In-app purchases (IAP) are real-money transactions where players purchase premium currency, items, or other content from app stores (Apple App Store, Google Play). The Keewano SDK provides dedicated methods to track both the monetary transaction and the virtual items granted from these purchases.

Note
Best Practice: Server-Side Validation
For optimal fraud prevention and accurate analytics, we strongly recommend calling these IAP tracking methods only after your server validates the purchase receipt with Apple/Google. This ensures your revenue data reflects genuine transactions and helps the Keewano AI Agents provide more accurate insights.

IAP vs Virtual Economy

It's important to understand the distinction between two types of transactions in your game:

  • In-App Purchases (IAP): Real money → Virtual currency/items (tracked with ReportInAppPurchase and ReportInAppPurchaseItemsGranted)
  • Virtual Economy: Virtual items → Other virtual items (tracked with ReportItemsExchange)

For example:

  • Player buys "500 Crystals Pack" for $4.99 → IAP
  • Player spends 100 Crystals to buy a sword → Virtual Economy (see In-Game Balance)

The Two IAP Methods

The Keewano SDK provides two separate methods for tracking in-app purchases:

1. ReportInAppPurchase - Track the Monetary Transaction

Use KeewanoSDK.ReportInAppPurchase() to log the real-money purchase event.

// After server validation
KeewanoSDK.ReportInAppPurchase(productId, priceInUsdCents);
Definition KeewanoSDK.cs:18
static void ReportInAppPurchase(string productName, uint priceUsdCents)
Reports an in-app purchase event.
Definition KeewanoSDK.cs:290

Parameters:

  • productId - The product identifier as defined in app stores (e.g., "com.mygame.crystals_500")
  • priceInUsdCents - The price in US cents (e.g., $4.99 = 499)

When to call:

  • ONLY after your server validates the purchase with Apple/Google
  • ONCE per purchase (even if items are granted multiple times)

2. ReportInAppPurchaseItemsGranted - Track the Items Delivered

Use KeewanoSDK.ReportInAppPurchaseItemsGranted() to log the virtual items or currencies granted to the player from the purchase.

// After server validation and successful grant
Keewano.Item[] grantedItems = { new Keewano.Item("Crystals", 500) };
static void ReportInAppPurchaseItemsGranted(string productName, Item[] items)
Reports items granted from an in-app purchase.
Definition KeewanoSDK.cs:310
Definition KBatch.cs:6
Represents a game item with a unique identifier and a quantity.
Definition KeewanoItems.cs:11

Parameters:

  • productId - The same product identifier used in ReportInAppPurchase
  • items - Array of items granted (can also use ReadOnlySpan<Item> for zero-copy performance)

When to call:

  • ONLY after items are successfully granted to the player's account
  • Every time items are granted (can be multiple times for monthly/daily packages)

Why Are These Two Methods Separated?

These methods are separated because the purchase event and item grant event may happen at different times:

Common Cases for Separation

  1. Asynchronous Server Validation: Purchase completes → server validates → items granted later
  2. Monthly Packages: Player purchases once, but receives items daily/weekly over a month
  3. Time-Limited Offers: Purchase validated immediately, but items granted when player claims them
  4. Login Rewards: Player purchases a "30-Day Login Bonus" pack → items granted each day they log in
  5. Failed Grants: Purchase validated successfully, but item grant fails (network issue, database error) → retry later

Example: Monthly Login Package

A player purchases a "Monthly Gems Package" for $9.99 that grants 100 gems every day for 30 days:

// Day 1: Player completes purchase
void OnMonthlyPackagePurchased()
{
// Report the monetary transaction ONCE
KeewanoSDK.ReportInAppPurchase("com.mygame.monthly_gems", 999);
// Grant first day's gems
Keewano.Item[] items = { new Keewano.Item("Gems", 100) };
KeewanoSDK.ReportInAppPurchaseItemsGranted("com.mygame.monthly_gems", items);
}
// Days 2-30: Player logs in each day
void OnDailyLogin()
{
if (PlayerHasActiveMonthlyPackage())
{
// Grant daily gems (NO ReportInAppPurchase - already reported on Day 1)
Keewano.Item[] items = { new Keewano.Item("Gems", 100) };
KeewanoSDK.ReportInAppPurchaseItemsGranted("com.mygame.monthly_gems", items);
}
}

The Complete Purchase Flow

Here's the recommended flow for handling in-app purchases:

Flow Diagram

sequenceDiagram
    actor Player
    participant Game
    participant Store as App Store
    participant Server as Your Server
    participant API as Apple/Google API
    participant SDK as KeewanoSDK

    Player->>Game: 1. Click "Buy" button
    activate Game

    rect rgb(200, 230, 201)
    note right of Game: Keewano Auto-Tracking
    Game->>SDK: 2. (Automatic) ReportButtonClick()
    end

    Game->>Store: 3. Initiate purchase
    deactivate Game
    activate Store
    Store->>Store: 4. Process payment
    Store->>Game: 5. Purchase receipt
    deactivate Store

    rect rgb(255, 243, 224)
    note right of Game: Server Validation Phase
    activate Game
    Game->>Server: 6. Validate receipt
    activate Server
    Server->>API: 7. Verify receipt
    activate API
    API-->>Server: 8. Valid confirmation
    deactivate API
    Server->>Server: 9. Grant items to player
    Server-->>Game: 10. Confirm grant
    deactivate Server
    end

    activate Store
    Game->>Store: 11. Finalize/acknowledge purchase
    Store-->>Game: 12. Purchase complete
    deactivate Store

    rect rgb(200, 230, 201)
    note right of Game: Keewano Reporting Phase
    Game->>SDK: 13. ReportInAppPurchase()
    Game->>SDK: 14. ReportInAppPurchaseItemsGranted()
    deactivate Game
    end

Common Scenarios

Scenario 1: Immediate Grant (Synchronous)

The most common case where items are granted immediately after validation.

// Called by your server validation callback
void OnPurchaseValidated(string productId, uint priceUsdCents, Keewano.Item[] grantedItems)
{
// 1. Report the monetary transaction
KeewanoSDK.ReportInAppPurchase(productId, priceUsdCents);
// 2. Report the items granted
KeewanoSDK.ReportInAppPurchaseItemsGranted(productId, grantedItems);
}

Scenario 2: Delayed Grant (Asynchronous)

Purchase is validated first, items are granted later.

// Step 1: Server validates the purchase
void OnPurchaseValidated(string productId, uint priceUsdCents)
{
// Report the monetary transaction immediately
KeewanoSDK.ReportInAppPurchase(productId, priceUsdCents);
// Server will grant items asynchronously...
}
// Step 2: Later, when server grants the items
void OnItemsGrantedFromPurchase(string productId, Keewano.Item[] grantedItems)
{
// Report the items that were granted
KeewanoSDK.ReportInAppPurchaseItemsGranted(productId, grantedItems);
}

Scenario 3: Monthly/Daily Packages

Player purchases once, receives items over time.

// Player purchases "30-Day VIP Pass" for $14.99
void OnVIPPassPurchased()
{
// Report purchase ONCE
KeewanoSDK.ReportInAppPurchase("com.mygame.vip_pass_30days", 1499);
// Grant Day 1 rewards
Keewano.Item[] day1Rewards = {
new Keewano.Item("VIP_Status", 30), // 30 days of VIP
new Keewano.Item("Daily_Gems", 200)
};
KeewanoSDK.ReportInAppPurchaseItemsGranted("com.mygame.vip_pass_30days", day1Rewards);
}
// Each subsequent day (2-30)
void OnDailyLogin()
{
if (PlayerHasActiveVIPPass())
{
// Grant daily rewards (NO ReportInAppPurchase call)
Keewano.Item[] dailyRewards = {
new Keewano.Item("Daily_Gems", 200)
};
KeewanoSDK.ReportInAppPurchaseItemsGranted("com.mygame.vip_pass_30days", dailyRewards);
}
}

Scenario 4: Bundle with Multiple Items

When a purchase grants multiple different items.

void OnStarterPackPurchased()
{
string productId = "com.mygame.starter_pack";
uint price = 999; // $9.99
// Bundle contains multiple items
Keewano.Item[] bundleItems = {
new Keewano.Item("Crystals", 1000),
new Keewano.Item("Gold_Coins", 5000),
new Keewano.Item("Epic_Sword"),
new Keewano.Item("Health_Potion", 10)
};
KeewanoSDK.ReportInAppPurchase(productId, price);
}

Scenario 5: Purchase Validated but Grant Fails

If the purchase is valid but item grant fails temporarily.

void OnPurchaseValidated(string productId, uint priceUsdCents)
{
// Report the monetary transaction (purchase was valid)
KeewanoSDK.ReportInAppPurchase(productId, priceUsdCents);
// Attempt to grant items
bool success = TryGrantItemsToPlayerAccount(productId);
if (success)
{
Keewano.Item[] items = GetItemsForProduct(productId);
}
else
{
// Log error - player paid but didn't receive items yet
KeewanoSDK.LogError($"Failed to grant items for purchase: {productId}");
// Implement retry logic
// Call ReportInAppPurchaseItemsGranted later when items are successfully granted
}
}
static void LogError(string message)
Reports a technical issue encountered during gameplay.
Definition KeewanoSDK.cs:627

Best Practices

Server Validation is Critical

NEVER do this:

// BAD: Reporting immediately on store callback without validation
void OnAppStoreCallback(Purchase purchase)
{
// This is vulnerable to fraud!
KeewanoSDK.ReportInAppPurchase(purchase.productId, purchase.price);
}

ALWAYS do this:

// GOOD: Only report after server validation
void OnAppStoreCallback(Purchase purchase)
{
// Send to your server for validation first
YourServerAPI.ValidatePurchase(purchase.receipt, OnValidationComplete);
}
void OnValidationComplete(ValidationResult result)
{
if (result.isValid)
{
// Now it's safe to report
KeewanoSDK.ReportInAppPurchase(result.productId, result.priceUsdCents);
KeewanoSDK.ReportInAppPurchaseItemsGranted(result.productId, result.items);
}
}
Note
Server validation implementation is your responsibility. You must integrate with Apple's App Store Server API or Google Play Developer API to verify purchase receipts. This documentation shows when to call the Keewano SDK methods, not how to implement server validation.

Use Consistent Product IDs

Use the same product ID for both methods:

string productId = "com.mygame.crystals_500";
KeewanoSDK.ReportInAppPurchaseItemsGranted(productId, items); // Same productId

Only Report Actually Granted Items

Only call ReportInAppPurchaseItemsGranted() when items are successfully added to the player's account:

bool itemsGranted = AddItemsToPlayerInventory(items);
if (itemsGranted)
{
// Only report if grant succeeded
}

Prices Must Be in USD Cents

Always convert prices to USD cents, regardless of the player's local currency:

// If local price is €4.49, convert to USD first (you must implement this conversion)
uint priceUsdCents = ConvertToUsdCents(localPrice, localCurrency);
KeewanoSDK.ReportInAppPurchase(productId, priceUsdCents);

Report Purchase Once Only

For packages where items are granted multiple times, only call ReportInAppPurchase() once when the purchase is made:

// DAY 1: Purchase completed
KeewanoSDK.ReportInAppPurchase("monthly_pack", 999); // ✅ Call ONCE
KeewanoSDK.ReportInAppPurchaseItemsGranted("monthly_pack", day1Items);
// DAY 2-30: Daily rewards
// ❌ Do NOT call ReportInAppPurchase again
KeewanoSDK.ReportInAppPurchaseItemsGranted("monthly_pack", dailyItems); // ✅ Call each day

String Parameter Limits

Product IDs and item names are limited to 255 characters and will be trimmed if longer. Empty or null strings will skip the event.

See Also