The Purchase Library and API
The MoSync Purchase C++ Library provides a set of classes and methods (in the IAP namespace) for purchasing products and handling user’s transaction information from within your own application. The library is built on top of the MoSync Purchase C API which provides a comprehensive set of functions for managing purchases.
Tutorials and Examples
For a detailed tutorial that shows how to create a cross-platform mobile application using the Purchase C++ Library and Purchase C API, see: In-App Purchase tutorial.
The MoSync SDK includes a fully commented example application, InAppPurchaseExample, that makes use of the the Purchase Library and API.
Platform Implementations and Variations
In-app purchase mechanisms vary from platform to platform. Their implementation is dependent not only on the device's software but also on the platform vendor's billing system.
The purchase type determines how the shops handle and track purchases.
Purchase types for Apple iTunes
- Consumable -- for products that must be purchased each time the user needs that item.
- Non-consumable -- for products that only need to be purchased once by the user and are available to all devices registered to a user.
- Subscriptions (auto-renewable, free, and non-renewing) -- for time-limited or periodically reoccurring content, for example newspaper or magazine content and club memberships.
Purchase types for Google Play
- "Managed per user account" -- products that can be purchased only once per user account on Google Play.
- "Unmanaged" -- products that do not have their transaction information stored on Google Play. These products are consumed within your application and are usually purchased multiple times.
Google Play/Android specifics
- To ensure the integrity of the transaction information sent to your application, Google Play uses the private key associated with your publisher account. So, to be able to perform any purchase request, PurchaseManager::setPublicKey() needs to have been previously set.
- On Android, refunds can only be initiated by the Google merchant that published the applications. Therefore, the user cannot request a refund, but only wait for refund events from the server in the PurchaseManagerListener::productRefunded() callback.
- Android does not support the purchase of a product with a quantity greater than 1. Therefore, Purchase::requestPurchase(quantity) will always have the quantity=1 on Android platform.
Google Play/Android limitations
- Google in-app billing can be implemented only in applications that you publish through Google Play.
- You cannot use Android emulator (or MoSync's MoRE emulator) to test in-app purchases; you must install your application on a device to test it.
- Make sure that your application is signed with the release key (i.e. build it in the MoSync IDE in Release mode) before testing in-app purchasing.
- You must have a Google Checkout Merchant account to use Google Play in-app purchase.
- If your device is running Android 3.0, in-app purchase requires version 5.0.12 (or higher) of the MyApps application. If your device is running any other version of Android, in-app purchase requires version 2.3.4 (or higher) of the Google Play application.
- An application can use in-app purchase only if the device is running Android 1.6 (API level 4) or higher. So remember to call PurchaseManager::checkPurchaseSupported() at the application entry point so that you can enable/disable certain UI features related to in-app purchase.
- For more information about in-app purchase requirements, see In-App Billing Availability and Policies.
Apple iTunes/iOS specifics
- To verify the receipt of a purchased item on iOS, you must set PurchaseManager::maPurchaseSetStoreURL() previously to any purchase request.
- iOS supports the purchase of a product with a quantity greater than 1.
- For a completed purchase, there are some receipt fields that are available only on iOS, such as:
- Receipt::getBID() the bundle identifier for the application.
- Receipt::getVersionExternalID() the arbitrary number that uniquely identifies a revision of your application.
- Receipt::getBVRS() the version number of the application.
- Receipt::getPrice() the cost of the product in the local currency.
- Receipt::getTile() the localized product title.
- Receipt::getDescription() the localized product description.
Apple iTunes/iOS limitations
- In app purchase does not work on the iOS simulator, so the testing must be done on the device.
- In app purchase requires iOS 3.0 or later.
- The developer must have an iTunes account in order to create products that will be later available for purchasing.
- The developer must sign the application with a valid iOS developer certificate that has in app purchase enabled.
Purchase C++ Library Classes and Methods
For a list of the platforms supported by the Purchase C++ Library, see Feature/Platform Support.
Purchases are encapsulated in objects of the Purchase class. The Purchase wraps a product that can be bought along with all the details of the transaction (such as the Receipt).
The main methods of the Purchase class include:
- Purchase() — the constructor, the minimum required to create a purchase object. Requires the productId that identifies the product and a listener.
- getProductId() — get the productId that identifies the product.
- requestPurchase() — request the user to purchase a product. The quantity parameter is available only on iOS.
- verifyReceipt() — verify if the receipt came from Apple App Store / Google Play.
- addPurchaseListener() — add an event listener for this purchase. Keep in mind that when a Purchase object is created it's parent is automatically set as an event listener.
Receipts are encapsulated in objects of the Receipt class: A Receipt wraps the details of a purchase. The main methods of this class include:
- getProductID() — Get the product id of the item that was purchased.
- getTransactionID() — Get the transaction identifier of the item that has been purchased.
- getTransactionDate() — Get the transaction date and time of the item that has been purchased.
- getAppID() — Get a string that the App Store/GooglePlay uses to uniquely identify the application that created the payment transaction. If your server supports multiple applications, you can use this value to differentiate between them.
- getVersionExternalID — Get the arbitrary number that uniquely identifies a revision of your application.
- getBID() — Get the bundle identifier for the application.
- getBVRS() — Get the version number of the application.
- getPrice() — The cost of the product in the local currency.
- getTitle() — Get the localized product title.
- getDescription() — Get the localized product description.
The PurchaseManager class manages purchase-related events and dispatches them to the target products. It is a singleton class. Its main methods include:
- checkPurchaseSupported() — check if in-app purchase is supported/enabled on a device. This method must be called from the start, so specific UI components related to purchase can be enabled/disabled.
- setPublicKey() — set your Google Play public key to the application to verify the signature of the transaction information that is returned from Google Play.
- setStoreURL() — set the store URL used for verifying the receipt on iOS platform.
- restoreTransactions() — restore transactions that were previously finished so that you can process them again.
The PurchaseListener can be used to listen for a specific purchase’s events. The PurchaseListener class contains the following virtual methods:
- productValid() notifies that the product has been validated and can be purchased.
- productInvalid() notifies that the product is not valid.
- requestInProgress() notifies that the transaction has been received by the server.
- requestCompleted() notifies that the transaction has been successfully processed.
- requestFailed() notifies that the transaction has failed.
- receiptValid() notifies that the transaction has been validated by the server.
- receiptInvalid() notifies that the transaction is not valid on the server.
- receiptError() notifies that an error occurred while verifying the receipt.
The PurchaseManagerListener can be used to listen for restored or refunded products. The class contains the following virtual methods:
- purchaseRestored() notifies that a purchase has been restored.
- purchaseRestoreError() notifies that restoreTransactions() has failed.
- purchaseRefunded() notifies that a purchase has been refunded.
Purchase C API IOCTLs
The Purchase C++ Library described above makes use of the MoSync Purchase C API which contains a number of lower-level C IOCTLs. For a list of the platforms supported by the Purchase C API, see Feature/Platform Support.
- maPurchaseSupported() — check if in-app purchase is supported/enabled on a device.
- maPurchaseCreate() — create a product object asynchronously.
- maPurchaseSetPublicKey() — set the Google Play public key to the application, enabling the application to verify the signature of the transaction information that is returned from Google Play. Must be set in order to be able to request purchases.
- maPurchaseRequest() — request the user to purchase a product. The system will handle the actual purchase process.
- maPurchaseVerifyReceipt() — verify if the receipt came from Apple App Store / Google Play. Make sure that the product is purchased before calling this syscall.
- maPurchaseGetField() — get a field value contained by the receipt. Make sure that the given product has a valid receipt. Call the maPurchaseVerifyReceipt() syscall and wait for a #MA_PURCHASE_EVENT_RECEIPT_VALID purchase event type.
- maPurchaseSetStoreURL() — set the store url used for verifying the receipt on iOS platform.
- maPurchaseRestoreTransactions() — restore transactions that were previously finished so that you can process them again. For example, your application would use this to allow a user to unlock previously purchased content onto a new device.
- maPurchaseGetName() — get product id using a product handle.
- maPurchaseDestroy() — destroy a product object.
More information on these functions can be found in the MoSync C/C++ API Reference.
A complete screencast for an example application can be found here, on our YouTube MoSync Dev Channel.