如何为iOS应用程序实现自动续订订阅收据验证?

4

我想发布一个具有自动续订订阅的iOS应用程序。虽然关于此方面有很多信息,但大多数都已过时,因此我将说明我已经完成的工作。

  1. I am working in Swift 2.0, so any objective C code will not help me.

  2. I will not be using my own server to communicate with Apple to verify the receipt, so I believe I either need to have the app communicate with Apple servers directly or I can parse the receipt locally on the device.

  3. I have been able to locate a receipt on the device (not sure if there are multiple ones) using the following code

    func checkForReceipt() {
        let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL
    
        let fileExists = NSFileManager.defaultManager().fileExistsAtPath(receiptUrl!.path!)
    
        if fileExists {
    
            let receiptData = NSData(contentsOfURL: receiptUrl!)
    
            //Now what do I do to decode the data and validate the receipt
    
        } else{
            requestReceipt()
        }
    }
    

然而,我无法弄清楚如何解码收据,以确定到期日期和其他验证步骤,以确保它是有效的收据。

我不得不说,这个对开发人员非常重要且有用的东西竟然如此难以遵循和定位,真的很令人沮丧。任何帮助都将不胜感激,并希望能对许多其他人有所帮助。

1个回答

4
以下是我使用的功能代码,用于检查我的ar-iap的订阅状态。如果我的代码不清楚,请参考此链接。在下面进一步阅读有关每个对应*的额外信息,这些信息作为注释保留。
func checkForReceipt() {
    let receiptUrl = NSBundle.mainBundle().appStoreReceiptURL

    let fileExists = NSFileManager.defaultManager().fileExistsAtPath(receiptUrl!.path!)

    if fileExists {

        let receiptData = NSData(contentsOfURL: receiptUrl!)

        let receiptToString = receiptData!.base64EncodedStringWithOptions([])
        let dict = ["receipt-data" : receiptToString, "password" : "YOUR SHARED SECRET"] //**
        do {
            let request = try NSJSONSerialization.dataWithJSONObject(dict, options: []) as NSData!
            let storeURL = NSURL(string:"https://sandbox.itunes.apple.com/verifyReceipt")! //***
            let storeRequest = NSMutableURLRequest(URL: storeURL)
            storeRequest.HTTPMethod = "POST"
            storeRequest.HTTPBody = request

            let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
            let dataTask = session.dataTaskWithRequest(storeRequest, completionHandler: { (data: NSData?, response: NSURLResponse?, connection: NSError?) -> Void in
                do {
                    let jsonResponse: NSDictionary = try (NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary)!
                    //****
                    let expDate: NSDate = self.expirationDateFromResponse(jsonResponse)!
                    print(expDate)
                } catch {
                     //handle NSJSONSerialization errors
                }

            })
            dataTask.resume()
        } catch {
            //handle NSJSONSerialization errors
        }
    } else {
        requestReceipt()
    }
}

** 您可以从iTunes Connect帐户获取共享密钥: 转到MyApps >“yourappname” >功能 >查看共享秘密 >生成共享秘密, 然后将生成的密钥插入dict中的密码字段

*** 确保在进入生产环境时将storeURL更改为“https://buy.itunes.apple.com/verifyReceipt

**** expirationDateFromResponse(jsonResponse: NSDictionary) -> NSDate?是一个函数,用于读取苹果的JSON响应,并返回ar iap的过期日期


1
请注意上面链接的苹果文档中的以下注释:“重要提示:不要从您的应用程序调用App Store服务器/verifyReceipt端点。” 相反,您需要做的是:a)将收据发送到自己的服务器后端进行验证,然后调用Apple服务器上的/verifyReceipt,或者b)使用OpenSSL / ASN.1在本地验证收据,如此处所述:https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateLocally.html#//apple_ref/doc/uid/TP40010573-CH1-SW2。 - Frederik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接