how to synchronise "non-consumable purchase" with a "online multiplayer game server" - ios

We are developing an online mobile multiplayer game for iOS platforms.
In our game, a player may purchase and activate the "PRO" mode to get some extra benefits.
So, we created a "non-consumable" type of in-app purchase. because, "PRO" mode is a kind of one time purchased, forever activated item. We will activate it and store the necessary data on the server, but we also need information about "who have just purchased this item form itunes game store".
My question is: how can we synchronise user's appleid and the server game account? appleid is a private variable which we can't get from SDK.
We also cannot use identifierForVendor, because someone can login and logout with different accounts on the same device.
Is there any solution is this situation? Or do you advice me to change this item as "consumable" type and handle all the works on the server side? ( I suppose this situation may also create some kind of trouble in the future )
EDIT: How can I detect that: someone delete the app, reinstall, log in to game server with different account and restore PRO mode for this account (he can easily do this probably lots of his friends who play the game) I wonder, how can I match appleuser <==> gameuser in this situation?

You can implement "restoreCompletedTransactions" method for your non-consumable items.
It's ready to use mechanic by Apple which allows user to restore purchases - you just provide a button and implementation.
Also check: https://developer.apple.com/in-app-purchase/In-App-Purchase-Guidelines.pdf

I found the solution
It is explained under the Server Product Model section.
There is an extra receipt validation process between the game server and itunes server. I get the transection receipt data with mobile app, send it to the game server, and then game server check this receipt if it is valid or not.
https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/StoreKitGuide/APIOverview/OverviewoftheStoreKitAPI.html#//apple_ref/doc/uid/TP40008267-CH100-SW11

Related

How to handle in-app purchase scenario?

Lets say I have website where user can purchase subsciption x,y,z and I have app where user can also buy same subsciption. What happen when user alredy bought sub on website and then login to app? Can we push informations to apple server or just check in app with our backend if user has sub and ignore apple?
For the multiple plateform scenario you have to maintain the server DB along with the status of the account is either purchased or not. If user is paid then which type of subscription (x,y,z) it is. For app (android, iOS), you have to use API's and for web you have fetch data from server DB.
Can we push informations to apple server.
No, you can not do this. Apple IAP data only maintains that you have purchased from the IAP. And same as for the google in app purchase.
Hope now you have been cleared.

Should in-app purchases be present after logging out of iTunes?

I am developing an iOS app. It will have non-consumable in-app purchases.
Q1. Let's say that a user is logged in on their iPad or iPhone to "iTunes & App Store" with "account1", then purchases the in-app purchase, and then logs out of "iTunes & App Store". Then they return to the app.
Should their in-app purchase still be present? Not will it, but should it?
If not, my questions are answered. On the other hand, let's say it should be present. Then I have a follow-up question.
Q2. After following all the above-mentioned steps, the same user logs in to "iTunes & App Store" with a different account, "account2". Should the in-app purchases they made with "account1" still be present while logged in as "account2"?
If you can enhance your own clear and succinct answer with an official statement from Apple, that would be awesome and much more likely to be marked as the solution! If not, thanks in advance for your personal thoughts, ideas, and opinions regarding the best user experience... if Apple doesn't have a clear position on this, then whoever makes the best case will have their answer marked as the solution.
Certainly an unusual case for two users to enter their App Store credentials on the same device. That said, the closest I can see to Apple having something to say about this is:
"Non-consumable products. Items that remain available to the user
indefinitely on all of the user’s devices. They’re made available to
all of the user’s devices. Examples include content, such as books and
game levels, and additional app functionality."
If you take this literally, and if you consider the device still being the same user's even if they have logged out, then I suppose you should make sure you award the non-consumable to the new user as well.
In my experience, many apps store locally when an IAP has been purchased so if the app has not been deleted, any user will see the unlocked content. Your app won't necessarily know that a new iTunes user is using the app, so it would be hard to detect that a new user was using it and revoke the content.
Additionally if you didn't want two users to potentially share a purchase, it would make more sense, in my opinion, to make the purchase a consumable and enforce some sort of log-in mechanism in your app such that it is credited to an individual authenticated account.
Purchases are literally stored in a file in the app bundle on the device. The path or url to the file can be accessed using appStoreReceiptURL. This documentation states:
In OS X, if the appStoreReceiptURL method is not available (on older systems), you can fall back to a hardcoded path. The receipt’s path is /Contents/_MASReceipt/receipt inside the app bundle.
While this is quote specifically mentions OS X, the same is true for iOS with the exception that the result is a localised app url. To support this further, the documentation for NsBundle (which is what appStoreReceiptURL returns) states:
An NSBundle object helps you access the code and resources in a bundle directory on disk.
So with this understanding, we can conclude that purchases are not stateless. They remain within the context of the app. If a user signs out of iTunes, the file isn't deleted.
If an app listens to the SKPaymentQueue, new transactions will come in from time-to-time, particularly when a user buys an auto-renewing subscription. If the user is signed out of iTunes they will receive a request to sign in with the account they originally subscribed with in order for the app receive and save the new receipt. But I digress.
By retaining the purchase state in the app, it allows the purchases to be used without an internet connection. Since an offline device can't authenticate with Apple, keeping the purchase state anywhere else would break this functionality. So yeah, it should be present.
As for Q2, the receipt for account1 is replaced with account2 once a transaction for account2 is received. However until account2 has their made first transaction account1's receipt will still be on disk. This can be used as an exploit to share purchases between users and AFAIK, no good solution exists without using your own user accounts. There are a bunch of stack posts describing this problem.
Should it happen? I wish it didn't, but it seems it is an unintended consequence of the stateful design of the purchase receipts.

