MetroMail Responsive Email Template
 
 
icon 2    April 4th, 2014
 
 
 
UPDATES & NEWS FOR THE LIVECODE COMMUNITY
 
 
 
 
 
 
 
Article 4: Amazon Purchasing
 
 

2. Setting up a stack to access in-app purchases

 

In order to use the in-app purchase with LiveCode, we must first create it in the Amazon Appstore Developer Portal. From the front page of Amazon Appstore Developer Portal, go to Dashboard, select the app for which you wish to create an in-app purchase, click "In-App Items", and click "Add a consumable"/ "Add an Entitlement"/ "Add a Subscription", depending on the type of the product you want to add. From there, follow the instructions to create the type of in-app purchase you wish to use. In the stack for this lesson, we are using a consumable, a non-consumable (or an entitlement, according to Amazon's terminology and a subscription purchase.

2. Setting up a stack to access in-app purchases

 

First create three buttons. One button for consumable, one button for non-consumable and one button for subscription. Then add code that allows us to interface with the Amazon Appstore and request the in-app purchases for download.

 

To our consumable purchase button, add the following code:

 

on mouseUp

mobileStoreEnablePurchaseUpdates

mobileStoreSetProductType "com.runrev.sampleapp.consumable", "inapp"

mobileStoreMakePurchase "com.runrev.sampleapp.consumable", "1", "This belongs to me"

end mouseUp

 

Add the following to our non-consumable and subscription purchase buttons:

 

on mouseUp

mobileStoreEnablePurchaseUpdates

mobileStoreSetProductType "com.runrev.sampleapp.nonconsumable", "inapp"

mobileStoreMakePurchase "com.runrev.sampleapp.nonconsumable", "1", "This belongs to me"

end mouseUp

 

on mouseUp

mobileStoreEnablePurchaseUpdates

mobileStoreSetProductType "com.runrev.sampleapp.sub.month", "subs"

mobileStoreMakePurchase "com.runrev.sampleapp.sub.month", "1", "This belongs to me"

end mouseUp

 

Finally, add the following code to the stack script:

 

on purchaseStateUpdate pPurchaseID, pProductID, pState

switch pState

case "paymentReceived"

answer "payment received!"

offerPurchasedProduct pProductID

mobileStoreConfirmPurchase pProductID

mobileStoreDisablePurchaseUpdates

break

case "error"

answer "Error occured during purchase handling:" & return & return & mobilePurchaseError(pPurchaseID)

mobileStoreDisablePurchaseUpdates

break

case "invalidSKU"

answer "Invalid SKU."

mobileStoreDisablePurchaseUpdates

break

case "alreadyEntitled"

answer "Already Owned."

mobileStoreDisablePurchaseUpdates

break

case "restored"

answer "Restored!"

offerPurchasedProduct pProductID

mobileStoreConfirmPurchase pProductID

mobileStoreDisablePurchaseUpdates

break

case "cancelled"

answer "Purchase Cancelled:" && pProductID

mobileStoreDisablePurchaseUpdates

break

end switch

end purchaseStateUpdate

on offerPurchasedProduct pProductID

if pProductID is "com.runrev.sampleapp.consumable" then

set the cConsumablesCount of this stack to (the cConsumablesCount of this stack + 1)

else if pProductID is "com.runrev.sampleapp.nonconsumable" then

set the cNonConsumablePurchased of this stack to true

else if pProductID is "com.runrev.sampleapp.sub.month" then

set the cSubPurchased of this stack to true

else if pProductID is "com.runrev.sampleapp.sub" then

set the cSubPurchased of this stack to true

end if

end offerPurchasedProduct

 

The mobileStoreEnablePurchaseUpdates command allows you to monitor the status of each in-app purchase request, using the built-in message, purchaseStateUpdate. This is handled to check the status of the in-app purchase.

 

The mobileStoreSetProductType command is used to set the type of the in-app purchase. The type can either be "inapp", for consumable and non-consumable items, or "subs" for subscription items. This distinction is not always necessary, since it is only used by the underlying Google API for in-app purchases, because it uses different methods, depending on the item type. However, it is recommended that you always use this command, even for non-Google stores. The mobileStoreSetProductType command is used with the identifier and the type of the in-app purchase we are requesting. These values must match the identifier and the type of an in-app purchase that has been set up in the Amazon Appstore Developer Portal for the app.

 

The mobileStoreMakePurchase command is then used with three parameters, denoting the in-app purchase identifier we are requesting, the requested quantity of the item and the developer payload. The quantity should always be "1" for non-iOS apps. The developer payload is a string that contains some extra information about the order. This command sends the request and begins the purchasing process. The purchaseStateUpdate message is then generated as the purchasing process takes place. This is sent with three parameters denoting the product identifier, the purchase identifier and the state of the specific purchase that the message is regarding. In the handler, the state of the purchase is checked using the parameter pState. Here we take action if it returns paymentReceived, indicating that payment for the purchase was received, or restored, indicating that the restoration request was successful. In all other cases, we print a message to the screen giving details on what is happening.

 

In case of an error, mobileStorePurchaseError can be used with the purchase ID to find the details of the error, and then use the mobileStoreDisablePurchaseUpdates command to indicate that the purchase process is complete. This is not essential in all circumstances, but is good practice. mobileStoreDisablePurchaseUpdates is used in cases where the item is already owned by the user, or there is no item with the specified identifier in the store listing, or the user cancels the purchase. In case of payment being received, or the purchase being restored, the app can take action to finalize the purchase or the restoration process. This app permits multiple in-app purchases and we use the pProductID parameter with offerPurchasedProducts to find identify which in-app purchase is being being processed. We can then take appropriate action for the in-app purchase that is being purchased or restored, and use the mobileStoreConfirmPurchase command to confirm to Amazon that payment has been received, finalizing the in-app purchase process on the Amazon Appstore's side.

The bundle identifier that you create the standalone application with, as specified in the standalone application settings, must match the bundle identifier tied to the in-app purchases in Amazon Appstore Developer Portal.

3. Handling in-app purchases once they have been purchased

3. Handling in-app purchases once they have been purchased

The above step handles a purchase. In this app, we set a custom property to indicate to the app that the purchase has been made. With the non-consumable and the subscription purchase we set a custom property to true, but with the consumable in-app purchase, the user can purchase it as many times as they like. We increment a custom property to indicate how many times a purchase has been made.

 

We can now use these custom properties to take action based on the in-app purchases the user makes. Handling the in-app purchase process records the purchases with Amazon and transfers money. For this app, we are using the non-consumable purchase to change the background color of the stack and change the text of a field. The consumable purchase is used to make a graphic flash on and off briefly. The subscription purchase is used to change the color of a button.

For the non-consumable and the subscription purchase, we can use a setProp to implement this:

 

setProp cNonConsumablePurchased pValue

set the cNonConsumablePurchased of this stack to pValue

if pValue then

set the backColor of this stack to 0,255,0

put "PURCHASED" into fld "purchased"

else

set the backColor of this stack to 255,255,255

end if

end cNonConsumablePurchased

setProp cSubPurchased pValue

set the cSubPurchased of this stack to pValue

if pValue then

set the backgroundColor of button "sub" to 0,0,255

end if

end cSubPurchased

 

For the consumable purchase, we want the user to be able to activate it whenever they want rather than immediately. For this we use two handlers, a setProp and a button. The setProp indicates to the user how many consumable purchases they have remaining, and the button is used to consume and activate the consumable.

 

Our setProp will look like this:

setProp cConsumablesCount pValue

set the cConsumablesCount of this stack to pValue

put pValue into fld "consumablescount"

end cConsumablesCount

And our button should have this code:

on mouseUp

mobileStoreConsumePurchase("com.runrev.sampleapp.consumable")

if the cConsumablesCount of this stack > 0 then

set the cConsumablesCount of this stack to (the cConsumablesCount of this stack - 1)

repeat with x = 1 to 10

wait 100 millisecs with messages

if the backcolor of grc "consumablegrc" is 255,255,255 then

set the backcolor of grc "consumablegrc" to 0,0,255

else

set the backcolor of grc "consumablegrc" to 255,255,255

end if

end repeat

set the backcolor of grc "consumablegrc" to 255,255,255

else

answer "you need to purchase a consumable first!"

end if

end mouseUp

 

This 'uses up' a consumable each time the user clicks the button, and only lets them carry out the action we want if they have purchased a consumable in the first place. The mobileStoreConsumePurchase command is called with the consumable product identifier. This command removes the consumable item from the user's inventory, so that it will not be contained in the list returned by mobileStorePurchasedProducts function.

4. Making purchases persistent

4. Making purchases persistent

Our custom properties revert to whatever values they are at build-time, each time the app is closed. One could therefore assume that custom properties have to be saved explicitly, allowing us to re-load them every time the app is opened. This is not the case for non-consumable and subscription products. The app is no longer responsible to retaining what the user has bought. All the purchased items of this type (non-consumables and subscriptions can be restored, not only in the particular device where the app was installed, but in every device the user owns. This can be done using a "restore" button.

 

Note : As a general rule, consumable products cannot be restored. Therefore, the app should have a mechanism to "remember" the consumable purchases of the user. One simple way of doing this is simply to add some code to our setProps which writes the value of the custom property to a location outside of the .app bundle. For example, this could be an SQLite Database or a text file. In this case, we write a text file to the documents folder. We add the following handlers to our stack script and call them at the end of our setProps for each custom property as follows:

 

on saveConsumablesCount

  put the cConsumablesCount of this stack into url("file:" & specialFolderPath("documents" &"/consumablescount.txt")

end saveConsumablesCount

setProp cConsumablesCount pValue

set the cConsumablesCount of this stack to pValue

  put pValue into fld "consumablescount"

  saveConsumablesCount

end cConsumablesCount

 

And we then simply load these values back in each time we open the app, by adding the following code:

 

on loadConsumablesCount

put (specialFolderPath("documents" & "/consumablescount.txt" into tPath

if there is a file tPath then

set the cConsumablesCount of this stack to url("file:" & tPath)

end if

end loadConsumablesCount

on preOpenStack

loadConsumablesCount

end preOpenStack

 

For restoring non-consumable or subscription items, we could use a restore button. It should have this code:

 

on mouseUp

mobileStoreEnablePurchaseUpdates

mobileStoreRestorePurchases

end mouseUp

 

Here, mobileStoreRestorePurchases command queries the user's inventory of purchased items, and returns them in the purchaseStateUpdate pPurchaseID, pProductID, pState message. The purchaseStateUpdate message is called as many times as the number of items the user owns, each time with a different pPurchaseID and pProductID, but always with the same pState : restored". In that case, the flow should be exactly the same as when the user successfully purchases the product for the very first time, with the difference that this time no actual payment occurs!

 

In other words, what mobileStoreRestorePurchases does, is simulating a successful purchase flow without charging the user's credit card for all the items that the user has already purchased. The underlying Amazon in-app purchasing API remembers what the user has bought, and does not allow them to buy an item that they already own, even if they do not call mobileStoreRestorePurchases. To make this clearer, imagine the following scenario for our example app:

 

1 . User launches the app for the very first time.

2 . They click on the non-consumable button, and send a purchase request to the Amazon Appstore for the non-consumable item.

3. The Amazon Appstore responds and asks for the user's password. The user types their password.

4 . The Amazon Appstore responds that the purchase is successful.

5 . purchaseStateUpdate message is called with parameters ("1", "nonconsumable_product_name", "paymentReceived").

6 . The app provides the user with the purchased item, i.e. the background becomes green.

 

Now, if the user exits and re-launches the app, the background is not green. But if they select to purchase the non-consumable itemagain, they get an "Already Owned" message. The purchaseStateUpdate message is called with parameters ("1", "nonconsumable_product_name", "alreadyEntitled"). If they want to get the purchased item, turning the background green, all they need to do is click on the "restore" button, which calls mobileStoreRestorePurchases.

Note : When you set up your subscription products in the Developer Portal, you maybe noticed that you were asked twice to specify the product identifier (or the SKU, according to Amazon's terminology). The first SKU is called parent SKU, and is the same for all different (if any subscription periods. This could be something of the form com.yourcompany.yourapp.sub. The second time that you are asked to specify the SKU, you have to use a different one, which is tied to the particular duration of the subscription you just added. This could be something of the form com.yourcompany.yourapp.sub.month. This SKU is called child SKU. You can add more child SKUs (i.e com.yourcompany.yourapp.sub.4months for the same subscription item, that have a different subscription period. In the FAQ of Amazon developers website, we can see :

 

Q: Why do I get a different SKU back when I initiate a purchase for my subscription SKU?

A: A subscription is comprised of a non-buyable parent SKU and one or more child term SKUs. This setup prevents users from purchasing multiple subscriptions of the same product. The non-buyable parent represents the product being purchased and is the SKU returned in the purchase response. The child SKUs represent the different subscription terms and are used to initiate the purchase. Subscription terms and charges are handled by Amazon and your app only needs to check whether a subscription is valid.

 

This means that in the purchaseStateUpdate message we have to handle both SKUs (parent and child SKU : The child SKU is returned with purchaseStateUpdate message when making a subscription purchase for the very first time, and the parent SKU is returned when we restore previous purchases.

5. Testing purchases

5. Testing purchases

For Amazon API, you need two things to test your in-app purchases:

 

1. The Amazon SDK Tester. This is a developer tool that allows users of the Amazon Mobile App SDK (ie the Amazon API that is used for in-app purchases to test their implementation in a production-like environment before submitting it to Amazon for publication. This will allow developers to construct test cases that cover all responses generated by the Amazon Mobile App SDK APIs, and give them confidence their apps will be published and run correctly. You must install it in the Android device that will be used for testing.

2. A .json text file that will contain the IAP item information used to respond to IAP API calls. This file should be written to the "mnt/sdcard" directory on the device that will be hosting the SDK Tester.

 

You can find very detailed information on how to use the Amazon SDK Tester in the official Amazon website for developers :

 

https://developer.amazon.com/appsandservices/apis/earn/in-app-purchasing/docs/testing-iap

LiveCode Lessons

 

This article comes from our extensive Lessons repository, see more here.

 
 
section image
 
Community Manager
 
7.0 is not just Unicode, find out what else there is to be excited about
 
read more
 
 
section image
 
Bag a Bug for LC
 
How to handle the influx of new releases arriving on your desktop
 
read more
 
 
section image
 
Speaker Sessions
 
Success story: from drawing board to chart topper in 3 months flat.
 
read more
 
 
section image
 
Amazon Purchasing
 
This lesson describes how to build a simple web page navigator for mobile
 
read more
 
 
 
Join Us in San Diego
 

Early Bird Pricing Still Available!

 
download
 
 
Featured Extensions
 
 
FMPro Migrator
 
Generate a full-featured LiveCode DB front-end from FileMaker Pro and Microsoft Access database files.
 
read more
 
 
 
Arcade Sounds Pack
 
What's a game without sound? Add this handy library to your app for a full range of fun noises in various formats
 
read more
 
Connect With Us
 
 
RunRev © Copyright 2013 . All Rights Reserved
 
 
 
RunRev © Copyright 2013 . All Rights Reserved