I'm trying to pull historical payments per-subscription from Apple, and I've run into some problems. What I'm hoping for is something similar to what I get from Stripe, where I send a subscription ID and receive an array of transactions (including payment date, payment amount, discount, currency, etc.).
Using in-app subscription purchases from React Native, the app receives and store what appear to be "iOS 6 style" receipts (regardless of the actual iOS version).
Validating these with Apple on a regular basis has worked well in order to check the current subscription status, but Apple's documentation suggests that the only way to retrieve historical transactions is to provide an "iOS 7 style" receipt. Even then, the returned receipt objects do not appear to contain information about the amount paid, the currency they were paid in, and whether Apple's cut was 15% or 30%.
First question would be how (or even if) I can transform the "iOS 6 style" receipt into "iOS 7 style" - or whether there's another way to get full history for a given subscription ID? The second would be how to retrieve the actual transaction information, above and beyond a simple "payment of some kind happened at this time"?
To be able to fetch data of user's transactions you need a receipt. Using apple verifyReceipt api you'll able to get all needed information, except prices.
I not sure, but there is no way to convert iOS6 style receipt into iOS7 style. But, I hope it may be done on client-side (device) automatically.
If you just want to get financial information look at Apple Reporter Tool, which allow you to fetch any financial data you want (subscriptions, inapps, application installs, applciations purchases).
Related
I'm worry about the refund process on Apple. As I understood, if a customer ask Apple for refund and Apple accept its, the owner of the application is not notified, instead, the owner shall be monitoring the receipt data with Apple to look for the Cancellation Date field in the receipt.
Apples says... "If the field has a date in it, regardless of the subscription’s expiration date, the purchase has been canceled—treat a canceled receipt the same as if no purchase had ever been made" (This is the recommended process)
Now, I'm wondering if it is possible to detect manually a refund from iTunes Connect and obtain the receipt data of the product canceled? I have to say that I don't have access to the Payments and Financial Reports section to check if this is possible, that the reason I'm asking.
Not sure what your goal is, i.e. it is definitely not possible to get information on the customer who got the app refunded.
Here's a way to get more information on the refunds:
Go to > Sales & Trends
Filter by "Transaction Type" and you get an overview of all your refunds (possible to filter by app, via Content "App Name")
You don't have any ways to track refunds explicitly via "App Analytics" (only shows the totals, i.e. downloads/purchases minus refunds) or "Payments and Financial Reports". For the latter, it's the same, they only show you the totals.
I'm having some confusions when creating in app purchase strategy for my iOS app. Some background info below;
I have an iOS app and a web app which both will work in subscription model. The backend has been developed in Ruby on Rails.
Currently I'm trying to develop the iOS auto-renewal in app purchase. I came across couple of gems which helps to verify in app purchase receipts (e.g Venice). I get that the whole point of verifying the receipts from the backend rather then the client is to make it secure and to be able to keep a copy of the receipt in your own server.
I can foresee a huge problem as explained below;
A user can create an account using the iOS app and subscribe to the service by paying X dollars monthly using x#x.com apple id. By doing this I will have the record of this user in my backend including the expiry date of his subscription which will enable for me to track if he renewed his subscription or not. The problem arises when this user logs out from the app and creates another user. Since his apple id is still x#x.com and as account email address or id doesn't matter at all when making a purchase from apple, the expiry date will still be a month ahead since he just subscribed with his previous account the new user will be identified as an already paid customer. Boom! now his friend can login with this account using the web app and enjoy it without paying a quid.
If this makes sense for you, there must be a solution for this hack. I know that Netflix uses Apple's IAP, Spotify used for a very long time.
Also gems like Venice, they don't put a thorough documentation on their github page therefore I don't know if this problem is solved by them out of the box. Just wanted to check with you guys and I'm sure many of you thought about this.
If you're attributing the auto-renewing purchase to a user in your database you will also want to attribute the original_transaction_id that is found in the receipt. Store this ID with the expires_date and ignore or error any receipts containing the same original_transaction_id the API receives that are already attributed to a different user in the database.
The original_transaction_id will never change for the iTunes user, even if they unsubscribe and re-subscribe at a later date it will remain the same. It will also remain the same if they upgrade/downgrade the duration of the subscription when the product IDs are of the same subscription family.
If you're looking for an alternative to Venice take a look at the itunes_receipt_validator gem (full disclosure: I am the author). It validates the signatures and decodes of both the deprecated transaction receipts and the newer grand unified receipts locally without connecting to Apple's API, but also provides the functionality to retrieve the updated receipt and receipt info from the Apple API.
I work for a game developing company which releases at least one game a month. For our true fans we want to start providing a subscription to our games, so they can play all our games (on any platform) without constantly having to buy them.
The idea for iOS is to use the in-app auto-renewable subscription. This results into a receipt which we store in our backend. The backend can validate this receipt and provide the apps with information about the subscription of the user.
This system will solve a lot of problems: You can take the subscription in 1 game, and play all the games as well, on any device you like.
But now we come to the problem: After a month the receipt is not valid anymore, and we need to check in the iTunes store to see if the user still has a valid subscription.
My first idea was to use the "latest_receipt_info" field, to get the latest receipt and validate this. But according the documentation this feature should only be used for iOS 6 receipts:
"Only returned for iOS 6 style transaction receipts for auto-renewable
subscriptions."
source:
https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-
Even though I can actually still use this field with my brandnew iOS 10 receipt, I don't think it's smart to use it since it's deprecated.
(another source telling you shouldn't use it anymore: https://forums.developer.apple.com/message/156580#156580)
The advised solution of apple is to implement a SKPaymentTransactionObserver in the app. This will retrieve the latest receipt when it's available, and send this to the backend. Even though this is far from ideal, this could work... however:
This means the app has to be active to retrieve the latest receipt. And in our case it's very well possible a user takes a subscription in app1, and after a couple of days downloads app2, 3 and 4, but never uses app1 again. So in this case the latest receipt will never be fetched (because only the observer of app1 can access the receipt)
To fix this problem we should be able to fetch the receipts from this subscription from any app in our subscription group. But according the documentation on the apple site (https://developer.apple.com/app-store/subscriptions/ ) you can only access a subscription from 1 app, and you have to do the multiple app thing yourself:
You can offer auto-renewable
subscriptions to access multiple apps in your portfolio. Each app must
be approved to use auto-renewable in-app purchases and must be
published under the same developer name on the App Store.
In iTunes Connect, you’ll need to set up separate and equivalent
auto-renewable in-app purchases in each app offered in the multi-app
subscription so that users can subscribe from any app. To avoid users
paying multiple times for the same offering, you are responsible for
verifying that they are subscribers in one of the apps before showing
any subscription options. To do this, consider maintaining an account
management system in which users create an account with your business
to sign in to each app.
So is there any way to do what we want, without forcing the user to go back to the app he used to purchase the subscription every month?
On the last WWDC we went to StoreKit labs and personally asked StoreKit evangelist about this. We were told that the 'latest_receipt_info' field return by iTunes validateReceipt endpoint is exactly what we are suppose to use in order to check if the subscription was renewed or not.
This is not going to be deprecated in the near future but they do have plans for adding some server-to-server communication that solve few of the problems we ran into:
Your server will be able to get notification from Apple regarding any subscription renewal, cancellation, downgrades etc.
In the latest_receipt_info returned by the validateReceipt endpoint few fields will be added, providing information like whether the subscription will be renewed after current one is expired, whether there was a problem charging the user's credit card etc.
Sources:
WWDC 2017 Session 303 - What's new in StoreKit
WWDC 2017 Session 305 - Advanced StoreKit
OK I'm working on a app where the user purchases the app from the App Store, gets access to the app for a year, and then after the year has passed they are sent to an In-App Purchase screen where they can purchase a subscription for continued access.
(this is not the subscription model I'd implement if it were up to me, but the client insists that it follow this model)
In order for it to work, though, I need a reliable way to check when the app was purchased, in order to calculate when the first year of access ends. Following the suggestions in one of the answers in...
iOS App Purchase Date
...I've gotten the app receipt and I can find all the data fields that the documentation says there are, but there are also a few others including "original_purchase_date" (not the one in the IAP receipt array; the one for the app receipt itself). This would appear to be what I want. However this field is undocumented.
As far as I can tell, Apple security operates via a form of "Security Through Obscurity/Diversity", so it's been difficult to find further information about these undocumented data fields. My concern is that I might use the data from this field, and then discover that it was only there in sandbox mode and actual receipts don't have it. Worse, what if I reference that field and then Apple releases a new iOS update that completely discards that field from its implementation? Undocumented features are even less reliable than deprecated features, after all.
My question is this: is there a reliable source of information somewhere where I can find out what Apples intends regarding this field? Or better yet, is there another, safer way of achieving the system my client wants?
You have to implement it as a free app that requires a subscription IAP. Paying for an app cannot be its subscription cost.
Check rule 11.12 here: https://developer.apple.com/app-store/review/guidelines/#purchasing-currencies
Apps offering subscriptions must do so using IAP, Apple will share the
same 70/30 revenue split with developers for these purchases, as set
forth in the Program License Agreement
Implementing it the way your client wants will result in rejection.
From the StoreKit guide:
If the user attempts to purchase a nonconsumable product or a renewable subscription they have already purchased, your application receives a regular transaction for that item, not a restore transaction. However, the user is not charged again for that product. Your application should treat these transactions identically to those of the original transaction.
This presents a huge problem in an app I am working on. We have licensed a large body of content from a publisher for sale through in-app purchase. They require that every time we sell a piece of this content (i.e. user pays us), our server calls an API on their servers to report the transaction. This is for accounting purposes and ultimately used to determine how much we pay them at the end of the month, per our agreement with them.
I have read several suggestions on SO and elsewhere about calling restoreCompletedTransactions rather frequently and maintaining a local understanding, on the device, of what the user has already purchased so they cannot be allowed to purchase it again. This to me seems like something that should be able to be implemented on the server side. However, the receipts that we are getting back from the Apple servers are exactly the same for a buy and a re-buy, as promised by the StoreKit guide.
If payment callbacks from StoreKit cannot be trusted as a valid accounting mechanism in this kind of situation ("you got paid" vs. "you didn't get paid"), what other real-time insights into transaction traffic are available? I don't think the publisher we are working with is going to be happy if we tell them we have to wait 45 days after the end of the month to get the REAL paid dollar amount out of iTunes Connect.
I have recently looked into the same problem. In my case, I wanted to implement accurate revenue tracking using Mobile App Tracking to track revenue generated from different customer acquisition campaigns.
Fortunately enough, there is a way to do it. It should be noted that SKPaymentTransactionStatePurchased vs. SKPaymentTransactionStateRestored solely depends on the initating action, e.g. whether you initiated a restore or a (re-)purchase, so that doesn't work.
What does work instead is checking for SKPaymentTransaction.originalTransaction which will be != nil for restores and re-purchases. The latter is unfortunately undefined behavior (docs). I'd consider a null check fair enough though.
Another option is to validate the transaction-receipt of transactions with SKPaymentTransactionStatePurchased and check that the original_transaction_id property in the returned, validated receipt matches the transaction_id.
The bad news is: In the current iOS version (4.3.x) there's no way to distinguish between a buy and a re-buy of non-consumable products.
To ease the situation I would recommend two things:
First
After a successful purchase, store the product identifier of the purchased product in the NSUserDefaults on the device. You can then hide the already purchased products from the user and thus handle a re-buy situation.
The NSUserDefaults are backed up by iTunes when the user synchronizes his device. So your stored purchase information is not lost when the user gets a new device.
Second
Store the receipt data together with the device ID on your server. Analyze the receipt's product identifier and the device ID.
If you receive another receipt with the same product identifier and device ID combination, then assume a re-buy. At least this would allow you to cover most of the re-buy cases.
Assuming that an ordinary iPhone user switches his device every 1-2 years, you will at least cover most of the re-buy cases and maybe apple will fix this in the future.
I have one solution,
Configure the product as consumable.
this will solve the problem - (They require that every time we sell a piece of this content (i.e. user pays us)).
Next you need to implement a logic in product buy option. It is in a way that once the user purchase a product the buy option need to remove otherwise the user may happendly go purchase and lost is cash once again for same product in same device.
you can use NSUserdefaults for this purpose.
thanks,