Release Notes: (1.2.8)
  • (Google) Fixed an issue that causes In-App Subscription OnPurchaseCompleted event is not being fired.

Integration Guide - Smart In-App Purchasing Plugin

Platforms: Android & iOS
Plugin version: 1.2.8
Apple IAP API version: since iOS 4.0
Google IAB API version: 3
Amazon IAP API version: 1.0.3
Samsung IAP API version: 2

Now In-App Purchasing can't be easier! The all-in-one package works cross stores and platforms! It supports Apple AppStore, Google Play, Amazon AppStore and SamsungApps Store. All you have to do is import a single unity package, and supply a few parameters, build and see IAP working for those stores and on iOS and Android devices! More importantly, the store from where your App is installed will be automatically detected so you don't have to build multiple versions of your App for different App Stores. Now let's look at this detailed integration guide, and follow a few simple steps to get the IAP feature integrated in your App, in a few minutes:

[1] Import the SmartIAPUniversal.unitypackage file to your project;

· >>> For Android platform, click on the menu item of Unity top menu bar: NeatPlug -> SmartIAP -> Patch Android Configuration. This is for generating a valid AndroidManifest.xml or patching the existing file with SmartIAP support.

· NOTE: To integrate SmartIAP, we need to use custom subclass of UnityPlayerActivity to receive onActivityResult call, if you have used another custom activity and have problem getting all neccessary functions working, please contact our support team.


· >>> For iOS platform, click on the menu item of Unity top menu bar: NeatPlug -> SmartIAP -> Patch iOS Configuration. This is for automatically adding iOS SDK frameworks, libraries or patching the Info.plist file (if needed) as long as the Xcode project is generated by Unity.

[3] Find SmartIAPAgent Prefab and SmartIAPListener Prefab in Assets/Standard Assets/NeatPlug/IAP/SmartIAP/Prefabs/, open the first scene of your game, drag & drop those two prefabs into the scene.

[4] Okay, the integration is done here. Now set up your IAP by filling in a few properties of the SmartIAPAgent gameObject which you just dropped in the Hierarchy window. To do this, simply select that gameObject, and look at its properties in the Inspector window, you need to fill in:

   · Store - Select the target store while testing, it should be set to "AutoDetect" before you submit your binary to app stores.

   · Google Play Public Key - The base64 encoded public key you can copy from Google Play publisher account.

   · Samsung Group Id - The Group ID you got from SamsungApps publisher account.

   · Test Mode - Check this if you want to test with testing or unpublished IAP items (Only valid for SamsungApps).

   · Show Spinner When Necessary - Check this if you want a spinner to show up while a transaction is in process (If necessary)

   · Consumable Product Skus - A set of Consumable product IDs you want the plugin to automatically retrieve information for you.

   · NonConsumable Product Skus - A set of Non-Consumable product IDs you want the plugin to automatically retrieve information for you.

   · Subscription Product Skus - A set of Subscription product IDs you want the plugin to automatically retrieve information for you.

   · Samsung Skus Map - A set of samsungItemID-to-Sku map items that enables you to purchase samsung items using same skus as Google's.

   · Verify Receipt From Device - Check this to verify receipt from the user device once the purchase is completed. (Only valid for Apple AppStore)

   · Server Receive Receipt URL - Set a valid URL on your server to enable posting the receipt to your server for verification.

   · Learn more about receipt verification: [Apple AppStore, Google Play, Amazon AppStore, SamsungApps Store]

[5] To deliver your in-app items when a purchase has successfully completed, you need to handle purchase events, to do so:

  Follow the instructions to handle purchase events:

  · Select the dropped SmartIAPListener gameObject, locate the SmartIAPListener.cs script, open it and make some modifications.

  These callbacks are exposed in the script, you can supply your own implementations in them.
Show All   
void OnPurchaseCompleted(SmartIAPReceipt receipt) { ... }
/**
 * Fired when the purchase successfully completed.	
 * 
 * This is where you should deliver the item to the user.
 * 
 * @param receipt
 *           SmartIAPReceipt - An object which contains the purchase information. 
 *                             { sku, purchaseTime, orderId, purchaseToken,
 *                               purchaseState, packageName, developerPayload, data }
 *                             NOTE: "data" is a JSON string that contains the receipt data
 *                             returned from the store, you may want to use it to do your own
 *                             receipt posting if you don't want the plugin to automatically
 *                             do it for you.
 *        
 */
void OnPurchaseCompleted(SmartIAPReceipt receipt)
{
    /// Your code here...   
}
void OnPurchaseFailed(string sku, string err) { ... }
/**
 * Fired when the purchase failed.
 *
 * @param sku
 *           string - IAP item identifier, the Product ID you defined at Google Play's publisher site.
 *
 * @param err
 *           string - The reason for failure.
 */
