How to develop a payment verification for in-app purchase? - iphone

I have developed an iPhone application that was rejected. With this application I offer an SMS transmission service. On my website each user has an account and he can buy credits on the website to be able to send SMS.
The reason for rejections was that my app uses an external service, my website. They say I have to use in-app purchase for the credits.
So now I am about to extend my api. So if purchase takes place in-app the web server needs to know that there was a purchase and what type of purchase. This is done using HTTP-POST.
I could build a simple url and register the purchase in the user-account, since I can verify that an purchase was performed correctly in the app store. But to prevent hacking and just for security reason I think there has to be some kind of encryption.
E.g. if the payment process in the app was successful I send a HTTP-POST to my webserver. It contains some encrypted key that can be encrypted by the webserver.
What do you think about all this? How can I make my api safe regarding in-app purchase and what security algorithm could I use?
Any other suggestions or ideas?

You should probably look into the Server Product Model, rather than trying to invent some way for your app on the device to tell the server that credit was purchased after the fact. The section on Verifying Store Receipts will come in handy; in short, your app transmits the contents of transactionReceipt to your server (ideally via HTTPS). Your server base64-encodes it, embeds it in a simple JSON object, and posts it to Apple to get the status and verified purchase information.

I have a complete implementation of storekit including the server code.
http://blog.mugunthkumar.com/coding/mkstorekit-4-0-supporting-auto-renewable-subscriptions/
Try this

You should check out this wiki article on public key encryption. This is what you'll probably what to be using.
CommonCrypto is a module available for iOS that deals with this type of encryption. Here is a sample project in the iOS developer library that uses this module.

Yes You are correct. That is the best way. When user purchase credit using In-App purchase(IAP) You will have delegate method for purchase succeed. So you can call your Server API in this delegate method and put some flag with credit number in the user table of your server database. You can send this info encrypted and your server would decrypt it and insert in your database.

Related

How to perform the verification off the In-App purchase?

I have just implemented the In-App purchase on my Flutter App.
I saw on various documentations that we should always verify the purchase prior to provide the benefits, but I can't figure out what that is really means.
The PurchaseDetails object provide the followings properties:
purchaseID
productID
verificationData
transactionDate
status
How are we supposed to use them for the verification ?
Thank you for your help,
Benjamin
but I can't figure out what that is really means.
It simply means that as a service provider, we should be double-checking a successful transaction with the payment processing authority (which is Google/Apple for Android/iOS IAP respectively) to prevent any form of fraud.
How are we supposed to use them for the verification ?
https://pub.dev/documentation/in_app_purchase_platform_interface/latest/in_app_purchase_platform_interface/PurchaseVerificationData-class.html
PurchaseDetails.verificationData exposes two kinds of data (they are used the way they are named):
localVerificationData
serverVerificationData
Purchase receipt verification can be done either locally (i.e. on the client app) or on (your) server side. Server-side implementation is recommended for security reasons.
Now, this is where verificationData behaviour for iOS and Android changes.
iOS verificationData
How iOS IAP verification works
Android verificationData
How Android IAP verification works
Ref 1
Ref 2
Without going too much into the references (I think they are quite self-explanatory):
In case of iOS, localVerificationData=serverVerificationData, and the purchase can be verified either by hitting the verifyReceipt endpoint (can be done either on server-side or client-side), or decrypyting the data on the client/server-side and parse the decrypted data manually.
In case of Android, localVerificationData carries the ProductPurchase data, that is otherwise returned by using the token provided by serverVerificationData to request the aforementioned REST endpoint. A purchase is considered 'verified' if purchase status is PURCHASED.
You may also have take care of other situations, depending on your use case.
Hope that the references linked above are useful.

Do i need to verify iPhone in app purchase receipt?

I have implemented an in-app purchase into my iPhone application. It is non-consumable, and it basically flags a BOOLEAN that allows the user to access an additional viewcontroller. Works great. But in apple's documentation, there is alot of stuff about verifying the receipt. Is this necessary? I don't use an external server for my purchase.
Even if it is not necessary, can I just save the receipt to NSUserDefaults?
Short answer: no, you can trust the Apple Server.
Long answer: there're some software for jb iphones that let users to obtain "fake" purchase receipts, so if you don't verify the receipt your sw can be fooled...
That said depends on your situation: having a server to check/validate receipts can cost you more that letting some thiefs to stole your work. But again weight your options...
You should verify the recipe, because otherwise there will be users with a jailbreak and a tool that just pretends to be an Apple server and says yes to every in app purchase. If you verify the recipe with the Apple server, you can guarantee that the user really bought the content.

