Flutter in app purchase with backend side calling completePurchase and verifyReceipt - ios

I have a flutter mobile app with a backend. I need to synchronize subscription with backend to share subscription across platforms.
For that I follow this flow :
I create a new account
I initiate new subscription after account has been created
I listen for purchase update and when I receive a purchase details with purchaseDetails.pendingCompletePurchase I send it to backend and use apple verifyReceipt endpoint to check receipt in purchaseDetails.VerificationData.ServerVerificationData
If receipt is valid I save the OriginalTransactionId from purchaseDetails.PurchaseID to database
My question here is:
After it return validation state from server I wonder if I still need to call completePurchase even if I called verifyReceipt endpoint.
I'm not sure to understand what completePurchase really do...
In the end, later I wait for apple server notification to update subscription status

Related

Apple Server to Server notification not receiving from the sandbox for testing subscription renewal

I am trying to update the user's subscription renewal state. I had set up the endpoint in the app information section "URL for App Store Server Notifications" in the app information. But didn't receive any notification. Also, I had tried to set up revenuecat but got no notification. Does anyone know about this issue?

Unable to receive In-App purchase refund server-to-server notification

I'm trying to implement handling of In-App purchase refund notification (App Store sends responseBody JSON data to server notification url typed by the app developer) in our server backend. But after getting successful refund of In-App purchase, I'm unable to get any notification from the App Store.
Here's the list of things that I did to handle refund notification in our server.
Goto App Store Connect > Type "App Store Notification Url" : "https://ourServerUrl/notifyRefund" (supports TLS 1.2)
Our server accepts 'POST' request and defines #RequestBody parameter as documented in responseBody
Purchase product ('Consumable') from our iOS App (about $0.99) - purchase_date = 2021-03-03
Goto reportaproblem.apple.com and request a refund. -> Next day the refund was processed by App Store and I got $0.99 refunded successfully to my bank account. refund_date = 2021-03-04
After doing above steps I'm still unable to get a notification from App Store.
I read a post about notification delay but I'm not sure if this is because of the delay or my server configuration has a problem.
Apple doc.
Update as of 2021-03-24
In Server <--> App (iOS/Android) communication,
our server's view resolver (ContentNegotiatingViewResolver) determines the default view (TextPlainView, JsonView)
based on the request header (Content-Type, Accept)
Since the apple notification callback response (request to our server)
does not have 'Accept' header, our server sets default view resolver as TextPlainView
following our server configuration in 'servlet-context.xml'
It has caused errors since Apple notification response is in Json format.
After changing our server default view setting as json view
we were able to parse apple notification responseBody.
I hope it helps developers dealing with similar problems.

Server to Server Pollling Auto Renewable Subscription

We are implementing server side receipt validation for auto renewable subscription. Now when a user turn off the subscription or when it auto renew there is no notification send from apple server to our server. We want to poll apple server when the subscription is about to expire. So how can we do this?
Is there a way to schedule such polling at specific date ?
First when any in app purchase made you need to store receipt data after validating it. Also you need to store expire date of that particular purchase which you will get by receipt validation.
Now create a crone job in your server to validate auto renew purchase, crone job time interval is up to you as per your project need but let say for example take 1 hours. In the crone job you need to select only those record which expire time with in next 6 hours(You can change this time as per your need). Then again validate this receipt and if purchase get auto renew then you will get list of receipt. You will get always new receipt in the list whenever purchase auto renew. In this you will get new expire time. Suppose you are not getting any new receipt then it means user has cancel subscription
You would need Receipt validation.
If your app offers auto-renewable subscriptions, you can receive server notifications from the App Store about key events by setting up an optional URL that links to your server.
Before sending a notification to your server, the App Store will try to establish a secure network connection with your server by using App Transport Security (ATS) protocols. If a secure connection cannot be established, notifications will not be sent to your server. See Requirements for Connecting Using ATS to learn more about security requirements.
After a secure HTTPS connection has been established, the App Store will deliver JSON objects through an HTTP post to your server for key subscription events. See the In-App Purchase Programming Guide to learn more about the contents of this HTTP post.
Use server notifications together with Receipt Validation to validate a customer's current subscription status and provide them access to content or services from within your app.
For more info : Link
Not get notifications such as cancel as these notifications are only sent when a subscription is canceled by Apple directly.
The renewal notification, "Automatic renewal was successful for an expired subscription. Check Subscription Expiration Date to determine the next renewal date and time." In general, iTunes will attempt to charge the user account a day before an auto-renewing subscription is scheduled to expire. If the renewal is successful, there is no server-to-server notification because the auto-renewing subscription did not enter into an expired state. There is no support at present to simulate this event in the sandbox environment.“
Read more: https://forums.developer.apple.com/message/283579#283579