void OnPurchaseFailed(string sku, string err)
{
    /// Your code here...
}
void OnPurchaseCancelled(string sku) { ... }
/**
 * Fired when the purchase cancelled by the user.
 *
 * @param sku
 *           string - IAP item identifier, the Product ID you defined at Google Play's publisher site.
 */
void OnPurchaseCancelled(string itemId)
{
    /// Your code here...   
}
void OnStoreDetected(SmartIAPStoreType store) { ... }
/**
 * Fired when the store detection completed.
 * 
 * This is an informational event that let you know the auto-detected 
 * source store from where your App is installed.
 * 
 * @param store
 *          SmartIAPStoreType - The detected store type.
 * 
 */
void OnStoreDetected(SmartIAPStoreType store)
{
    /// Your code here...   
}
void OnBillingSupported(bool supported, string response) { ... }
/**
 * Fired when the check for the In-App Billing support is done.
 * 
 * @param supported
 *             bool - true for supported, false for unsupported.
 * 
 * @param response
 *             string - The response code returned from the IAP API.
 *
 */
void OnBillingSupported(bool supported, string response)
{
    /// Your code here...   
}
void OnSubscriptionSupported(bool supported, string response) { ... }
/**
 * Fired when the check for subcription support is done.
 *
 * @param supported
 *             bool - true for supported, false for unsupported.
 * 
 * @param response
 *             string - The response code returned from Google IAB API.
 */
void OnSubscriptionSupported(bool supported, string response)
{
    /// Your code here...
}
void OnItemDataReady() { ... }
/**
 * Fired when the item data is ready to query.
 * Do your item query then if you need.
 */
void OnItemDataReady()
{
    /// Your code here...
}
void OnOwnedItemReported(string sku) { ... }
/**
 * Fired when receiving an owned item report event.
 * 
 * This indicates that the item type is "NonConsumable" and the user has already 
 * owned the item. By default the plugin gets notified with the event every time your 
 * app launches, it is suggested that you should redeliver the item to the user here 
 * if the locally saved data record cannot be found. (Probably the user cleared the 
 * PlayerPrefs data or a new device is being used) 
 * 
 * @param sku
 *           string - IAP item identifier, the sku you defined at Google Play's publisher site.	
 */
void OnOwnedItemReported(string sku)
{
    /// Your code here...
}
void OnItemAlreadyOwned(string sku) { ... }
/**
 * Fired if the user has already owned this NonConsumable item when a corresponding
 * purchase is attempted.
 *
 * This indicates that the item type is "NonConsumable" and the user has already owned
 * the item. This event is only triggered in case you ignored the default automatic
 * owned item reporting happened in OnOwnedItemReported() at app launches, but 
 * you are not suggested to do so since requiring the user who has already purchased 
 * the NonConsumable item to perform the purchase again, and tell the user "You have already
 * owned the item", is obviously causing confusion.
 *
 * In most cases you should only play with the "OnOwnedItemReported()" event.
 * But you can use this where you really need it to be that way.
 *
 * @param sku
 *           string - IAP item identifier, the sku you defined at Google Play's publisher site.	
 */
void OnItemAlreadyOwned(string sku)
{
    /// Your code here...
}
void OnReceiptPosted(string response) { ... }
/**
 * Fired when the receipt is successfully posted to server.
 * 
 * @param response
 *           string - The response from your server.
 * 	
 */
void OnReceiptPosted(string response)
{
    /// Your code here...
}
void OnFailedToPostReceipt(string err) { ... }
/**
 * Fired when the receipt data failed to be posted.
 * 
 * @param err
 *           string - The error string.	
 * 	 
 */
void OnFailedToPostReceipt(string err)
{
    /// Your code here...
}

[5] Call SmartIAP.Instance().Purchase(string sku) function in your code to initiate a purchase request.

  Initiate a purchase request:

  · SmartIAP.Instance().Purchase(string sku);

  NOTE: If you don't supply Consumable Product Skus and Nonconsumable Product Skus in the properties of SmartIAPAgent gameObject, you

            need to call SmartIAP.Instance().Initialize(...) to provide that information to plugin.

  There are useful public methods that SmartIAP provides, to use them, simply call SmartIAP.Instance().methodName().
Show All   
public void Purchase(string sku, string payload = null, Dictionary<string, string> extras = null)
/**
 * Initiate an in-app purchase request to the plugin.
 * 
 * @param sku
 *           string - IAP item identifier, the Product ID you defined at IAP Provider's publisher site.
 * 	
 * 
 * @param payload
 *          string -  a developer payload that is associated with a given purchase, 
 *          if null, no payload is sent.Developer Payload is a developer-specified 
 *          string that contains supplemental information about a purchase.
 *
 * @param extras
 *          Dictionary - The extra parameters you want to post the receipt along with. 
 *                       extras is particularly useful when you want to send your customized
 *                       data to your server along with the receipt for server-to-server
 *                       verification. For instance, you can put in the user ID or device ID
 *                       for further associating the purchase with the user.
 */
