Plan for In-App-Purchase Support

From OHRRPGCE-Wiki
Jump to navigation Jump to search

In-App Purchases[edit]

I would like to add a lump for defining purchases, which would be displayed in-game as a purchases menu. It could be implemented in a generic way so the same interface could work for Android or OUYA or even iOS purchases, even though the implementations would be different.

There is also the possibility of some other stores that would work with Windows/Mac/Linux versions. I am also thinking that a Paypal-Honor-System store backend would be nifty. It could redirect the player to a browser window with paypal with the appropriate destination e-mail and suggested amount, and then wait for them to return to the game.exe window and choose the "Yes, on my honor, I payed" button to proceed.

The functioning of the purchase menu would be very platform-dependant. The interface for customizing it in custom should make that fact clear. I don't want game authors to mistakenly think they can recieve payments for the Windows version just because they have configured payments for OUYA and Android.

key.der[edit]

Ouya billing requires a key.der file. The docs describe compiling this into your apk file and accessing it as a raw resource. I don't know if this is our only option. I think the best option would be if I can figure out a way to embed it into the rpg file and then load it at runtime.

Ouya Developer ID[edit]

The OuyaFacade object needs to be initialized with a developer ID code. This should not be too hard to do at runtime. I am already initializing the OuyaFacade using a dummy id "00000000-0000-0000-0000-000000000000" just for the OuyaFacade.isRunningOnOUYAHardware() method.

entitlements vs consumables[edit]

There are two kinds of purchaseables, and as far as I can tell, this metaphor extends to other in-app-purchase stores, not just OUYA.

Entitlements are purchases that have a receipt. The app can check to see if they have been purchased already. These are usied for buying the full version of a demo, or unlocking a feature.

Consumables are purchases that can be repeated. The app is responsible for keeping track of these. There is no way of knowing with 100% reliability whether or not (or how many times) the user has purchased this item. This is used for donations, buying items and equipment, buying resources like money or experience.

Purchase info in general.reld[edit]

  • purchase_root - parent node for purchase data
    • stores_by_platform - Parent node for data about which stores are enabled
      • default string - Valid values are "disabled" and "paypal". If this node is blank or missing, "disabled" is implied. This applies to Windows, Mac, Linux, and non-ouya android (Using "paypal" might be a violation of the Google Play Store TOS, I am not sure)
      • ouya string - Valid values are "disabled" and "ouya" (accepting payments from another source such as paypal is a violation of ouya terms of service) If this node is blank or missing, "disabled" is implied
    • ouya - parent node for ouya-specific data
      • developer_id string - OUYA Developer ID. Defaults to "00000000-0000-0000-0000-000000000000" if not specified.
      • key.der string - OUYA key.der file (downloaded from https://devs.ouya.tv/developers/games after you create an entry for your game)
    • products - parent node for purchasable products. Has zero or more prod nodes.
      • prod - contains information about a specific purchasable
        • displayname string - Displayed in the purchase menu in-game
        • description string - Displayed when this product is selected in the purchase menu. Can be several lines of text.
        • repeatable - If this node is present, allow the player to re-purchase the product more than once. (This corresponds to the "consumable" product type for ouya, but you must manually set it, it will not be automatically set for consumable ouya products)
        • already string - This caption will be displayed if you have already purchased the product. If left blank it will default to "Already purchased". You can use the text code ${COUNT} to insert the number of times the product has been purchased.
        • buy_action - parent node for action when a purchase is confirmed.
          • thanks string - Thank-you text that will be displayed when the product is purchased. Default value if left blank will be "Thank you!"
          • tag int - A tag number to be turned on when this purchasable is purchased. For entitlements this will also be turned on when the receipt is checked for an already-purchased item. (should there be a run-time error if this is used on a consumable?)
          • global int - The ID of a global that will be set equal to the number of times that the product has been purchased.
        • ouya - ouya specific data for this product
          • identifier string - a unique string that identifies this purchase. This will be used to query the store server to find price and availability
        • paypal - paypal specific data for this product
          • button_id string - Paypal button ID

Checking for Receipts[edit]

Purchases should be though of on a game-by-game basis, NOT on a save-by-save basis. However, all the practical effects of a purchase matter on a save-by-save basis. Therefore, there are several places where purchase reciept information needs to be updated.

  • When a newgame is started
  • When a savegame is loaded
  • When the purchase menu has been used.

Receipt checking actually happens asynchronously. I think the best way to deal with this is to have three commands one to make the request, one to check if the reply has arrived, and one to retrieve the reply. Something like

DECLARE SUB purchases_request_prices(product_codes as string)
DECLARE FUNCTION purchases_requested_prices_ready() as bool
DECLARE FUNCTION purchases_requested_prices() as string

This would make it pretty easy to display a progress spinner of some kind while waiting for the reply, and to implement a time-out in case the purchase store is not reachable.

This should work out nicely. A person could make a purchase when they have an internet connection, and it will update tags, variables, and items right away. This will be saved in the save-game, so if the person plays later, it won't matter that the receipt-check fails unless they are starting a new game

However, for the case when they are starting a new game while disconnected from the internet, but have already made purchases, it would be nice to be able to cache purchase information locally. This is unfortunately hackable-- but no more so than just hacking the RPG file or RSAV file to get the desired tag/global/item, so I am not really concerned about that angle.

  • purchase_cache - parent node for cached purchases.
    • paypal - parent node for cached purchases from paypal
      • button_id string - the unique identifier for the product
        • count int - the number of times the product has been successfully purchased.
    • ouya - parent node for cached purchases from ouya store
      • identifier string - the unique identifier for the product
        • count int - the number of times the product has been successfully purchased.


A really nice thing about the purchase_cache is that it will provide a way to count the number of times a consumable has been purchased, which is not a feature provided by either the Google Play or the OUYA stores.