The many states of IAP - a visual guide

ArmellineArmelline Member, PRO Posts: 5,331

I've spent a lot of time in the past few weeks exploring the many intricacies of the new IAP system. At first, I spent a lot of time using words like "stupid" and "ridiculous" and various others I cannot type on a family friendly forum. The new system seems stupidly obtuse and prone to failure, and seemed to provide very little valuable feedback.

After taking the time to get my head around it, though, I realised just how valuable this new system is. It provides massive amounts more flexibility than was present before. In fact, whereas before we had two feedback states - purchase succeeded and purchase failed - now we have almost complete control over our buttons.

I've seen various IAP tutorials and templates released and they've provided a ton of really valuable information, but they haven't really got into just how powerful this new system is. At almost no point now should the user not be able to be given accurate and up-to-date information about what's happening with their purchases, from the moment they open the shop to the moment the last item has been purchased.

Apple are becoming increasingly demanding regarding in-app purchase. They will reject your app if you don't have a restore button. (This has been true for a while, but there are app out that don't have one and Apple let them pass... they won't let you pass without one.) They will reject your app if the user presses a button and there isn't an immediate result.

What should happen when the user presses a button? You might be inclined to answer "You request the purchase!" You'd be wrong :D What should happen is that the button should change to reflect a purchase is being attempted. When the purchase succeeds or fails, the button should change to reflect that. (Or a popup should display - but the beauty of this new system is you can give all the feedback you need to via the button images.) Other buttons should change to reflect the purchase state of a purchase attempt too.

I'm working on a free tutorial template that will walk through all this in excruciating detail, but for now I want to share a "flow chart" type thing with you that looks at the possible states. This is assuming one non-consumable purchase available, via a single button, in addition to a restore button. You'll probably be surprised by how many possible states you need to account for :D I'm still working on this, so this flow chart may well become even bigger as I identify new possible states!

Click the image to enlarge!

I'll post once the tutorial template is ready, but for now enjoy thinking about all the possible states you need to account for! If the GS team want I'd be happy to do a presentation at one of the meet-ups to walk people through exactly what this image means, and how to implement all of this into their games.

«1

