iOS inapp purchases receipt additional payload - ios

In my application users can make purchases linked to their accounts in the system, not apple ID. As usual iOS app sends App Store receipt to server, which validates it. I want to know, that each transaction inside receipt belongs to specific user account. One way to do this, is sending additional parameters further to receipt like:
receipt: String, login: String, platform: String
Receipt digital signature validation make sure that the data inside is valid and not replaced by hacker. If parameters (login and platform) will be inside receipt, validation will be completely safe, and valid digital signature tells that all purchases are valid and belongs to account. Otherwise, one receipt can be sent with different logins and allows multiple users to have purchases without paying. To prevent this, for instance, all bundle (receipt, login, platform) can be additionally signed and added check for unique pairs transactionID, userId.
My question is there any way to put additional transaction parameters to receipt, or another common way to archive linkage between purchases in receipt and user account?

Related

Retrieve the subscription_group_id from an in-app purchase receipt

Is it possible to retrieve the subscription_group_id from validating a local receipt? I'm am validating it via ASN.1 on device. Apple provides the following receipt fields on their website: https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
However, I can't see anything about the subscription group id. Seems weird we wouldn't be able to access that so is there another way?

How to verify ios In-App Purchase with different account?

I'm developing an app with non-consumable products. My app need to register and log in for service.
I figure out that the products that user has bought are tied with Apple ID. If user use same Apple ID but different accounts from my server, how will I verify them whether the account buy the product or not?
I have used original_transaction_id to validate it.
Steps-
When any user make a payment, validate the receipt on server.
If a valid payment then update paid in your database and store
original_transaction_id of that receipt.
Next time if the user use same Apple ID, after validating the receipt, check if the original_transaction_id exists in the database or not. If already
exists means user is using same Apple ID for other accounts too,
else its using its Apple ID to make payment first time.

iOS inapp purchase subscription serverside validation security

The logic of the app.
You register with login password. Then if you doesn't have subscription (checked by server) you go to "Buy subscription page".
Problem.
I register user1. buy subscription. token1 goes to server.
I register user2. as he doesn't have subscription he goes to "Buy subscription page", clicks "Buy", apple says "You already bought subscription" and gives token2 (why does it give different token?)
var receiptUrl = NSData.FromUrl(NSBundle.MainBundle.AppStoreReceiptUrl);
return receiptUrl.GetBase64EncodedString(NSDataBase64EncodingOptions.None);
token2 goes to server. As a result we have 1 bought subscription but 2 users that use the same subscription.
Is there any way to identify itunes of user? to save along the token and be able to check if that itunes user already bought subscription for some server side account
This is a fundamental problem in StoreKit receipts and I think most developers don't realize it.
The problem is that Apple doesn't give developers a way to identify which iTunes account a receipt belongs to. This makes it trivial for a user to share their iTunes credentials with other users and unlock subscriptions.
The correct way to handle this is to, in your database, store the actual transaction_id from the Apple verifyReceipt response, and ensure it is unique in your database. This is a lot of work, so it may not be worth it.
It is further complicated by the fact that sometimes, you want an iTunes account to be usable with different app side accounts. For example if a user creates an account and purchases a subscription, lets the subscription expire, then later creates a new account and tries to purchase again, it should be permitted, even though the same receipt is now being used by multiple accounts.
If you don't want to deal with it, I have a service that handles all these edge cases automatically.

Is it possible to refresh the receipt of an in-app subscription from an iTunes API?

I have a backend api that accepts the receipt hash data from client ios devices when an iTunes subscription is purchased. I use https://buy.itunes.apple.com/verifyReceipt to verify the receipt data from Apple and to get the subscription details such as transaction id, expiration date etc.
It seems based on this post that I need to refresh such receipts to discover whether or not there is a cancellation_date. Other than doing this from an ios device as described in the developer docs, is there any other way to call an itunes endpoint from the server-side?
Send the receipt itself and have the server store it. Then, re-send the receipt from the server as often as needed to check for subscription updates.
Apple docs:
Persisting Using Your Own Server
Send a copy of the receipt to your server along with some kind of credentials or identifier so you can keep track of which receipts belong to a particular user. For example, let users identify themselves to your server with an email or user name, plus a password. Don’t use the identifierForVendor property of UIDevice—you can’t use it to identify and restore purchases made by the same user on a different device, because different devices have different values for this property.
The documentation for how to validate a receipt on the server side may be helpful here as well.

Create Token With Apple Pay Without Payment

I have two questions:
Is there a way to create an STPToken using Apple Pay without a payment? In my iOS app, the customer either enters in their payment info or decides to use Apple Pay when registering. When the customer decides to make a purchase (some time in the future after signing up), their card will be automatically charged. There is a method that I can call to check if the payment request can be made, but it seems that I have to actually run the payment and charge the card in order to get the token. Note that I can create a customer and saving a card without charging the customer if the customer enters in the payment info manually. This issue only comes about if the customer decides to use Apple Pay.
For testing purposes, when I do use the payment to create the token and charge the customer's card during the sign up process, I've noticed that the dynamic_last4 and expiration date fields do not match the actual card. I have verified this not just in my program, but also when I log into Stripe's website and check the customer's record. Although these fields do not match the actual card, I can indeed charge the card correctly. Are these fields being masked in some way by Stripe or Apple on purpose?
You need to invoke the Apple Pay payment process in order to get the Apple-generated token. While strictly speaking you don't actually have to process the payment to get the token, what would you do with it otherwise? Store it? They're not re-usable and you don't get the card details to otherwise store a customer/card pair from it for future token generation. If you're not already familiar with it, I would strongly recommend reviewing the Apple Pay Identity Guidelines doc: https://developer.apple.com/apple-pay/Apple-Pay-Identity-Guidelines.pdf with respect to offering your customers multiple payment options including Apple Pay.
Yes, with Apple Pay the last4/exp values are disassociated from the actual card for security purposes.

Resources