我正在开发中迅速使用应用程序内购买一个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”字段。它仅包含“收据”,“身份”和“环境”键:
因此,如果订阅已经被另一台设备上购买的,我不能确定。我必须失去了一些重要的东西,但不应该是服务器收到验证的优势,始终最新收据吗?要知道一件重要的事情是,如果我恢复购买或尝试再次购买的话,如果我调用服务器验证代码,它完美的作品,并有“latest_receipt”键。但是,什么是这一切的意义?我想使用服务器验证,以避免强制用户做一个恢复购买或重新购买,即使不收取费用。谢谢你的帮助。
服务器端收到验证的目的是为了保护自己免受用户注入伪造收据。服务器只需证明您发送收据。它不使用你发来检查是否有可用的后相应的收据收据。
你描述你需要恢复在Device B的购买流程,是预期的过程。
你可能会混淆服务器端收到的验证与服务器的通知,其中,苹果可以将您的服务器subscription status updates