We have a gamme with iAP feature with some issue recently.
Currently the device is to purchase items from Appstore
and the device will send the receipt to server for validation.
After validated, server will give the products (e.g. coins) to player's account.
It ran well for long and there is a user reported that they cannot receive coins from the game.
The user said they have receive confirmation from AppStore but no increase in coins.
Thus, we are thinking if the user has sudden data lost in network and the receipt was not sending to server. (or sent but somehow lost packet)
would like to know:
1. how to search out this purchase history? by code, in Appstore or iTune connects?
2. is there any best practice code to recovery lost receipt or validate the receipt?
Thanks very much
Apple has responded me about this issue.
From their explanation, it sounds like a specific case that the transaction is not completed in their side but it gives a transaction completed message to user.
Related
Good day! I'm trying to implement notifications for auto-renew subscriptions and some parts of the whole system are not clear for me. Could you please help?
First of all, when user creates a subscription I get a receipt from user's device, verify it and create a record in database with all needed information. Now, the notifications are coming to server.
INITIAL_BUY notification - When does it come and why? I just got a receipt from device, verified it and I'm happy. Why do I need it?
Correct me if I'm wrong, this part is unclear for me, When user UPGRADES subscription level I get CANCEL notification for oldSubscription and a receipt with a new purchase for newSubscription, right?
So theoretical question is - if on my server side content available in oldSubscription and content available in newSubscription are different entities than when I get CANCEL for oldSubscription I just deny user's access to oldSubscription content and when I get receipt from client I create newSubscription with access to new content, right?
DOWNGRADE and CROSSGRADE. As far as I see I get DID_CHANGE_RENEWAL_PREF or DID_CHANGE_RENEWAL_STATUS. So I will get auto_renew_status in notification for this subscription and when payed period will expire I will get a receipt from user device with info about new purchase? Or I have to figure out how to handle DOWNGRADE and CROSSGRADE only by DID_CHANGE_RENEWAL_PREF and DID_CHANGE_RENEWAL_STATUS notifications?
Thank you
The problem with server receipt validation is that there is not only one way. There are endless possibility to implement this and it depends on your use case of the usage of subscriptions and how you want the communication between your app and server to happen.
In your second paragraph is the first example of those possibilities: your server will get the receipt from the device only if you implemented it that way. Also, maybe you update your database solely based on the notifications instead of the send receipt. You see, it is all up to you ;-)
Regarding you questions:
1)
Occurs at the user’s initial purchase of the subscription.
See documentation
Theoretically this is correct, but your described use case isn't an upgrade. Would be odd, if the better subscription wouldn't contain the content of the lower one.
There isn't much to handle with down- or crossgrade. The notifications only tell you that there will be a change with the next auto-renewal. Because, the user is still eligible to access the better content until the next auto-renewal. After the better subscription expired you will receive a normal DID_RENEW with the down- or crsssgrade product id.
So I followed the official manual and implemented this:
https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1
user pays in app
app gets receipt info from Apple
this receipt info is sent to my server
my server verified receipt by calling Apple API and activates membership for client
The obvious problem is that 3. can fail. I have clients complaining they paid, they are sending me SS of the amount being deducted, but my server was never notified. And I have no way to find these users. Is there some CP where I can search by customer e-mail or transaction ID to check if this is Photoshopped screenshot or valid one?
Is there some API that can be called to list transactions by product and e-mail of client?
https://appstoreconnect.apple.com/ - Apple CP is useless for this
There is no method to correlate the customers details with your transaction details. Only Apple can do this.
My first suspicion is that you may have a logic problem in your purchasing process. If implemented correctly, a transient failure at step 3 doesn't matter.
You should:
Create your transaction queue observer a soon as your app starts. This will enable any pending transactions to be delivered to your observer
When you get a purchase transaction in your observer you verify with your server
Only once you have a response from your server that the purchase has been recorded successfully do you call finishTransaction.
This way if something goes wrong with your server or the app crashes the transaction is still pending in the queue.
If you are using auto-renewing and/or non-consumable IAP then I
strongly suggest you provide a "restore purchases" button in your
UI. This makes it simple for the user if something goes wrong or when
they move to a new device.
If you have users who claim that they did not get what they paid for then you can refer them to Apple App Store support who can refund the transaction.
If step three fails you can fall back to local verification and then let the user through for this session (or some number of sessions before you require it to succeed). Unfortunately local authentication is a pain in the ass because the receipt is encrypted. See this link for an example: https://github.com/andrewcbancroft/SwiftyLocalReceiptValidator . You can also report failures of step 3 to your analytics tool so you can see who is actually affected by this issue (obviously this only works if the analytic eventually get an internet connection.
We have got a problem with auto renewable subscription.
First, I would like to tell you my case from the beginning to understand my problem totally.
So, I have an app that contains auto renewable subscription. I managed to buy a product from my app, but I would like to validate the receipt from my server. If I understand it well, then I should send the receipt data to my server that will send the receipt data to Apple and verify that receipt.
First question is that, do I know it right that verification means that we send a request to https://sandbox.itunes.apple.com/verifyReceipt ?
Secondly, what happens if I cannot send the receipt data for the server? I mean, in this case should I save the receipt data locally and try to send it again in a different time (my app can be used after registration so I have to send the user id with receipt data to my server)?
Furthermore, there is a subscription status URL for auto renewable subscription in iTunes connect. We set up an URL for this but we do not get any notification from Apple's server. We configured the server as explained in Apple's documentation (protocols, etc.) but we still don't get any notification. Do you have any suggestion why is it?
Do I know it well, that the notifications should be sent automatically if any status update change happens? If not then what should I do in my app or on my server? (e.g. how to detect if user cancels a subscription?)
Do I have to implement both logic for the best user experience?
To validate the receipt you can send it on apple servers, "can" because you can validate the receipt also in app. In this case is not fully safe, because someone can attack you app and tamper your validation code.
Apple has 2 different kind of servers test and production, when you are debugging you send receipt to the test servers, that also means that auto renewable subscription have shorter time, if I remember well a month in test is 5 minutes.
This is documented very well in apple documentation.
A receipt is always present in your app even if it's free. It's up to you how to manage those kind of situation, in my opinion a receipt should aways be valid from the beginning until the server responds in a different way.
The third question is not clear. There is a system to refresh a subscription but this should be done with user permission as far as I know, the subscription itself seems to be already updated automatically from time to time by the purchase mechanism.
You must implement all the logic to manage a subscription, cancellation, revocation etc.
From time to time, our users claim that they've made an in app purchase in our IOS application but they did not receive their product.
Our purchase flow goes like this:
Once the user purchases an item, the app makes a request to server including the transaction receipt.
Server saves this purchase with the transaction receipt in "new" state.
Server tries to verify this receipt on Apple servers.
If verification succeeds, the product is granted to user.
If verification succeeds, the purchase is marked as "Success".
If verification fails, the purchase is marked as "Fail".
On some occasions, we can find the purchase attempt in between one of these steps and we recover from there.
But sometimes we cannot find any purchase records relative to this user. I personally believe that most of our users are not lying but some bugs or network problems exist instead.
Is there a way I can debug these issues? Is there any information that I can request from the customer and compare that information to some records on iTunes pages or somewhere? Are we doing any mistake during our purchase process? What can we do better to prevent these issues?
Edit
We are verifying purchases by making calls to Apple Api (by using We are verifying purchases by making calls to Apple api (by using nodejs's iap_verifier).
We do not handle any duplicates since we had none so far but I do not think that that is relevant for this specific case.
I understand that this might be an Apple outage, a problem on the Apple side, a network problem or any other problem that are not related to our servers. But I still need a way to confirm a user's purchase when he or she approaches us claiming that he or she made a purchase but did not get their product. Does such a way exist?
We are using server side validation of the payment like so -
User makes payment.
Store kit API sends transaction receipt to App.
App sends base64 encoded transaction receipt to our server.
Our server calls https://buy.itunes.apple.com/verifyReceipt and validates the transaction recept.
User is marked as paid.
For a particular user, we didn't get the transaction receipt at the server, due to which the receipt couldn't be verified. We are guessing something went wrong in steps 2 and 3.
If there were connection problems at the time of sending receipt to server, the app retries again on subsequent app resume.
Now we have one missing transaction receipt and an angry user. How do you suggest we go forward? How can we prevent this in future? Are there any guidelines or best practices that we can follow to prevent such situation?
Thank you.
Based on my experience, the likely issues are
The base64 data got url-encoded along the way and so + and / got messed up - replace these with safer characters before transfer
The whole transaction is bogus.
The way to check for the second case is to look at your account and see if there is a matching purchase record. Unfortunately, the web site can be a bit difficult to review unless you have a low purchase volume.
The are two things you need in your code to correctly handle errors on your server or on, if it happens, Apple's end.
Do not call finishTransaction: until you have successfully communicated with your server (it wouldn't help in this case but worth noting)
Have a "Reload Purchases" button or action that calls restoreCompletedTransactions: on the SKPaymentQueue defaultQueue. For non-consumable/entitlement objects, this will resend all transactions with receipts that can be re-verified on your server.
If the problem you are facing is with non-consumables/entitlements, then the second item is the way out.