В проверке квитанции App App с доверенным сервером.Есть идеи, почему я не получаю последнюю квитанцию ​​с сервера? - PullRequest
0 голосов
/ 10 февраля 2019

Я разрабатываю приложение для iOS в swift, которое использует In App Purchase.У меня есть только один продукт, который представляет собой автоматически продлеваемую подписку, которая также предоставляет пробную версию на 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) У меня есть два устройства, A и B.

2) Я удаляю любую существующую сборку приложения с обоих устройств.Хорошо.

3) Я создаю нового пользователя в песочнице в iTunesConnect и использую его для входа в учетную запись песочницы обоих устройств в настройках.Хорошо.

4) Я запускаю приложение из XCode на устройстве A, так как это первый запуск, у которого нет чека, поэтому он получает его через SKRefreshReceiptRequest.Хорошо.

5) Я запускаю приложение из Xcode на устройстве B, и у него также нет квитанции, так как это первый запуск, поэтому он получает его через SKRefreshReceiptRequest.Хорошо.

6) Я покупаю подписку на устройстве B. Функции доставляются немедленно.Все в порядке.

7) Теперь я снова запускаю приложение на устройстве А. У него есть квитанция (мы запустили ее в пункте 4)), но эта квитанция устарела, поскольку она не включает приобретенный мной продуктна устройстве B. PerformServerToServerValidation вызывается, но, к сожалению, возвращенный JSON не содержит поле «latest_receipt».он содержит только ключи «квитанция», «статус» и «окружение»:

Xcode Debugger Screenshot

Поэтому я не могу убедиться, что подписка уже купленана другом устройстве.Я, должно быть, упускаю что-то важное, но не должно ли быть одним из преимуществ проверки квитанции Сервера, чтобы всегда иметь самую последнюю квитанцию?Важно знать, что если я восстановлю покупки или попытаюсь совершить покупку снова, то, если я вызову код проверки сервера, он отлично работает и имеет ключ «latest_receipt».Но в чем смысл всего этого?Я хотел бы использовать проверку сервера, чтобы не заставлять пользователя делать покупки для восстановления или повторной покупки элемента, даже если он не оплачивается.Спасибо за любую помощь.

1 Ответ

0 голосов
/ 10 февраля 2019

Цель проверки квитанции на стороне сервера - защитить себя от пользователей, использующих поддельные квитанции.Сервер просто проверяет полученную вами квитанцию.Он не использует квитанцию, которую вы отправляете, чтобы проверить, есть ли позднее доступная соответствующая квитанция.

Описанный вами поток, в котором необходимо восстановить покупки на устройстве B, является ожидаемым процессом.

Возможно, вы путаете проверку квитанции на стороне сервера с уведомлениями сервера, когда Apple может отправлять на ваш сервер обновления статуса подписки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...