diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index c9420e1d78..692c372832 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -94,7 +94,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case preferredVideoCodec(Int, String, String?, Bool) case disableVideoAspectScaling(Bool) case enableVoipTcp(Bool) - case resetInAppPurchases(PresentationTheme) + case restorePurchases(PresentationTheme) case hostInfo(PresentationTheme, String) case versionInfo(PresentationTheme) @@ -110,7 +110,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.logging.rawValue case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: return DebugControllerSection.experiments.rawValue - case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineStickers, .localTranscription, . enableReactionOverrides, .resetInAppPurchases: + case .clearTips, .crash, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .resetWebViewCache, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .playerEmbedding, .playlistPlayback, .voiceConference, .experimentalCompatibility, .enableDebugDataDisplay, .acceleratedStickers, .experimentalBackground, .inlineStickers, .localTranscription, . enableReactionOverrides, .restorePurchases: return DebugControllerSection.experiments.rawValue case .preferredVideoCodec: return DebugControllerSection.videoExperiments.rawValue @@ -191,7 +191,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 32 case .enableReactionOverrides: return 33 - case .resetInAppPurchases: + case .restorePurchases: return 34 case .playerEmbedding: return 35 @@ -1043,9 +1043,21 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) - case .resetInAppPurchases: - return ItemListActionItem(presentationData: presentationData, title: "Reset IAP Transactions", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: { - arguments.context?.inAppPurchaseManager?.finishAllTransactions() + case .restorePurchases: + return ItemListActionItem(presentationData: presentationData, title: "Restore Purchases", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.context?.inAppPurchaseManager?.restorePurchases(completion: { state in + let text: String + switch state { + case .succeed: + text = "Done" + case .failed: + text = "Failed" + } + if let context = arguments.context { + let controller = textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: "OK", action: {})]) + arguments.presentController(controller, nil) + } + }) }) case let .hostInfo(_, string): return ItemListTextItem(presentationData: presentationData, text: .plain(string), sectionId: self.section) @@ -1111,7 +1123,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present if case .internal = sharedContext.applicationBindings.appBuildType { entries.append(.enableReactionOverrides(experimentalSettings.enableReactionOverrides)) } - entries.append(.resetInAppPurchases(presentationData.theme)) + entries.append(.restorePurchases(presentationData.theme)) entries.append(.playerEmbedding(experimentalSettings.playerEmbedding)) entries.append(.playlistPlayback(experimentalSettings.playlistPlayback)) } diff --git a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift index 05d73cdc05..08bda86473 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -215,7 +215,7 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { transactionState = .purchased(transactionId: transactionIdentifier) if let transactionIdentifier = transactionIdentifier { self.disposableSet.set( - self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier, receipt: getReceiptData() ?? Data(), restore: false).start(error: { _ in + self.engine.payments.sendAppStoreReceipt(receipt: getReceiptData() ?? Data(), restore: false).start(error: { _ in Logger.shared.log("InAppPurchaseManager", "Transaction \(transaction.transactionIdentifier ?? "") failed to assign AppStore transaction") queue.finishTransaction(transaction) }, completed: { @@ -229,18 +229,6 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { Logger.shared.log("InAppPurchaseManager", "Transaction \(transaction.transactionIdentifier ?? ""), original transaction \(transaction.original?.transactionIdentifier ?? "") restroring") let transactionIdentifier = transaction.transactionIdentifier transactionState = .restored(transactionId: transactionIdentifier) - if let transactionIdentifier = transactionIdentifier { - self.disposableSet.set( - self.engine.payments.assignAppStoreTransaction(transactionId: transactionIdentifier, receipt: getReceiptData() ?? Data(), restore: true).start(error: { _ in - Logger.shared.log("InAppPurchaseManager", "Transaction \(transaction.transactionIdentifier ?? "") failed to assign AppStore transaction") - queue.finishTransaction(transaction) - }, completed: { - Logger.shared.log("InAppPurchaseManager", "Transaction \(transaction.transactionIdentifier ?? "") successfully assigned AppStore transaction") - queue.finishTransaction(transaction) - }), - forKey: transactionIdentifier - ) - } case .failed: Logger.shared.log("InAppPurchaseManager", "Transaction \(transaction.transactionIdentifier ?? "") failed \((transaction.error as? SKError)?.localizedDescription ?? "")") transactionState = .failed(error: transaction.error as? SKError) @@ -268,6 +256,15 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { Logger.shared.log("InAppPurchaseManager", "Transactions restoration finished") onRestoreCompletion(.succeed) self.onRestoreCompletion = nil + + if let receiptData = getReceiptData() { + self.disposableSet.set( + self.engine.payments.sendAppStoreReceipt(receipt: receiptData, restore: true).start(completed: { + Logger.shared.log("InAppPurchaseManager", "Sent restored receipt") + }), + forKey: "restore" + ) + } } } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index c94edaa4c3..3f057038ef 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -6227,13 +6227,12 @@ public extension Api.functions.messages { } } public extension Api.functions.payments { - static func assignAppStoreTransaction(flags: Int32, transactionId: String, receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func assignAppStoreTransaction(flags: Int32, receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(267129798) + buffer.appendInt32(224186320) serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(transactionId, buffer: buffer, boxed: false) serializeBytes(receipt, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("transactionId", String(describing: transactionId)), ("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 3bd555de53..8dd0f98cef 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -8,12 +8,12 @@ public enum AssignAppStoreTransactionError { case generic } -func _internal_assignAppStoreTransaction(account: Account, transactionId: String, receipt: Data, restore: Bool) -> Signal { +func _internal_sendAppStoreReceipt(account: Account, receipt: Data, restore: Bool) -> Signal { var flags: Int32 = 0 if restore { flags |= (1 << 0) } - return account.network.request(Api.functions.payments.assignAppStoreTransaction(flags: flags, transactionId: transactionId, receipt: Buffer(data: receipt))) + return account.network.request(Api.functions.payments.assignAppStoreTransaction(flags: flags, receipt: Buffer(data: receipt))) |> mapError { _ -> AssignAppStoreTransactionError in return .generic } @@ -23,6 +23,10 @@ func _internal_assignAppStoreTransaction(account: Account, transactionId: String } } +public enum RestoreAppStoreReceiptError { + case generic +} + func _internal_canPurchasePremium(account: Account) -> Signal { return account.network.request(Api.functions.payments.canPurchasePremium()) |> map { result -> Bool in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index cf33ea9cbd..8afeb78d59 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -38,8 +38,8 @@ public extension TelegramEngine { return _internal_clearBotPaymentInfo(network: self.account.network, info: info) } - public func assignAppStoreTransaction(transactionId: String, receipt: Data, restore: Bool) -> Signal { - return _internal_assignAppStoreTransaction(account: self.account, transactionId: transactionId, receipt: receipt, restore: restore) + public func sendAppStoreReceipt(receipt: Data, restore: Bool) -> Signal { + return _internal_sendAppStoreReceipt(account: self.account, receipt: receipt, restore: restore) } public func canPurchasePremium() -> Signal {