Possible security measures for in-app purchases downloaded from a server

I have an app I'm developing which relies heavily on users being able to purchase content which will be downloaded from a server. As the app nears completion I'm becoming more concerned about my current distribution model, which is simply that when the user purchases an item the app then generates the correct URL and downloads the data (e.g., from www.website.com/content/music.mp3).
I have some simple web development experience, but I'm not aware of any authenticating process to ensure that only my iphone app has access to this content. In other words, as soon as somebody detects the outgoing URL request, they could get my content for free. Is there anything I can do to prevent, deter or even strongly discourage this?
Send the receipt to your server, verify the receipt and create a one-time-url for the file.

iPhone in app purchase subscription to web server data. How should I auth?

I'm working on an app that will provide data from a web server to users but only if they've bought an in app purchase subscription. I understand the basics of IAPs but how do I securely make sure the data from the server is only accessible to the app, and only if the subscription has been purchased? I don't want to make the user set up an account, I just want to auth the app/purchase securely.
Thanks in advance :)
I'm going to use subscription model too with IAP.
AFAIK, you SHOULD NOT use a unique phone identifier like the IMEI of the phone to identify the user on your server. According to the Apple documentation, you MUST provide a way so that an user can restore his subscriptions on several devices!
Besides, a call to restoreCompletedTransactions of the SKPaymentQueue will restore ONLY nonconsumable products! Subscriptions are not supported by this method.
See these links :
http://developer.apple.com/library/ios/#technotes/tn2009/tn2259.html (section « Frequently Asked Questions », point 10)
iPhone - How to recognize the iTunes user of my app
The only way I know is to use a login/password to identify the user on the web server but this could be quite ugly...
However, if someone know another way, could he describe his solution ?
You should upload store receipts to your server, to be able to check them on Apple's site. And, with request you should upload phone identifier. And, of course, store somewhere in the database. After all, you will have information about which phone id has access to subscription.
And, when you will request subscription-related info from your server, you'll be able to check who has acces (via phone id) and who hasn't.

IPHONE in-app purchase: is it possible to verify a receipt without using an external server?

I have a receipt of a recorded transaction stored by the application when the transaction was done and I would like to ask apple's servers if this receipt is valid.
Is there a way to do this without using an external server?
I would like to ask Apple's servers if this receipt is valid.
Is there a way to do this without using an external server?
Perhaps it's just me, but it seems like you are asking to contact a server without contacting a server, which is quite impossible I'm afraid.
As far as I know, there are few json service provided by Apple:
One for the In App sandbox (before the submission):
https://sandbox.itunes.apple.com/verifyReceipt
One for the App Store version:
https://buy.itunes.apple.com/verifyReceipt
You can call them sending your receipt:
{
"receipt-data" : "(actual receipt bytes here)"
}
And it returns the answer:
{
"status" : 0,
"receipt" : { ... }
}
I assume you can make a direct call to the service within your iPhone app OR you can call your own server script that work as a proxy to the Apple service. It depends on your app logic. If you need to check the receipt on your server (IE. to authorize a download) you should call your server script otherwise you can verify the receipt directly from the app.
Doc reference:
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html
this case is solved. It is possible to do that using just the iphone.
To clarify:
Only the Apple Server can give information about the validity of a
transaction receipt. Indeed you have to contact this server even just
to find out if a product is still active (or if the user has
cancelled the subscription).
On the web, you get the impression that
it is not at all, or at least not in any safe way, possible to
contact this Apple Server simply via HTTP-POST out of your app.
Everybody seems to be convinced you need to have a web server which
is contacted from your app, and that you should only contact Apple's
server from your web server.
Apple, however, even provides implementation code (I wish I had found that earlier) on how to contact the verification server safely without another web server in between:
http://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/_index.html
This implementation is similar to what lomanf mentioned, just in more detail and with all the security needed to make it work even with iOS 5.x.
So the answer is most definitely: Yes.