如果 IAP 验证失败,我该怎么办?

Posted

技术标签:

【中文标题】如果 IAP 验证失败,我该怎么办?【英文标题】:What should I do if IAP validation fails? 【发布时间】:2015-04-15 21:10:06 【问题描述】:

ios 中,如果用户尝试购买 IAP,但我的服务器验证收据失败,那么正确的行为是什么?在沙盒中进行测试时,我只会收到大量弹出窗口询问我的密码。如果我调用 finishTransaction,它会停止询问我的密码,但我相信这会导致用户在没有收到产品的情况下被收费。

【问题讨论】:

【参考方案1】:

我认为进行应用内购买时的错误处理是进行应用内购买时较少提及的困难之一。这里有几个问题。例如: 1)如果您在设备上对购买收据进行验证(即 >= iOS7 样式的解密样式验证),并且验证失败,您应该怎么做? 2) 如果您使用基于 Web 的服务器进行验证,但失败了,您应该怎么做? 3) 如果您将收据存储到您自己的基于 Web 的服务器上,但失败了,您应该怎么做?我将从我自己的应用程序中提出一些想法。很高兴看到其他人对这种错误处理做了什么。

1) 如果您在设备上对购买收据进行验证(即 >= iOS7 解密样式验证),并且验证失败,您应该怎么做?

如果您在设备上的初始验证失败,Apple 建议您执行收据刷新 (SKReceiptRefreshRequest)。但是如果刷新后验证失败怎么办?您可以将这种情况解释为存在严重错误(例如,用户以某种方式侵入您的应用程序,故意给您一张错误的收据),告诉用户购买因收据验证失败而失败,然后完成交易(SKPaymentQueue finishTransaction:) ,永久失败。但是,我不喜欢这样最终。也许这是我的自信,但我的编程可能出了问题。我喜欢给用户更多的机会。所以,我的解决方案是:1) 告诉用户验证失败,2) 将 SKPaymentTransaction 置于“等待”状态,3) 调用 finishTransaction。这种保持状态的想法是我的发明,Apple 没有任何建议(或支持)。我已经创建了 SKPaymentTransaction 的可变子类,并有一个队列(称为 SPASMutablePaymentTransaction),我将其存储(使用 NSCoding)到 NSUserDefaults 中。几乎总是,这个队列是空的,但是如果我得到一个验证失败,就像我在这里谈论的那样,我创建一个 SPASMutablePaymentTransaction 对象,复制 SKPaymentTransaction 信息(包括收据,例如,来自捆绑包),并保存该交易进入我的持有状态队列。我让我的 UI 的一个(通常是隐藏的)部分可见,这可以允许用户重试持有状态事务。

复杂吗?对,一点儿。但是,由于我们正在与给您钱的用户打交道,因此我正在努力保持稳健。到目前为止,它似乎在测试中运行良好。我还没有用户对此(或分析)的任何反馈,但它已部署到应用商店。

2) 如果您正在使用基于 Web 的服务器进行验证,但失败了,您应该怎么做?

对我来说,这与上面的 1) 类似。您已尝试对收据进行验证,但失败了。您可以先尝试刷新收据(见上文),然后重新尝试服务器验证。在我的应用程序中,由于我总是先进行设备上的收据验证,因此再次刷新收据对我来说没有意义(因为如果设备上的收据验证失败,我会这样做)。因此,我再次将收据置于“持有”状态(如上),并允许用户自行决定重试持有状态的交易。

3) 如果您将收据存储到自己的基于 Web 的服务器上,但失败了,您应该怎么做?

(a) 大概这绝对不应该是您永久不向用户提供购买的情况。这是您的服务失败。就我而言,这可能会发生,例如,如果我在与服务器通信时遇到网络错误。我在这里做一些不同的事情。我不会立即让用户访问他们的购买,也不会将交易置于“持有”状态。相反,我设置了一个计时器来重试将收据存储到我的服务器的过程。它会在几分钟后重试。我告诉用户我在做什么。我将收据数据存储到 NSUserDefaults 中(再次使用 SPASMutablePaymentTransaction 对象),因此即使应用程序崩溃/终止,也会在此重试中持续存在。当我成功将收据保存到我的服务器时,我授予用户购买权限。

(b) 在这种情况下,我确实调用了 finishTransaction:,但我还没有授予用户购买的权限。我可以通过不调用 finishTransaction: 来避免这些细节,让我的事务观察者再次处理这个过程(例如,当应用程序下次启动时),但用户可能不得不再次输入他们的 Apple Id。我的想法是这是我的问题(即,我未能将收据信息保存到我的服务器),所以我试图在幕后处理它。

【讨论】:

【参考方案2】:

弹出一个 UIAlertView。请参阅下面的代码...

self.alert("Purchase Failed", Message: "Please Make Sure You are connected to the internet and try agian")    

 func alert(title:String, Message:String)
        let actionSheet:UIAlertController = UIAlertController(title: "\(title)", message: "\(Message)", preferredStyle: UIAlertControllerStyle.Alert)
        
        // for alert add .Alert instead of .Action Sheet
        // start copy
        
        let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler:                
            
                (alertAction:UIAlertAction!) in                                        
                // action when pressed
        )
        
        actionSheet.addAction(firstAlertAction)
        
        // end copy
        self.presentViewController(actionSheet, animated: true, completion: nil)        
    

【讨论】:

以上是关于如果 IAP 验证失败,我该怎么办?的主要内容,如果未能解决你的问题,请参考以下文章

RESTful 服务,如果验证失败如何响应?

Firebase 身份验证在发布模式下失败

如果 iOS 购买收据验证失败怎么办?

验证失败时设置 Spark TextInput 背景

证书验证失败怎么回事?

Drupal 中的 CSRF 验证失败