iOS 7 Local (on device) Receipt Validation and In-App Purchases Check

杀马特。学长 韩版系。学妹 提交于 2019-12-02 18:12:46

Alright so here is what worked for me, Apple approved the app last night after multiple rounds of review appeals and re-submissions spanning almost a month.

Do NOT try and refresh the receipt when the app launches and do not block the UI. What I was doing was not showing any UI on launch until a receipt was found, so when prompted for the iTunes password on launch pressing cancel would show the limited version of the app, entering a correct password would try and download a new receipt and act according to whether one was found.

So on launch if you find a receipt thats fine, if not do not try and refresh it.

DO however refresh it when the user presses the Restore Purchases option.

Hope this helps.

I've deleted my previous response, I had misunderstood the question.

I believe you are doing everything right and Apple is confused about its own guidelines, to be honest. After all, in the Receipt Validation Programming Guide, they advise clearly: "If validation fails in iOS, use the SKReceiptRefreshRequest class to refresh the receipt" and there is no way to influence to what server this call is made (SKReceiptRefreshRequest reference)

According to http://asciiwwdc.com/2013/sessions/308, what server is called depends on how the app is signed, and it needs to be signed for production upon submission, obviously.

The difference between production and sandbox environments is based on the link that you are calling.

#define ITMS_PROD_VERIFY_RECEIPT_URL        @"https://buy.itunes.apple.com/verifyReceipt"
#define ITMS_SANDBOX_VERIFY_RECEIPT_URL     @"https://sandbox.itunes.apple.com/verifyReceipt";

ITMS_PROD_VERIFY_RECEIPT_URL is production server. ITMS_SANDBOX_VERIFY_RECEIPT_URL is sandbox server.

  1. Make sure that you create the right provisioning cert from Apple provisioning portal. Know the difference between Ad-Hoc vs Distribution.
  2. When you are using a Test iTunes user account that you created from iTunes Connect to buy, you will have to test it under sandbox server. Under the Release of Code Signing Identity, you should choose Ad-Hoc provisioning rather that distribution provisioning.
  3. But when you want to release to app store, you have to choose distribution provisioning and also the production server (ITMS_PROD_VERIFY_RECEIPT_URL). You can not use test user account on this server. You will have to use a real iTune user account to buy it (after Apple approves it) to make a real purchase.

To Learn how to implement IAP locally and verify the receipt locally, learn from:- 1.http://www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios-6-tutorial

2.http://www.raywenderlich.com/23266/in-app-purchases-in-ios-6-tutorial-consumables-and-receipt-validation

You may download the completed sample project here:- 3. http://cdn1.raywenderlich.com/downloads/InAppRagePart2Finished.zip

NOTE: There might be another way of verifying the receipt that I do not know.

I found something that might help:- 1. https://developer.apple.com/library/ios/documentation/StoreKit/Reference/SKReceiptRefreshRequest_ClassRef/SKReceiptRefreshRequest_ClassRef.pdf

- (id)initWithReceiptProperties:(NSDictionary *)properties

It says "In the production environment, set this parameter to nil." properties In the test enviroment, the properties that the new receipt should have. For keys, see “Receipt Properties” (page 4). In the production environment, set this parameter to nil.

Dialog for enter user's psw is shown if the receipt is invalid or does not exist.

So RATHER then ask for psw at the beginning if receipt does not exist (for user is confusing bcs he just launch the app and it asks for no reason) PROVIDE Restore btn which you have to provide ANYWAY and w8 till you get receipt which you can reasonably varify.

So put your refresh code into if statement:

if([[NSFileManager defaultManager] fileExistsAtPath:[[[NSBundle mainBundle] appStoreReceiptURL] path]] == YES) {

        self.receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
        self.receiptRefreshRequest.delegate = self;
        [self.receiptRefreshRequest start];
}

I'd like to share my experience. I have been working in the Sandbox and the app receipt missing after deleting the app. (And then re-Command-R-ing) I do not know if this happens in production, but it sounds as though it does. Asking for a refresh upon the first ever app boot, and prompting the user for their password is startling. This is an issue, of course.

It seems as though [[SKPaymentQueue defaultQueue] restoreCompletedTransactions] also silently refreshes the app receipt without popping a dialog box. Meaning, after transaction have been restored, asking for the appReceiptURL + Data returns a non-nil value. This is just from my short amount of testing. Please, do your own testing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!