iOS In-app purchase: server side receipt validation for consumable products

I would like to implement In-App purchase of consumable products for an iOS app I'm developing. I want to validate the receipt on the server side as indicated in the documentation:
App start transaction asking to the Apple Store
Apple Store return receipt to the app
The app send the receipt to a trusted server
Trusted server sends receipt (in base 64 format) to the Apple Store through an HTTP POST
Apple Store replies to the HTTP POST with the validation
If the validation response is ok, the purchase can be enabled
I'm concerning about the following situation: a user buys a product and the Apple Store sends back the receipt to the App (steps 1,2). Then, when the app tries to send the receipt to the trusted server (step 3) the connection goes down. In this case receipt validation has to be retried in a second moment, however, I have the following questions:
a) in this case, has the user already paid for the product?
b) Since receipts for consumable products compare only at the time of the purchase, how should the validation retry be managed? Should I save the receipt locally in order to retransmit it in the future?
Can I simply does not mark the transaction as "finished"? From what I understand reading the documentation, in this case StoreKit should call the transaction queue observer again (passing again the receipt?) until the transaction is marked as "finished", is it correct?
Thank you in advance
a) in this case, has the user already paid for the product?
The PaymentTransaction observer will tell you what state the user's purchase is .Purchased, .Purchasing, .Failed . e.t.c.
So we can assume from your question that the user's state is .Purchased and You would have received a payment.
Now since they have a receipt and it’s hopefully from a real purchase they will be waiting for you to validate on your server and unlock the purchase because they have received a receipt containing data about their purchase.
b) Since receipts for consumable products compare only at the time of the purchase, how should the validation retry be managed? Should I save the receipt locally in order to retransmit it in the future? Can I simply does not mark the transaction as "finished"? From what I understand reading the documentation, in this case StoreKit should call the transaction queue observer again (passing again the receipt?) until the transaction is marked as "finished", is it correct?
You don’t need to store it locally, with the information stored about the purchase in the receipt. This is kept until your paymentObserver finishes the transaction or the receipt is refreshed/ updated again.
Your app will keep trying to validate with your server until it receives a response about the receipt usually when the user launches the app again,
At that point if we assume it's valid, you enable your product and then after this finish the transaction on the SKPaymentQueue.
In the documentation it says’s
“The in-app purchase receipt for a consumable product is added to the receipt when the purchase is made. It is kept in the receipt until your app finishes that transaction. After that point, it is removed from the receipt the next time the receipt is updated “
https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
Also:
“For example, consider the case of a user buying something in your app right before going into a tunnel. Your app isn’t able to deliver the purchased content because there’s no network connection. The next time your app is launched, StoreKit calls your transaction queue observer again and delivers the purchased content at that time. Similarly, if your app fails to mark a transaction as finished, StoreKit calls the observer every time your app is launched until the transaction is properly finished.”
I hope this helps and I hope it answered your questions.

Any chance to register a callback URL for In App Purchase at iTunes Connect for consumable products?

We're reading the receipt from StoreKit an sending the NSData to our server. There we're verifying the the data with https://github.com/chrismaddern/iOS-Receipt-Validator-PHP afterwards we make the booking transaction in our cloud system and mark the transaction as completed. But what if the data connection of the client (user) breaks during the buying transaction. Then we'll never get the request with the receipt data and we can't complete the process at our server side. So it would be perfectly if apple submits a callback for every new transaction at In App Purchase. So we can check in time when a customers bought a product at the app. Ideas?

Resources