Всем доброго времени суток!
Проблема в следующем: когда я тестирую приложение в песочнице, все работает нормально.И приложение появляется в App Store и вылетает при попытке купить.Покупка не расходная.
Некоторые факты, которые могут привести к правильной мысли:
- Сбой происходит после строк: let payment = SKPayment (product: subscription.product);SKPaymentQueue.default (). Добавить (оплата)
- Приложение не падает "мгновенно", а через ~ 1 секунду, что означает, что оно падает после некоторого ответа от сервера
- Окнопри вводе пароля, логина, подтверждения покупки не появляется на экране.До этого происходит сбой.
- Это приложение было размещено в App Store как обновление старого.Он был создан в новом проекте, в котором идентификатор пакета был изменен на идентификатор пакета старого приложения.
- Все покупки в itunesconnect, одобренные модератором, отображаются в App Store.
class BillingManager: NSObject {
static let sessionIdSetNotification = Notification.Name("SubscriptionServiceSessionIdSetNotification")
static let optionsLoadedNotification = Notification.Name("SubscriptionServiceOptionsLoadedNotification")
static let restoreSuccessfulNotification = Notification.Name("SubscriptionServiceRestoreSuccessfulNotification")
static let purchaseSuccessfulNotification = Notification.Name("SubscriptionServiceRestoreSuccessfulNotification")
private override init() { }
private static var instance: BillingManager?
/** создает 1 объект или возвращает текущий (синглтон) */
static func shared() -> BillingManager {
if instance == nil {
instance = BillingManager()
}
return instance!
}
var isPro: Bool {
/** Здесь проверяем дату подписки по UserDefaults */
var subscriptionAccess = false
if let purchase = UserDefaults.standard.string(forKey: "purchaseDate") {
if let expires = UserDefaults.standard.string(forKey: "expiresDate") {
if let purchaseDate = dateFormatter.date(from: purchase), let expiresDate = dateFormatter.date(from: expires) {
subscriptionAccess = (purchaseDate...expiresDate).contains(Date())
}
}
}
return (currentSubscription != nil) || subscriptionAccess || UserDefaults.standard.bool(forKey: "forever.subscription")
}
var hasReceiptData: Bool {
return loadReceipt() != nil
}
var currentSessionId: String? {
didSet {
NotificationCenter.default.post(name: BillingManager.sessionIdSetNotification, object: currentSessionId)
}
}
var currentSubscription: PaidSubscription?
var options: [Subscription]? {
didSet {
NotificationCenter.default.post(name: BillingManager.optionsLoadedNotification, object: options)
}
}
func loadSubscriptionOptions() {
let productIDs = Set([InAppType.month.rawValue,
InAppType.halfYear.rawValue,
InAppType.year.rawValue,
InAppType.forever.rawValue,
InAppType.discountedForever.rawValue])
let request = SKProductsRequest(productIdentifiers: productIDs)
request.delegate = self
request.start()
}
func purchase(subscription: Subscription) {
let payment = SKPayment(product: subscription.product)
SKPaymentQueue.default().add(payment)
}
func restorePurchases() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
func uploadReceipt(completion: ((_ success: Bool) -> Void)? = nil) {
if let receiptData = loadReceipt() {
Service.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)
}
}
}
}
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
}
}
}
extension BillingManager: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
options = response.products.map { Subscription(product: $0) }.sorted(by: { (left, right) -> Bool in
left.product.price < right.product.price
})
}
func request(_ request: SKRequest, didFailWithError error: Error) {
if request is SKProductsRequest {
print("Subscription Options Failed Loading: \(error.localizedDescription)")
}
}
}