I'm referring to this question
Who bought my app
only with a little twist: I don't want to know the email address of the user or phone number or anything alike. All I care about is some unique identification of the user who purchased it (="the active android/ios account" that was billed).
Is that possible?
I want the user that bought the app on android to be able to access the app on ios. Also I want to prevent "frauds". Imagine somebody borrows my device with my android credentials and within the app logs into his account and presses "buy". That would enable the user to buy the app and it'd charge me. Also it would allow them to restore MY purchases. That's why I need to get the fingerprints of the user who bought it.
I am assuming you already have the account management facility in your app.
So answer to your second question would be to implement the register and login facility which would allow the users to log in with the fingerprint which is the separate problem.
So go ahead and solve this problem first.
The answer to your first question resides in the central server where you register and authenticate the users.
You will need to validate InApp purchase from your server.
The flow steps of how it should be done:
User clicks on the buy button. (It does not matter whether the original user is doing this action or a fraud)
Ask the user for authentication. In this case fingerprint. (The fraud would not be able to pass from this step.)
The app initiates the purchase flow. The user completes the flow.
The app receives the payment successful response from the google. (The app will not allow the access to the item to the user yet. The payment needs to be verified by our server. Google suggests we verify payment from the server and not the app. Refer to Security Best Practices.)
The app sends purchase receipt received from the Google + Unique Id(UserId, Email, Phone no.) to the server.
The server sends purchase receipt (purchaseToken) to Google for verification. The Google verifies it as a successful purchase.
Now that our server knows that the purchase was successful it creates an entry in the database with purchase info (Purchase time, Start time, Expiry time etc.) and user info.
(This is the answer to your first question)
The flow steps when the user logs in from the iOS or any other device.
The user logs in to the device.
The user tries to use the purchased product.
The app sends the request to the server.
The server checks whether the user has access to the resource.
Returns the response.
Key point is to have a Server which authenticates the user and verifies the purchase.
Follow my THIS answer you will get clear Idea on how to implement this.
Related
I want to store in Android app data a token (a random number, e.g. 128 bit long) unique for each install. I also want to deliver this token to the backend after confirmed purchase. That is, the backend should reject hacker's attempts to store the token, if it is not after an app purchase.
In other words, I need to implement app "activation" so, that the activation is possible only after a genuine Google Play purchase.
An explanation why I need this:
Suppose I resell a $1 product for $2 in a $10 paid app.
The right to use this service by the user appears when he purchases my paid app.
If the user can fake app install, then he may obtain 1000 products for $10 and thus I would have $990 loss.
Thus I need to store on server side a token generated on confirmed (on the backend side) purchase.
Is this possible with Play Market?
In Flutter (and I believe, in plain Android, too) it can be done this way:
Every purchase needs to be "acknowledged".
After verifying the purchase receipt and the delivering the content to the user it is important to call InAppPurchase.completePurchase to tell the underlying store that the purchase has been completed. Calling InAppPurchase.completePurchase will inform the underlying store that the app verified and processed the purchase and the store can proceed to finalize the transaction and bill the end user's payment account.
Warning: Failure to call InAppPurchase.completePurchase and get a successful response within 3 days of the purchase will result a refund.
So, the task can be done this way:
The purchase is created (on the client app side, by contacting Play Store).
The app contacts my server with purchase token (and possibly other info).
During the request from the app the server retrieves the purchase by purchases.products.get to verify that the purchase is not forged by a hacker and increases users in-app funds.
App, after receiving a successful reply from the server, acknowledges the purchase by InAppPurchase.completePurchase.
If the app fails to acknowledge, the purchase is refunded in 3 days.
I would like to know if there is an API or endpoint that I can call/use to retrieve active subscriptions or the purchase history for a user and only to a specific app. To explain what I want to achieve, I am going to tell you what I currently have developed:
An Android app that has an active subscription that users can subscribe to.
Once a user pays and Google Play calls onPurchasesUpdated(), to deliver the result of the purchase operation, the app handles the purchase.
To handle the purchase, the app sends the sku, purchaseToken and other relevant information to our server.
As soon as the server returns a 200 OK to the app HTTPS POST request, the app acknowledges that subscription based on the purchaseToken.
If a user wants to check their active subscriptions that information is available through the following url: https://play.google.com/store/account/subscriptions
If a user wants to check their purchase history that information is available through the following url: https://play.google.com/store/account/orderhistory
So based on this information, I would like to know how can I obtain information about all the purchases (or the last one), either with the Google Play Billing Library or the Google Play Developer API (or other), so that I can access the purchaseToken information. My objective is to have a way to access, from within the app, a list of that user's subscriptions or just it's last purchaseToken. Note that I do not want to get access to a list that includes other apps purchases or history. Only the info about my app.
I plan to use non-renewing subscription on SaaS app since apple doesn't allow auto-renewable for SaaS.
Apple also requires us to provide a server side mechanism to track the subscription with multiple devices.
But, based on my research, apple also seems to reject app if registration is mandatory, so such user registration must be made optional.
My app can be used without registration at start, so registering is optional at this point. But, if users want to buy non-renewing subscription, registration is mandatory to track the subscription.
Does apple reject this approach?
Related links:
app rejected.how to track user non-renewing subscription
*UPDATE
I checked the session video of WWDC2012, and it seems it is ok to ask user to register with your server BEFORE purchase for non-renewing subs. I will post an answer once they really approved this method.
*UPDATE
I got an reply from apple through Resolution Center.
The bottom line is we should allow user to buy subscriptions without registration anyway.
This is the answer from apple review team.
It would be appropriate to make registration optional. You may provide
an alert stating that the user will not be able to track a
subscription on multiple devices without registering. However, you
should provide the option to register and track a subscription after
the subscription is purchased as well.
I don't have a definitive answer but my understanding (not just a guess) is that you must permit them to purchase the subscription without making an account. You can warn them that if they don't make an account, their subscription won't be portable to other devices, but you still have to let them move forward without an account if they want.
From a technical perspective, you could treat this as "you must allow the user to make an account without any personal information"; they might have an account on your server for receipt validation, etc, but it's not tied to their name, email, udid, etc. The issue is one of privacy, so as long as it's not personally identifiable info you're storing, it's fine to keep track of the subscription so you know when it expires, etc. (It's nice to later let them enter their email if they want so they can make the subscription portable.)
Of course, what Apple approves or not changes over time and varies for other reasons, so YMMV.
I'm developing an app using Unity (for Android and iOS). I'm using the SOOMLA plugin to allow users to purchase Gems (virtual currency) with In App Purchase.
Users and Gems and all other game logic go through my server on Azure.
I want the following procedure to take place as a single transaction in some way:
User buys Gems with IAP
App notifies server
Server validates the purchase and updates data
But if the internet connection breaks down between step 1 and step 2 - the user payed for Gems that he did not receive (not good!)
So my current approach is this:
User initiates a purchase
App notifies the server
Server blindly updates data accordingly
User buys Gems with IAP
If the purchase is cancelled, notify server to undo it
That way, the user is guaranteed to get his purchased Gems, but I am not guaranteed to get paid (not great...)
Note: I don't want to manage user Gems in the store itself. I want everything on my own server. So the SOOMLA's balance is meaningless to me. I don't care for it.
I was thinking maybe the app can store the purchase data in persistent storage until it manages to notify the server about it, and then delete it. But I was also thinking that this might be a bad solution. Hence this question.
I imagine the best solution as something that will properly handle this scenario:
User buys Gems with IAP
IAP succeeds
Internet breaks down
My own server isn't notified
User uninstalls app from his device
User may then install the app on other devices:
Either he was charged and he got the gems by some magic
Or he was refunded automatically, since the gems were not received
So far it seems like this is impossible by any means, which makes me disappointed with the technology of IAP's. Hoping for answers that will prove me wrong.
Seems like all I'd ever need is the ability get a user's purchase history from my server, with a secured request to Google Play or Apple Store. But that's just not part of the framework.
So what are others doing? What is the best approach?
In general, you seem to suffer from the Two Generals' Problem which was
the first computer communication problem to be proved to be unsolvable.
Since everywhere in your communication protocol a message can be lost (even the acknowledgement or the acknowledgement`s acknowledgement or the ...) you cannot be 100% sure that both communication parties (the user device and your server) have agreed upon the same state. You can only say that upon a certain probability the state information has been interchanged successfully.
I would send a couple of ACKs back-and-forth and store the purchase if a sufficient number got trough. Quote from Wikipedia:
Also, the first general can send a marking on each message saying it is message 1, 2, 3 ... of n. This method will allow the second general to know how reliable the channel is and send an appropriate number of messages back to ensure a high probability of at least one message being received
For customer satisfaction I would take the odds in their favor - 1% not delivered goods will get you in a lot of trouble but 1% loss on your side is acceptable.
Considering your Gems are a virtual currency, then the natural in-app product type should be consumable, i.e. they are not restorable purchases.
To consume a purchase with a Google Play purchase you will call consumePurchase. On iOS you will call finishTransaction on the SKPaymentQueue. In both marketplaces the consumable purchase will remain in an active state until they have been consumed. If the user deletes the app off their device before the purchase is consumed, they will be able to re-install, and restore their previous unconsumed purchases.
In-between the initial purchase and consumption is where you want to put your server-side validation. When a purchase is made, send the receipt or token to your server, perform the validation and respond accordingly. The app should wait for a valid response from the server before consuming the purchase.
(Note that consumed purchases will not appear in the in_app collection on an iTunes receipt. They are only present if the purchase has not been consumed yet).
If the server is timing-out or network connectivity is lost the purchases will remain in an active state and the app should continue trying to send the details periodically until it receives a response it is expecting.
Purchases for both Google Play and iOS are stored locally so you will just need to run a process that looks for unconsumed purchases once network connectivity is re-established.
You can treat the provisioning of Gems in the same way a bank handles deposits of cheques; the new balance will be immediately updated but the amount spendable will not match until the cheque (or in your case a validation) is cleared.
Some pseudo code to make the process clear:
Purchase product or Restore purchases
While consumable purchases > 0
Send purchase receipt to API
If response is ok
If purchase is valid
Consume product
Allocate gems
Break
Else
Remove retroactive gem allocation
Discipline the naughty user
Break
Else
Retroactively allocate un-spendable gems
Pause process until network is re-established
Re-send receipt to API
I don't have much knowledge about android but after reading your post I was really interested to search keenly and more over how game like clash of clans in app purchase logic work and prevent freedom fake purchase hacks.
After doing some research I would like to share my thoughts over your problem, You can implement it by following approach:
Make your in app purchase verification completely online. For e.g., you can consider the game clash of clans.
How it works:
1)Game loads, synced with server. Network connection required, as network connection breaks game reloads from server.
2)User have 10 gems, server also have 10 gems.
3)User purchased gems, server verify purchase separately for the purchased consumables, gems credited to the users account.
4)If in can case network fails, then also server can verify purchase and later on it update it in account of user, whether it is on any device.
5)This will also help you to bypass many fake in app purchase hacks like freedom (prevention) and lucky patcher.
Google provide api for server side to verify or get purchase detail and when purchase from application side and server side match then only you credit gems or consumable item into users account.
For more information about in app purchases and their hack preventions you can visit these links:
1)Server side verification of in app purchase part 1 and part 2.
2)How would you verify in app purchase billing server side.
3)Verify purchase via PHP.
4)Secure in app purchase scenario on web server.
Hope this might lead you in direction which you want to go, also I would love to hear your thoughts over the same.
You can try restoring the In App purchases made with a particular account.
The feature is given just for this case when either the payment was made and user didn't receive the items he was promised or when he switched device.
Upon restoring the purchase you'll receive the purchased product again from the iTunes server and then you can accordingly notify your server.
Some advice:
User buys Gems with IAP
IAP succeeds
Internet breaks down
My own server isn't notified
User uninstalls app from his device
User may then install the app on other devices:
Either he was charged and he got the gems by some magic, or he was refunded automatically, since the gems were not received.
At step 3, receipt information is stored on the user's device. If the user uninstalls and reinstalls your app, the receipt information will be lost. But you can restore it; Apple talk about that here. You can resend a restored receipt to your server. At your server, you verify that plus Gems for the user so he can receive what he should be.
he was refunded automatically, since the gems were not received
This seem impossible with IAP because Apple does not allow a user to cancel their purchase. (With Google IAB, refund are allowed, more about that here)
How do I implement (Auto-renewable) Subscriptions for an Android App.
I've read the documentation
and as far as I understand, the process is the following:
User subscribes to such a subscriptions on the app. This will generate a Purchase token.
The app sends this token to the server along with something to identify this user
The server will store this Purchase token with this user and will mark the subscription as valid
the server validates this Purchase token via the http-api periodically (typically once per day) with something like a cronjob
if the subscription isn't valid anymore, the subscription will be marked as invalid on the server-side.
If the app makes requests to the server to resources that need the subscription, the client will send this user-identity-string along with the requests. We then check in the database, if the subscription of this user is still marked as valid.
My question is now, how we should identify this users? Do we have a simple user id available that we can share between our app and our server? or should we use something different? What is the best practice here?
We did already similar subscriptions on ios and we used the uuid of the device to identify the users (at least as long as we were able to use the uuid).
From the Answer below we should generate a unique ID. This would be unique per device (or per app-installation). But if a user changes his device or reinstalls the application this id would not be the same anymore. So I'm not sure, how the process is in this use case. I thought of something like this:
The user is logged in with the same google play account on his second device.
As the app starts (or becomes active) we would fetch the users subscriptions
We then would receive this purchase token from the subscriptions and send them along with the new unique-ID to our backend-server as if the user had made a new subscription.
Would this be the right process? And stays the purchase token the same as it was on the first device?
Ok, my question about identifiying users is answered, the link provided delivers enough informations. I'll put further questions in new threads on SO, if I have some.
This link maybe helpful to you as you want to identify the users uniquely.Please note that the personal information of a user rests with Google only.And you should avoid getting private information of a user.
http://www.pocketmagic.net/2011/02/android-unique-device-id/#.URIe_B3Wgr7