iOS 7本地(设备上)收据验证和应用内购买检查

iOS 7本地(设备上)收据验证和应用内购买检查,ios,objective-c,receipt,receipt-validation,Ios,Objective C,Receipt,Receipt Validation,在苹果收据验证编程指南的帮助下,我使用OpenSSL和asn1c编译器在设备上本地实现了收据验证。我的应用程序仅支持iOS 7及更高版本 根据苹果公司的建议,我拨打电话,[[NSBundle mainBundle]appStoreReceiptURL]获取appstore收据。当应用程序在显示任何UI之前“第一次”启动时,我也会这样做。这是第一次启动电话,因为苹果建议,如果第一次尝试时没有收据,就刷新收据。此呼叫(SKReceiptRefreshRequest)的结果是,应用程序要求用户输入其i

在苹果收据验证编程指南的帮助下,我使用OpenSSL和asn1c编译器在设备上本地实现了收据验证。我的应用程序仅支持iOS 7及更高版本

根据苹果公司的建议,我拨打电话,
[[NSBundle mainBundle]appStoreReceiptURL]
获取appstore收据。当应用程序在显示任何UI之前“第一次”启动时,我也会这样做。这是第一次启动电话,因为苹果建议,如果第一次尝试时没有收据,就刷新收据。此呼叫(
SKReceiptRefreshRequest
)的结果是,应用程序要求用户输入其iTunes登录信息

现在的问题是,苹果一直拒绝该应用程序,说我正在打电话给他们的生产服务器,而不是沙箱服务器。但据我从收据验证编程指南中了解,只有在使用第二种验证方法并通过自己的安全服务器向苹果发送数据时,才有效。然而,我在本地做所有事情,对于如何区分生产环境和沙箱环境,以便我的应用程序能够通过审查,我感到非常困惑


任何提示或建议都会非常有用。

我删除了以前的回答,我误解了这个问题

我相信你做的一切都是对的,老实说,苹果对自己的指导方针感到困惑。毕竟,在收据验证编程指南中,他们明确建议:“如果在iOS中验证失败,请使用SKReceiptRefreshRequest类刷新收据”,并且无法影响此调用的服务器()


根据,调用什么服务器取决于应用程序的签名方式,显然,提交应用程序时需要对其进行生产签名。

生产环境和沙箱环境之间的区别取决于您调用的链接

#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\u产品\u验证\u收据\u URL是生产服务器。ITMS\u沙盒\u验证\u收据\u URL为沙盒服务器

  • 确保您从Apple provisioning portal创建了正确的配置证书。了解临时与分发之间的区别
  • 当您使用从iTunes Connect创建的测试iTunes用户帐户进行购买时,您必须在沙盒服务器下进行测试。在代码签名标识版本下,您应该选择临时资源调配,而不是分发资源调配
  • 但是,当您想要发布到app store时,您必须选择分发资源调配以及生产服务器(ITMS\u生产验证\u接收\u URL)。您不能在此服务器上使用测试用户帐户。你必须使用真实的iTunes用户帐户(在苹果批准后)才能进行真正的购买
  • 要了解如何在本地实施IAP并在本地验证收据,请学习:- 一,

    二,

    您可以在此处下载已完成的示例项目:- 3.

    注意:可能还有另一种我不知道的验证收据的方法

    我发现了一些可能有用的东西:- 1.

    它表示“在生产环境中,将此参数设置为nil。” 性质 在测试环境中,新收据应具有的属性。有关钥匙,请参见“收据” 属性”(第4页)。
    在生产环境中,将此参数设置为零。

    好吧,这就是对我有效的方法,苹果在经过近一个月的多轮审查上诉和重新提交后,昨晚批准了该应用程序

    当应用程序启动时,不要尝试刷新收据,也不要阻止用户界面。我所做的是,在找到收据之前,不会在启动时显示任何用户界面,因此当启动时提示输入iTunes密码时,按“取消”将显示应用程序的有限版本,输入正确的密码将尝试下载新收据,并根据是否找到收据采取行动

    所以,如果你发现一张收据就可以,如果没有,就不要尝试刷新它

    但是,当用户按下“恢复购买”选项时,请刷新它


    希望这有帮助

    我想分享一下我的经验。我一直在沙箱中工作,删除应用后,应用收据丢失。(然后是re-Command-R-ing)我不知道这是否发生在生产中,但听起来好像是这样。在首次启动应用程序时要求刷新,并提示用户输入密码,这令人震惊。当然,这是一个问题


    似乎
    [[SKPaymentQueue defaultQueue]restoreCompletedTransactions]
    也会在不弹出对话框的情况下静默刷新应用程序收据。这意味着,在事务恢复后,请求appReceiptURL+数据将返回一个非零值。这只是我的少量测试结果。请自行测试。

    如果收据无效或不存在,则显示输入用户psw的对话框

    因此,更确切地说如果没有收据,那么在开始时要求psw(因为用户对bcs感到困惑,他只是启动应用程序,它没有任何理由要求)提供恢复btn,您必须提供
    和w8,直到您收到收据,您可以合理地更改收据

    因此,将刷新代码放入if语句:

    if([[NSFileManager defaultManager] fileExistsAtPath:[[[NSBundle mainBundle] appStoreReceiptURL] path]] == YES) {
    
            self.receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
            self.receiptRefreshRequest.delegate = self;
            [self.receiptRefreshRequest start];
    }
    

    这没有道理。为什么苹果会抱怨你提交审查的应用程序正在使用生产服务器?为什么他们会说在生产应用程序中使用沙盒服务器?我不认为我可以在外部发布苹果的resolution center消息,否则我会将其发布到这里。只是好奇:在调用refresh之后,我假设它失败了,之后你会在应用程序中做什么?通读devforums,似乎只有在验证失败的情况下,您阻止审核人继续进行IAP pu,您才会收到此类拒绝
    if([[NSFileManager defaultManager] fileExistsAtPath:[[[NSBundle mainBundle] appStoreReceiptURL] path]] == YES) {
    
            self.receiptRefreshRequest = [[SKReceiptRefreshRequest alloc] initWithReceiptProperties:nil];
            self.receiptRefreshRequest.delegate = self;
            [self.receiptRefreshRequest start];
    }