Comments

  • lycettebroslycettebros Member, PRO Posts: 1,598
  • colandercolander Member Posts: 1,610

    There is so much to consider it can bend your mind. Something to also look at is the "pending" state which it can stay in for a while for example if kids are waiting for approval from their parents.

  • ArmellineArmelline Member, PRO Posts: 5,331

    @colander said:
    There is so much to consider it can bend your mind. Something to also look at is the "pending" state which it can stay in for a while for example if kids are waiting for approval from their parents.

    Don't worry, I've got that covered in there :D

  • The_Gamesalad_GuruThe_Gamesalad_Guru Member Posts: 9,922

    Yes anytime you do a new system like this it's a it more complex but with access to deeper features and control over those features by nature requires you to now build that out. This is very true for multiplayer. The logic is extensive almost mind bending as there is so much one needs to consider when mapping out the code. You have to think both forward user one and reverse user two not to mention if you have 8 players in the mix. Getting things crossed up can happen fast. The more power features are added the more complex the software becomes. My point? Get used to having to spend more time wrapping your head around stuff. Some things just can't be drag and drop.

  • SocksSocks London, UK.Member Posts: 12,822
    edited November 2014

    @Armelline said:
    . . . for now I want to share a "flow chart" type thing with you that looks at the possible states . . .

    Excellent stuff, genuinely useful information, and great chart too, this should be stickied somewhere.

    But you did miss out one option . . .

  • ArmellineArmelline Member, PRO Posts: 5,331

    @Socks said:
    But you did miss out one option . . .

    Ah dammit, I knew I'd missed something! Will add it to the next version!

    The main area we don't have valuable feedback is when the user requests a restore. We can tell if the restore succeeds (something changes in the table) but we have no way of distinguishing between "Restore failed" and "There was nothing to restore".

  • colandercolander Member Posts: 1,610

    I have one I haven't been able to solve regarding a bundle Buy Item purchases and Restore IAP. It is bedtime here so I will write it out in the morning.

  • colandercolander Member Posts: 1,610

    This is not going to be easy to follow but I will do my best to explain it.

    First let me tell you why I have set it up the way I have. Putting Request Purchase Data outside a rule at the start of a game or in a purchase menu is fine it will get the data for the PurchaseTable and for State in column 5 it puts "unpurchased". It was recommended Restore Items run next outside of a rule to change the state to "purchased" for any item the player had previously purchased or "pending:" for any purchases not yet completed.

    I do not like having the Restore Item action outside of a button because it will ask the player to login if they are not currently logged in. That is not ideal and will freak some people out thinking they will somehow be charged for something if they log in. Much better to have the logon request when a button is pressed.

    I put the Restore Purchases action in a Restore IAP button and use the Buy Item action in a Buy button. Both will log a user in if they are not already logged in and more importantly the user expects it. I run a parallel IAP system to handle all purchases for the game so I don't rely on Restore Items to run every time and activate any purchases. If a user reinstalls the game and if for any reason doesn't restore their IAP's and presses a Buy button the stores will handle it and they get it at no cost.

    This all works fine unless you have a bundled purchase/s. If a user had previously bought items singularly and after reinstalling their game pressed a bundled buy button they will be charged for it and visa versa. Some might think great I get paid twice apart from the fact they are ripping their customers off Apple might pull your app from sale while you fix it, you could get bad reviews, etc.

    This means Restore Items needs to go in every buy button and run before Buy Item to prevent the user making an inadvertent purchase. The problem is Restore Item doesn't let you know when it has finished running and that is a problem for the rest of the purchase routine.

    Request Purchase Data puts "unpurchased" in column 5 when it runs then Restore Item will only change it to purchased if an item was purchased otherwise it overwrites "unpurchased" or "pending" if it is still processing it. So if there were no previous purchases you wouldn't know when it had finished running because nothing in the table changed and Restore Items doesn't return anything to let you know it has finished.

    I got around this in the Buy button by using a Change Table action to delete the data in column 5 in the PurchaseTable for the relevant items then running Restore Item in a timer set to "After 0.03 seconds (1 code cycle)" to make sure Change Table action had time to clear the data out of the table. Restore Item will then update the state in column 5 of the PurchaseTable from a empty cell to "unpurchased", "pending" or "purchased". I now know Restore Item has finished running and I can use the three different states to run the rest of the purchase routine.

    This is an enormously complex system compared to the old one but as @Armelline said it has its advantages. Hope this is helpful to others who provide bundled purchases.

  • RondoRocketRondoRocket Member Posts: 411

    Thanks for sharing! I just implemented IAP into my game so this is great info to have so I can double check and make sure I implemented everything correctly. I like the idea about the buy button changing to represent an attempt at a purchase is occurring.

  • ArmellineArmelline Member, PRO Posts: 5,331

    Great write-up @colander. The only thing I'm unclear about is why you need the Restore Items in every buy button. If the user hasn't bought that item before, then obviously there's no problem. If the user has bought that exact item before, they'll just get asked if they want to buy it again for free. And if there are other purchases that might disqualify the need for that button, why isn't it being disabled based on your recording of purchases elsewhere?

  • gyroscopegyroscope I am here.Member, Sous Chef, PRO Posts: 6,598

    Excellent stuff, @Armelline; and @colander too - helpful, thanks.

    To confirm tho' - am I right in saying the Restore feature is only needed for consumables - so isn't required for buying (unlocking a full) game itself - is that right?

    ""You are in a maze of twisty passages, all alike." - Zork        temp domain http://spidergriffin.wix.com/alphaghostapps

  • colandercolander Member Posts: 1,610
    edited November 2014

    @Armelline this is for a reinstall of a game with single and bundled purchases where the user has made a previous purchase/s. If you don't have any bundled purchases it is not needed.

    Assuming the user doesn't use the Restore IAP for an unknown reason you can't know which button they will press so you have to make sure any button will up date the table before it tries to purchase otherwise they could buy an item they already own as part of a bundle they bought previously because when they go to buy it it will show as "unpurchased". With the state returned by Restore Item you can then create a routine to handle it from there.

    This is not an easy to see problem until you start creating bundled purchases and creating the rules for them.

  • colandercolander Member Posts: 1,610

    @gyroscope Restore Item updates the table to the current state (unpurchased, pending and purchased) of any purchases the user has made for consumables and non consumables (Column 5) and their local currency (Column 4).

  • gyroscopegyroscope I am here.Member, Sous Chef, PRO Posts: 6,598

    Thanks, @colander :smile:

    ""You are in a maze of twisty passages, all alike." - Zork        temp domain http://spidergriffin.wix.com/alphaghostapps

  • ArmellineArmelline Member, PRO Posts: 5,331
    edited November 2014

    @colander said:
    Assuming the user doesn't use the Restore IAP for an unknown reason you can't know which button they will press so you have to make sure any button will up date the table before it tries to purchase otherwise they could buy an item they already own as part of a bundle they bought previously because when they go to buy it it will show as "unpurchased". With the state returned by Restore Item you can then create a routine to handle it from there.

    So what you're saying is that you have, for example, Item 1, Item 2, and Item 3. But you also have options to buy bundled purchase, Bundle 1 (Item 1 and Item 2). If the user has a new install, they may well have previously bought Bundle 1, and therefore already own Item 1 and Item 2, but if they attempt to buy Item 1, they'll get charged again, as the Purchase ID was different? Hence you need to restore purchases before requesting one, to be sure that they haven't bought Bundle 1 before letting them buy Item 1? That makes sense. Definitely stealing your trick to monitor a restore, either way!

    @gyroscope said:
    Excellent stuff, Armelline; and colander too - helpful, thanks.

    To confirm tho' - am I right in saying the Restore feature is only needed for consumables - so isn't required for buying (unlocking a full) game itself - is that right?

    Apple will reject any game without a dedicated "Restore purchases" button. So strictly speaking, it's needed for all games. A Restore also won't restore consumables, only non-consumables. The cookbook is a little misleading in one thing it says:

    @GameSalad_Cookbook said:
    Sets the "state" column of any items purchased by the player, including consumable items that haven't been consumed.

    This makes it sound like if you let the player buy 10 lives, and assign those lives to them, it will restore any lives they haven't used. This is not the case. When they say "haven't been consumed" they mean "You haven't yet told Apple that this set of lives have been assigned to the player". As soon as you assign them to the player you're expect to use the Consume Purchase behaviour, which tells Apple that that purchase has been acknowledged as completed, and they should allow it to be purchased again. Until you "Consume" the purchase using that Consume Purchase behaviour, the player won't be able to make the same purchase again - so they'd be allowed to buy no more than 10 lives.

  • gyroscopegyroscope I am here.Member, Sous Chef, PRO Posts: 6,598

    Thanks v.m @Armelline for explanation - gradually getting my head around it. :smile:

    ""You are in a maze of twisty passages, all alike." - Zork        temp domain http://spidergriffin.wix.com/alphaghostapps

  • colandercolander Member Posts: 1,610

    @Armelline said: So what you're saying is that you have, for example, Item 1, Item 2, and Item 3. But you also have options to buy bundled purchase, Bundle 1 (Item 1 and Item 2). If the user has a new install, they may well have previously bought Bundle 1, and therefore already own Item 1 and Item 2, but if they attempt to buy Item 1, they'll get charged again, as the Purchase ID was different? Hence you need to restore purchases before requesting one, to be sure that they haven't bought Bundle 1 before letting them buy Item 1? That makes sense. Definitely stealing your trick to monitor a restore, either way!

    Yep that's it.

  • kidvanmeterkidvanmeter Member, PRO Posts: 10

    I'm confused about the difference between "Request Purchase Data" and "Restore Items". Does "Request Purchase Data" return the correct value for state from the app store? If so, isn't that the same as doing a "Restore Items"? For example if my current state is un-purchased and I do a "Request Purchase Data", it should change to purchased...right? What is the difference?

  • kidvanmeterkidvanmeter Member, PRO Posts: 10

    I need to clarify that I meant "Restore Items" should set the state of purchased only if the item really has been purchased. The way I asked the question indicates it would always set it to purchased.

  • ArmellineArmelline Member, PRO Posts: 5,331

    Request Purchase Data will get information from Apple about the IAP items you offer, most particularly the price. It does not retrieve information to fill column 5, though - it doesn't find out if an item has been purchased.

    Restore Items asks Apple specifically if items have been purchased. Restore Items is primarily used to fill the information in column 5 - the information about the purchase state of the IAP items.

    Restore Items can be called at any time, but ideally it will only be called when the player requests it be called. It is entirely legitimate to have the game automatically check for previous purchases with a Restore Items call, but it will bring up a username/password login box that may freak some users out if they didn't specifically request it.

  • kidvanmeterkidvanmeter Member, PRO Posts: 10

    When a user purchases an item, the status field in our table is changed to pending. How does it get changed to purchased after that? Do we have to keep checking the status from the app store or is that somehow done automatically? I imagine one click of the purchase button would only return the status once and exit (so the status would remain pending). Do we have to periodically invoke "Restore Items" until we get the updated status (i.e. purchased or un-purchased)?

  • ArmellineArmelline Member, PRO Posts: 5,331

    Once the purchase is registered as completed (between GS and Apple, nothing you can do to affect it once the request is sent), the field will change to "purchased". This will happen automatically (or it will change back to "unpurchased" if the purchase fails).

    You can see when a purchase is completed successfully by having a rule that something like "When text expression tablecellValue(PurchaseTable,1,5) IS 'purchased' then do x"

    As soon as the game registers the purchase as successful, that action x will then take place. You shouldn't need to use a restore purchase. However, this appears to be buggy on Android, and the table isn't always changed.

  • gfb08174gfb08174 Member, PRO Posts: 69
    edited July 2015

    Hi @Armelline , I used the now deprecated IAP behavior and have had some issues changing my code. I posted about it here: http://forums.gamesalad.com/discussion/comment/548442

    The new IAP features do not allow me to "success" "failure" or "cancel" a purchase like the old one (see here http://imgur.com/8DIaYhH ). Using the new IAP behaviors, when I preview my game these notices trigger: http://imgur.com/a/ueiLX. The lack of options means I cannot progress and simulate a purchase.

    How can I simulate the old version in the viewer?

  • ArmellineArmelline Member, PRO Posts: 5,331

    @gfb08174 said:
    Hi Armelline , I used the now deprecated IAP behavior and have had some issues changing my code. I posted about it here: http://forums.gamesalad.com/discussion/comment/548442

    The new IAP features do not allow me to "success" "failure" or "cancel" a purchase like the old one (see here http://imgur.com/8DIaYhH ). Using the new IAP behaviors, when I preview my game these notices trigger: http://imgur.com/a/ueiLX. The lack of options means I cannot progress and simulate a purchase.

    How can I simulate the old version in the viewer?

    My tutorial template shows you exactly how to do this. It's a lot harder now but a lot more flexible!

    http://www.armelline.com/iap-tutorial-template.html

  • gfb08174gfb08174 Member, PRO Posts: 69

    @Armelline

    Thanks for the reply. When I click on download now the following message appears:

    There doesn't seem to be anything here.
    You're trying to view a link that does not exist.

    Your free tutorial template is no longer there! :)

  • ArmellineArmelline Member, PRO Posts: 5,331

    Oops, I must have broken the links again!

  • gfb08174gfb08174 Member, PRO Posts: 69

    That's what motivated me to submit my post. Many links were expired, broke, moved or nonexistent.

    Let me take a look at yours and see if it solves the issues I have.

  • gfb08174gfb08174 Member, PRO Posts: 69

    @Armelline

    This looks great. Thank you for your help. Complicated at first sight, but your explanations make perfect sense.

    1. When I preview the game by clicking on either purchase or restore, this message appears "In App is not supported in the Viewer." How can I simulate the user experience and see what it would look like when I purchase, restore or cancel? No matter which actor I press, the same message always appears.

    2. Are the "Purchased" "Pending" and "Unpurchased" expressions case sensitive? Would an in actor text expression not recognize the table cell value because one is uppercase and the other lowercase?

  • gfb08174gfb08174 Member, PRO Posts: 69
    edited July 2015

    @gyroscope said:
    Excellent stuff, Armelline; and colander too - helpful, thanks.

    To confirm tho' - am I right in saying the Restore feature is only needed for consumables - so isn't required for buying (unlocking a full) game itself - is that right?

    @Armelline Apple will reject any game without a dedicated "Restore purchases" button. So strictly speaking, it's needed for all games. A Restore also won't restore consumables, only non-consumables.

    Wait a minute......

    What's stopping someone from purchasing a non-consumable "remove ads and unlock full game" IAP, playing the full game, and then just restoring the IAP when done?

    You could play a full, unlocked, ad free game by buying the IAP, and then just return it?????

  • MentalDonkeyGamesMentalDonkeyGames Member Posts: 1,276
    edited July 2015

    @gfb08174 The point of non-consumables is that you only need to purchase them once.

    If the player deletes the game, and then installs it again, they can restore the purchase they've already made the last time.

    Mental Donkey Games
    Website - Facebook - Twitter

Sign In or Register to comment.