public void Purchase(string sku, string payload = null, Dictionary<string, string> extras = null)
public void GetItemInfo(string sku)
/**
 * Get the specified item information.
 * 
 * The item information is retrieved at app launch and it is cached in plugin for better performance.
 * You should always call this function in SmartIAPListener::OnItemDataReady() to make sure the data
 * has been ready for you to query.
 * 
 * @param sku
 * 			string - IAP item identifier, the sku you defined at IAP Provider's publisher site.
 * 
 * @return 
 * 			SmartIAPItem - A Google IAB Item which contains { title, description, price, type }
 */
public void GetItemInfo(string sku)
public void GetItemPrice(string sku)
/**
 * Get the price of specified item.
 * 
 * The item information is retrieved at app launch and it is cached in plugin for better performance.
 * You should always call this function in SmartIAPListener::OnItemDataReady() to make sure the data
 * has been ready for you to query.
 * 
 * @param sku
 * 			string - IAP item identifier, the sku you defined at IAP Provider's publisher site.
 * 
 * @return 
 * 			float - The price of the item
 */
public void GetItemPrice(string sku)
public void RestoreCompletedTransactions()
/**
 * Restore completed transactions.
 * 
 * This is useful when your locally saved purchase records are somehow wiped out on the device,
 * in this case you may want to redeliver the purchased Non-consumable products if any.
 *
 * NOTE: (Android) You don't need to call this function on Android, the historical purchases will be
 * fetched every time your App starts.
 * 
 * NOTE: (iOS) Since Apple requires the user to authenticate before restoring completed transactions,
 * this task cannot be done automatically when App starts. You would need to add a button named
 * "Restore Completed Transactions", to provide the user with a way to restore his / her original 
 * purchases.
 * 
 */
public void RestoreCompletedTransactions()
public void RefreshItems(string[] skusConsumable, string[] skusNonConsumable, ... )
/**
 * Refresh the items information.	
 * 
 * @param skusConsumable
 *              string[] - A set of Consumable product IDs you want the plugin to automatically 
 *                         retrieve information for you.
 * 
 * @param skusNonConsumable
 *              string[] - A set of Non-consumable product IDs you want the plugin to automatically 
 *                         retrieve information for you.
 * 
 * @param skusSubscription
 *              string[] - A set of Subscription product IDs you want the plugin to automatically 
 *                         retrieve information for you.
 * 
 * @param samsungSkusMap
 *              string[] - A set of samsungItemID-to-Sku map, to leave your "Purchase()" code unchanged while
 *                         handling Samsung item purchases. As you may know, samsung has a different naming
 *                         convention - a numeric ID for each item but not the form that Google, Amazon and 
 *                         Apple provides. You can fill the "map" in one item of the filed, for instance:
 * 	                       "000001000018:com.your.item.sku". (Note the ":" is the delimiter)
 */
public void RefreshItems(string[] skusConsumable, string[] skusNonConsumable, 
	                 string[] skusSubscription, string[] samsungSkusMap)

[6] Test your In-App Purchasing functionality. Before you can test, you should set up the corresponding Product IDs at each IAP Provider's publisher site. Also it would be helpful for you to address issues if you take a look at the logcat output (Android) or xcode debug console (iOS) to find the debug / error / warning messages.

· Testing for Amazon Appstore:

To test your Amazon IAP functions, you need to download the test tool AmazonSDKTester.zip. Unzip it, there are two files in the package: amazon.sdktester.json and AmazonSDKTester.apk. Open amazon.sdktester.json, read and modify the test sample data (Or you can download a working App-specific json file from Amazon Developer site, click on one of your Apps, and then click on "In-App Items", finally you can click on "JSON Data File" button on the right top of the page, to download that file), and then put it in the SDCARD root of your Android device.; Install AmazonSDKTester.apk on your device using adb, and run the apk on your device. Now it is time to run your own app and see if your IAP feature works!

For further detailed information, please refer to https://developer.amazon.com/sdk/in-app-purchasing/documentation/testing-iap.html


· Testing for Google Play:

To test your Google Play IAP functions, you need to add at least one testing account to your Google Play publisher account.

For further detailed information, please refer to http://developer.android.com/google/play/billing/billing_testing.html


· Testing for Apple AppStore:

To test your Apple IAP functions, you need to create at least one testing account to your iTunesConnect account.

Learn more, please refer to Apple Developer Guide


· Testing for Samsung Apps:

To test your Samsung IAP functions, you need to set the "Test Mode" property of SmartIAPAgent to true.

IMPORTANT: Don't forget to turn off test mode before you build your release binary for appstore submission.

[EOF] If you encounter any problems while integrating the plugin, please do not hesitate to shoot us an email at support@neatplug.com, we will be helping you as soon as possible.Thanks for choosing NeatPlug solutions!