You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
in_app_purchase: How to validate receipts on iOS? #77232
Hi!
I've made flutter app with auto-renewable subscriptions. It works well on Android, but from Appstore i received this letter:
Please give me advice, how to deal with it?
There is very laconic advice there. I have no idea how to realize this in flutter neither local nor server... (((
Maybe anyone flutter guru can send me steo-by-step lesson or so to deal with this quest?
Actually a lot of dart pub libraries (such a local_auth, etc) have samples what code one need to write in native - swift or kotlin to achive a result, but not in_app_purchase alas. I really got stucked. Some double-trouble it is.
@ValeriusGC this actually goes beyond what flutter handles, and this is really up to you how you handle purchase validation
here are basic steps to get server validation:
get serverVerificationData from in_app_purchase - on iOS this is base64 encoded string
Details
if (purchaseDetails !=null) {
var verificationData = purchaseDetails.verificationData;
if (Platform.isIOS && verificationData ==null) {
verificationData =awaitInAppPurchaseConnection.instance.refreshPurchaseVerificationData();
}
finalbool subscriptionActive =Platform.isAndroid ||// we don't necessarily need validation on androidawaitvalidatePurchase( // call to backend
verificationData.serverVerificationData
);
// ...
}
on server setup such function (i use nodejs firebase cloud functions for example)
Details
/** * This function validates the user purchase on iOS.* It queries the data from the Apple verifyReceipt method, checks whether subscription is still active* and returns a boolean value.*/exportconstvalidatePurchase=functions.https.onCall(async(data,context)=>{const{ verificationData }=data;if(verificationData===undefined){thrownewfunctions.https.HttpsError('invalid-argument','Required `verificationData` field is missing');}constrequestData=JSON.stringify({'receipt-data': verificationData,'password': itunes.password,// this is apple shared secret key'exclude-old-transactions': true,});constheaders={'Content-Type': 'application/json','Content-Length': requestData.length,};letres=awaitaxios.post('https://buy.itunes.apple.com/verifyReceipt',requestData,{headers: headers});if(res.data.status===21007){res=awaitaxios.post('https://sandbox.itunes.apple.com/verifyReceipt',requestData,{headers: headers});}constlatestInfo=res.data?.latest_receipt_info;constpendingRenewalInfo=res.data?.pending_renewal_info;if(!latestInfo||!pendingRenewalInfo||!latestInfo[0]||!pendingRenewalInfo[0]){functions.logger.log(`{ verificationData: ${verificationData}, status: ${res.data?.status}, false, description: no latest_receipt_info or pending_renewal_info }`);returnfalse;}constgraceMs=pendingRenewalInfo[0].grace_period_expires_date_ms;constnow=Date.now();if(graceMs){constvalue=now<graceMs;functions.logger.log(`{ verificationData: ${verificationData}, ${value}, description: grace period }`);returnvalue;}constexpiresMs=latestInfo[0].expires_date_ms;constvalue=now<expiresMs;functions.logger.log(`{ verificationData: ${verificationData}, ${value}, description: default period (no grace) }`);returnvalue;});
I am really shocked! Do thousands of lone programmers build their own servers to get subscriptions? don't make me wrong, please, i can not believe this is really so complex.
Apple and Google both highly recommend handling the verification of receipts on the server-side. Since yesterday a codelab is available which will take you through the steps on setting up server-side receipt verification using Firebase. Even if you don't want to use Firebase as a backend solution, the codelab might be helpful as it discusses all steps necessary to verify a receipt in detail.
More information can be found in the store specific documentation:
Local validation is also possible as the in_app_purchase API provides all the data necessary to do so, however since it is not recommended no examples have been worked out.
I will close this issue as I feel with the codelab there is clear information on how to handle the verification (be it server-side). However please don't hesitate to leave a comment if you have any more specific questions and I would be happy to re-open it.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.
Activity
[-]in_app_purchase: How validate receipts on iOS?[/-][+]in_app_purchase: How to validate receipts on iOS?[/+]nt4f04uNd commentedon Mar 4, 2021
duplicate #61339
nt4f04uNd commentedon Mar 4, 2021
oh actually i think no. they are similar and can be closed by one PR but not duplicate
ValeriusGC commentedon Mar 4, 2021
There is very laconic advice there. I have no idea how to realize this in flutter neither local nor server... (((
Maybe anyone flutter guru can send me steo-by-step lesson or so to deal with this quest?
Actually a lot of
dart pub libraries(such a local_auth, etc) have samples what code one need to write in native - swift or kotlin to achive a result, but not in_app_purchase alas. I really got stucked. Some double-trouble it is.nt4f04uNd commentedon Mar 4, 2021
@ValeriusGC this actually goes beyond what flutter handles, and this is really up to you how you handle purchase validation
here are basic steps to get server validation:
serverVerificationDatafromin_app_purchase- on iOS this is base64 encoded stringDetails
Details
on how to get shared secret see https://developers.facebook.com/docs/app-events/getting-started-app-events-ios/app-shared-secret/
nt4f04uNd commentedon Mar 4, 2021
local validation:
ValeriusGC commentedon Mar 4, 2021
It turns out that, that no way to realize it without making my own server?
nt4f04uNd commentedon Mar 4, 2021
yes, refer to #77232 (comment)
nt4f04uNd commentedon Mar 4, 2021
i reconsidered, it's actually a duplicate of #61339 @TahaTesser
ValeriusGC commentedon Mar 4, 2021
I am really shocked! Do thousands of lone programmers build their own servers to get subscriptions? don't make me wrong, please, i can not believe this is really so complex.
nt4f04uNd commentedon Mar 4, 2021
i didn't say it's complex. you can always implement it yourself by writing some native code
i updated my previous comment a bit as well
nt4f04uNd commentedon Mar 4, 2021
summarized all from above in #61339 (comment)
mvanbeusekom commentedon May 20, 2021
Apple and Google both highly recommend handling the verification of receipts on the server-side. Since yesterday a codelab is available which will take you through the steps on setting up server-side receipt verification using Firebase. Even if you don't want to use Firebase as a backend solution, the codelab might be helpful as it discusses all steps necessary to verify a receipt in detail.
More information can be found in the store specific documentation:
Local validation is also possible as the in_app_purchase API provides all the data necessary to do so, however since it is not recommended no examples have been worked out.
I will close this issue as I feel with the codelab there is clear information on how to handle the verification (be it server-side). However please don't hesitate to leave a comment if you have any more specific questions and I would be happy to re-open it.
github-actions commentedon Aug 1, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.