I am doing one application.In that i am using InAppPurchase concept.In that i am implementing auto renewal subscription.Whenever i subscribe for product,I am sending the receipt to apple server from my server.In that i am getting the response from apple.That response contain different fields.In that fields,i want to know about transactionIdentier.Is this fileds is different from every payment.Means whenever i subscribe first time whatever i get is this same as whatever i get at the time of renewal.And if another user subscribe for same item then that person also get the same transactionIdentifier or different one.
I think the answer you are looking for is that all users and all transactions get a unique transactionIdentifier (which unless I've misread is a string of numbers). If you want the transactionIdentifier from when the user first subscribed, I believe you can get that from transaction.originalTransaction during SKPaymentTransactionStateRestored and I believe that is the same as looking for the original_transaction_id field on your server.
Related
Now when user upgrade the auto renew subscribe product in apple app purchase, the apple server will send a DID_CHANGE_RENEWAL_STATUS message to my develop server. Now I am received the message successfully. But I did not know what should I do to handle the DID_CHANGE_RENEWAL_STATUS message properly. I read the doc and search from internet and tell me the apple will take effect the new upgraded subscribtion the next period. what should I do when received the DID_CHANGE_RENEWAL_STATUS message?
I have think one way that save the new upgraded subscribe record and mark the new subscribed record not valid until recieved switch message from apple server. should I do it like this?
now I am get the subscribe product by using product id and expire date, I must add another field to mark the new upgraded product not valid. I just want to know how to handle the DID_CHANGE_RENEWAL_STATUS message the best way. The same as downgrade auto renew product, any suggestion is appriciate.
This event is only telling you that the product_id will change.
As you said, in case of an up-grade/cross-grade, it will change right away. In case of a down-grade it will change at the next expires_date.
To know if you should change the current product associated to your user, look into the last element of the latest_receipt_info (ordered by web_order_line_item_id) and check the product_id. If its value match the upgraded product, you should change, otherwise no.
If it didn't change, you'll get the new product:
in case of an up-grade/cross-grade: an INTERACTIVE_RENEWAL S2S will succeed to the DID_CHANGE_RENEWAL_STATUS (and you'll have to check the latest_receipt_info.product_id property, as described before)
in case of down-grade: since the expires_date will be past, you'll need to check with the /verifyReceipt API if the subscription has been renewed. By looking to the product_id property, you'll detect the down-grade.
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.
I'm accessing the receipt after a successful in-app subscription (by checking SKPaymentTransactionStatePurchased
state). After I verified this receipt, in the receipt verification response "expiration_date", "expiration_date_ms", and "expiration_date_pst" are are missing under "receipt". Why is that?
(As a workaround I tried to get the last object of latest_receipt_info and refer its expiration date. But this data is referring to the last subscription before the current one. So I cannot find the required expiration date there.)
How can I resolve this and retrieve the expiration date of the subscription purchased just now?
you're looking in the right place. You are probably looking at the wrong object in your index when you say the "last" one. It is a good practise to sort the latest_receipt_info, usually by purchase_date_* in order to make sure you can count on the object you're looking at.
You should probably check this guide to see if there's something about the receipt structure you are getting wrong:
https://www.namiml.com/blog/app-store-verify-receipt-definitive-guide
In particular, in the receipt section you get an array of IAP items, each of which holds things like expiration_date.
latest_receipt_info should have the current subscription, and not the older one - are you processing the response from Apple's json, or just decoding the local receipt? A query with to Apple should always return the latest purchase data.
I'm in the process of upgrading an existing iOS IAP subscription system that already makes use of App Store Server Notifications. My existing solution is using the now deprecated latest_receipt, latest_receipt_info, latest_expired_receipt and latest_expired_receipt_info fields. According to Apple, these fields are now all replaced with the single unified_receipt field.
After watching all the required WWDC videos and sifting through the little documentation available I'm still left with a few unanswered questions.
The latest_receipt_info field is documented as:
An array that contains the latest 100 in-app purchase transactions of the decoded value in latest_receipt.
This means that this array will contain the customer's entire transaction history. This will not only include the relevant subscription but also any transactional products the customer may have purchased.
My question here is how can I find the relevant transaction in this array? The relevant transaction in this case would be the one that triggered the event (e.g. CANCEL). I need this transaction in order to update our backend database to reflect the current subscription status. For example, to update the subscription end date to the cancellation_date on a CANCEL event .
I have a similar question regarding the pending_renewal_info array. It's unclear to me from the existing documentation if all customers with an active (or maybe even expired?) subscription will always have an entry in this array.
An array of elements that refers to auto-renewable subscription renewals that are open or failed in the past.
I also need to find the relevant transaction in this field to do things like toggle the subscription status on a DID_CHANGE_RENEWAL_STATUS event or update the billing status on a DID_FAIL_TO_RENEW event. From the docs it doesn't look like there is enough info in the pending_renewal_info alone to compute the current subscription renewal status.
Overall my question really boils down to:
Can I be sure that there will be an entry in both unified_receipt.latest_receipt_info and unified_receipt.pending_renewal_info that matches the top level event auto_renew_product_id? And if so how should I find the relevant object in the respective array? Will there only be a single entry for each auto_renew_product_id or should I search the array and pull out the first match?
I found out that the transactions inside unified_receipt.latest_receipt_info array are ordered by purchased date from the latest to the oldest. And sure that you can found out the the top level event auto_renew_product_id.
However, for updating the subscription status or billing status, I utilize the return value from /verifyRecipt, which you can get by requesting to the Apple verifyReceipt server with receipt-data and password(https://developer.apple.com/documentation/appstorereceipts/verifyreceipt). Noted that the input receipt-data is unified_receipt.latest_receipt, and the responses share the same structure as unified_receipt.
What the server-to-server responseBody looks like and how should i know if a user cancelled subscription or refunded?
I have seen this doc: https://developer.apple.com/documentation/appstoreservernotifications/responsebody, but still confused.I have not seen a field like cacellation_date.
Should i parse the latest_receipt_info, and then if user cacel subscription, there will be cacellation_data and cacallataion_intent?
The cancellation fields are only for the case that the Apple Support cancelled the subscription for a customer. In that case you get the cancellation_date_ms field in the server-to-server response.
cancellation_date_ms
The time and date that Apple customer support canceled a transaction or the time and date the user upgraded an auto-renewable subscription.
more details here.
cancellation_date is the corresponding field in the receipt itself.
Note: cancellation_date and cancellation_date_ms both only exist in the production environment.
To check if a user cancelled your subscription, you would use expiration_intent (The reason a subscription expired).
You can use this value to:
Decide whether to survey the subscribers who have opted in to an account on your system or show alternative subscription products within the same group, if the value is “1”.
Decide whether to show the same or alternative subscription products, if the value is “2”, since the user did not actively make the choice to unsubscribe.
Decide whether to present a subscription offer to win back the user if the value is "1".
more details here