How to synchronize/verify in-app recurring subscriptions with a web server (cross platform subscription)

We run a SAAS Web app and are going to be launching our app in Apple’s app store (up to now we’ve had a mobile Web app).
We want to offer the ability to purchase a subscription in app due to the ease of use for our customers. No problem, we know how to do that.
The question we have is whether there is an easy way to keep our web app's db updated with the user’s current subscription status so if they access our Web app we know whether their subscription is valid.
Ideally it would be great if Apple offered a web hook option where they would post an update to a url on our server. From what I've read this isn't an option.
We can always post the data to our server from the iPhone app when the user logs in, but if the user doesn’t log in on the iPhone for a while the subscription status recorded on our server will be out of date.
How are other people handling this? Are we missing something?
Update:
The closest I've found is this thread: https://forums.developer.apple.com/message/70707#70707
The app gets a receipt the first time it buys a subscription or
restores a subscription. The app can send that original receipt to
anyone's server. Anyone's server can then use that orignal receipt to
verify the current subscrition anytime it wants. You can't do that
with a non-renewing subscription but with a non-renewing subscription
the user must purchase the extension from the iOS device each time
period.
Followed up with this:
https://hetzel.net/2011-04-01/server-side-auto-renewable-subscription-receipt-verification/
And from Apple it sounds like they definitely do not make any provisions on their end for synchronization:
Cross-Platform Considerations
Product identifiers are associated with a single app. Apps that have
both an iOS and OS X version have separate products with separate
product identifiers on each platform. You could let users who have a
subscription in an iOS app access the content from an OS X app (or
vice versa), but implementing that functionality is your
responsibility. You would need some system for identifying users and
keeping track of what content they’ve subscribed to, similar to what
you would implement for an app that uses non-renewable subscriptions.
Late to the party, but I think this is a relevant reply to this question:
https://stackoverflow.com/a/47537279/543423
Hopefully this is helpful to someone :)

Prevent iOS in app purchase being shared between devices

I intend my app to gain access to my server after the in-app purchase is complete. This access requires real work, and data & traffic ($$).
A typical client might own anywhere up to a couple of hundred devices (and I assume on one account, for their simplicity).
Thus I only get the one payment across many, many devices interacting with the server.
I'm not trying to be stingy - but can I prevent multiple devices sharing the same purchase (in my case server access)?
Or do I implement another method for selling access?
You'll have to implement another method. Apple's guide explicitly states that:
Users can restore products that they previously purchased—for example, to bring content they’ve already paid for onto their new phone.
If the same iTunes account is associated with more than one device then Apple requires any purchases to be available on all those devices.
#Tommy is correct - regarding non-consumable IAPs. However, you could implement a non-recurring subscription in-app purchase instead and give each device a unique identifier. When the user attempts to access the server, you could see if that identifier is in your database (if the user has purchased the IAP), and determine whether or not they need to purchase a subscription. Even though you may not want a subscription-based service, you could probably make a membership for a very long period of time like 10 years (it's not required to be selected in iTunes Connect) and handle it that way. Only issue is that you need to figure out a way to give each device a unique ID that won't change.
Further to the #Tommy answer, in the February 3, 2014 version of Apple's Getting Started with In-App Purchase on iOS and OS X it says:
There are a handful of important guidelines to keep in mind as you design your application:
- You must make your In-App Purchase items available to all of the devices registered to a user
and
Users view the items they purchase as theirs to keep and permanent. Therefore be sure
purchased items are available in all instances of your app running on all the devices the user
owns, even after your app is deleted from a device, reinstalled, or downloaded to a new device.
and
For Non-Renewing Subscriptions, [blah, blah, blah]..
Additionally, your application must include a mechanism to deliver the purchased Non-
Renewing Subscription In App Purchase to all iOS devices owned by a single user.
Looks like there is no way to restrict items to a single device :(

Apple App Store - bypass listed purchase price?

Is there a way to offer a purchase free of charge for in-app purchases? I'd like to give a free download as a promotional item and not charge the normal price that is listed in iTunes.
You have to code for this in your app. In my app all purchases are registered on parse.com and sync'd between user's devices. I can add a purchase to the class on parse.com for a user and then they get the IAP for free when the data sync's to their device.
Apple don't have any mechanism for this like they do with app purchases unfortunately. The best way I've found is a custom URL scheme, so you can generated a code/string of your custom URL type ://myApp/123456promoCodeFooBar12999 etc, then your app, in response can connect to your server and check this code off against your database (confirming that it has not been used before, and can't be used again on a diff device) before unlocking the feature. This circumvents needing to get UUID's off people etc (which you can't do in code anymore to check against anyway), you just need an email address, send link, user clicks in it, your app opens and away you go :)
edit addition 28 Feb 2014..
an alternate approach might be to submit an separate paid version of the application in which all upgrades are unlocked because they are paid for upfront at purchase time. You may choose to keep this off the iTunes shelf but occasionally put it up, perhaps at a prohibitively high price, $1000 etc, because you can get the normal promo codes off Apple for this one to give to journalists etc, just explain what you are doing to them in your cover letter and I'm sure they'll be more than happy to play ball

Resources