在与可信服务器应用程序购买收据验证。任何想法,为什么我没有得到的最 新收据从服务器?

问题描述 投票:0回答:1

我正在开发中迅速使用应用程序内购买一个iPhone应用程序。我只有一个产品,这是一个自动再生认购,即还提供7天的试用。根据大多数的文件,我发现,首先Apple docs的,按照最好的策略是使用受信任服务器收到验证。我已成立了一切都在我的项目,我信任的服务器上,现在的通信工作,至少没有错误。我在应用程序代码如下:

func performServerToServerValidation() {

guard let receiptUrl = Bundle.main.appStoreReceiptURL,
   let receiptData = try? Data(contentsOf: receiptUrl)
   else {
            return
    }

let baseUrlString = "https://<my.trusted.server>/validation/verifyReceipt.php"

let theRequest = AFHTTPRequestSerializer().request(withMethod: "POST", urlString: baseUrlString, parameters: nil, error: nil)

theRequest.timeoutInterval = 20.0

theRequest.httpBody = receiptData.base64EncodedString().data(using: String.Encoding.utf8)

operation = AFHTTPRequestOperation(request: theRequest as URLRequest)

operation?.responseSerializer = AFHTTPResponseSerializer()

var dict: Dictionary<String,Any>!

operation?.setCompletionBlockWithSuccess({ operation, responseObject in
        if let responseObject = responseObject as? Data {

    do {
        dict = try JSONSerialization.jsonObject(with: responseObject,                           options: JSONSerialization.ReadingOptions.mutableContainers) as? Dictionary<String, Any>

        print("Finished connection with the trusted server")

        if let receiptBase64String = dict["latest_receipt"] as? String {

           let decodedData = Data(base64Encoded: receiptBase64String)!

           let newReceipt = Receipt.init(data: decodedData)

           print("\(newReceipt!)")

           self.validateReceipt(receipt: newReceipt)

           self.analyzeInAppPurchasesInReceipt()
     }
   } catch {

   }

}

})

// 5
operation?.start()

}

我在服务器上的代码如下:

<?php
function getReceiptData($receipt)
{
    $fh = fopen('showme.txt',w);
    fwrite($fh,$receipt);
    fclose($fh);
    $endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';

    $ch = curl_init($endpoint);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $receipt);
    $response = curl_exec($ch);
    $errno = curl_errno($ch);
    $errmsg = curl_error($ch);
    curl_close($ch);
    $msg = $response.' - '.$errno.' - '.$errmsg;
    echo $response;
}

foreach ($_POST as $key=>$value){
$newcontent .= $key.' '.$value;
}

$new = trim($newcontent);
$new = trim($newcontent);
$new = str_replace('_','+',$new);
$new = str_replace(' =','==',$new);

if (substr_count($new,'=') == 0){
  if (strpos('=',$new) === false){
    $new .= '=';
  }
}

$new = '{"receipt-data":"'.$new.'","password":"<my_shared_secret>"}';
$info = getReceiptData($new);

?>

现在到了我的问题。我想利用服务器中的中间人的优点,例如,以确定是否用户已经订阅的另一设备上,通过使用服务器的验证。我的测试流程如下:

1)I有两个设备A和B.

2)我从两个设备中删除任何现有应用程序的构建。好。

3)我创建iTunesConnect一个新的沙盒的用户,我用它来登录上设置两个设备的沙盒帐户。好。

4)从我的Xcode启动应用程序在设备A上,因为它是它不具有接收所述第一发射,因此获得一个贯通SKRefreshReceiptRequest。好。

5)本人从Xcode中启动的应用程序在设备B上,并且它也没有一个收据,因为它是第一次发射,因此获得一个贯通SKRefreshReceiptRequest。好。

6)我购买订阅设备B上的特点是立即交付。一切都好。

7)现在,我再次启动应用程序的设备A.它有一个收据(我们推出了它的第4点)),而是因为它不包括我已经在设备B. PerformServerToServerValidation购买的产品被称为该收据是过时的,但不幸的是,返回的JSON不包含“latest_receipt”字段。它仅包含“收据”,“身份”和“环境”键:

Xcode Debugger Screenshot

因此,如果订阅已经被另一台设备上购买的,我不能确定。我必须失去了一些重要的东西,但不应该是服务器收到验证的优势,始终最新收据吗?要知道一件重要的事情是,如果我恢复购买或尝试再次购买的话,如果我调用服务器验证代码,它完美的作品,并有“latest_receipt”键。但是,什么是这一切的意义?我想使用服务器验证,以避免强制用户做一个恢复购买或重新购买,即使不收取费用。谢谢你的帮助。

ios cocoa-touch in-app-purchase
1个回答
2
投票

服务器端收到验证的目的是为了保护自己免受用户注入伪造收据。服务器只需证明您发送收据。它不使用你发来检查是否有可用的后相应的收据收据。

你描述你需要恢复在Device B的购买流程,是预期的过程。

你可能会混淆服务器端收到的验证与服务器的通知,其中,苹果可以将您的服务器subscription status updates

© www.soinside.com 2019 - 2024. All rights reserved.