Я добавляю подписку iOS inapp в свое приложение.Я следую этому замечательному учебнику со страницы Рэя Вендерлиха:
https://www.raywenderlich.com/659-in-app-purchases-auto-renewable-subscriptions-tutorial
В основном учебник состоит из следующих шагов:
- подписка на покупку
- получить квитанцию
- проверить квитанцию в Apple (это должно быть сделано через бэкэнд, но для простоты учебник делает это в приложении).
- после проверки квитанции Apple отвечает сJSON обработал квитанцию.
- приложение локально хранит приобретенные товары и связывает их с sessionID (UUID создан).
После завершения урока кажется, что все работает хорошо, ноУ меня проблемы с двумя проблемами.
Каждый раз, когда пользователь входит в приложение, он проверяет, есть ли у него действительный идентификатор сессии и действительная квитанция:
guard SubscriptionService.shared.currentSessionId != nil,
SubscriptionService.shared.hasReceiptData else {
showRestoreAlert()
return
}
loadSelfies()
hasReceiptData делает это:
var hasReceiptData: Bool {
return loadReceipt() != nil
}
private func loadReceipt() -> Data? {
guard let url = Bundle.main.appStoreReceiptURL else {
return nil
}
do {
let data = try Data(contentsOf: url)
return data
} catch {
print("Error loading receipt data: \(error.localizedDescription)")
return nil
}
}
}
Эти методы только проверяют, существует ли квитанция, больше ничего.
Чтобы проверить currentSessionId, это метод:
var currentSessionId: String? {
didSet {
NotificationCenter.default.post(name: SubscriptionService.sessionIdSetNotification, object: currentSessionId)
}
}
И value currentSessionId устанавливается, когда Apple отвечает на подтверждение получения:
func uploadReceipt(completion: ((_ success: Bool) -> Void)? = nil) {
if let receiptData = loadReceipt() {
SelfieService.shared.upload(receipt: receiptData) { [weak self] (result) in
guard let strongSelf = self else { return }
switch result {
case .success(let result):
strongSelf.currentSessionId = result.sessionId
strongSelf.currentSubscription = result.currentSubscription
completion?(true)
case .failure(let error):
print("? Receipt Upload Failed: \(error)")
completion?(false)
}
}
}
}
Что ж, мои сомнения таковы:
Каждый раз, когда пользователь входит в приложение, оно толькопроверяет, существует ли currentSessionId и квитанция, больше ничего, поэтому, если они существуют, но срок действия подписки истек, приложение не знает об этом, и пользователь продолжает использовать ее без какой-либо активной подписки.Что я должен сделать, чтобы избежать этого случая?Сохранять локально в UserDefaults обработанную JSON-квитанцию и проверять дату истечения срока действия?
И поскольку currentSessionId не сохраняется постоянно, если я убиваю приложение и снова запускаю его, currentSessionId будет нулевым, первымпроверка не удалась, и пользователь не может использовать приложение.Каков наилучший способ справиться с этим?Снова хранить локально в UserDefaults currentSessionID?
РЕДАКТИРОВАТЬ
Глядя на некоторые похожие вопросы, кажется, что каждый раз, когда пользователь входит в приложение, прежде чем проверять currentSessionID и квитанцию, я должен проверитьлокально хранится квитанция, это правильно?