mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Merge commit '8f6767c010a78a1d5dad2b8172561095d828ab90'
This commit is contained in:
@@ -119,8 +119,8 @@ public struct BotPaymentForm : Equatable {
|
||||
public let passwordMissing: Bool
|
||||
public let invoice: BotPaymentInvoice
|
||||
public let paymentBotId: PeerId
|
||||
public let providerId: PeerId
|
||||
public let url: String
|
||||
public let providerId: PeerId?
|
||||
public let url: String?
|
||||
public let nativeProvider: BotPaymentNativeProvider?
|
||||
public let savedInfo: BotPaymentRequestedInfo?
|
||||
public let savedCredentials: [BotPaymentSavedCredentials]
|
||||
@@ -206,7 +206,7 @@ extension BotPaymentRequestedInfo {
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInvoiceSource) -> Api.InputInvoice? {
|
||||
func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInvoiceSource) -> Api.InputInvoice? {
|
||||
switch source {
|
||||
case let .message(messageId):
|
||||
guard let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) else {
|
||||
@@ -321,6 +321,9 @@ func _internal_fetchBotPaymentInvoice(postbox: Postbox, network: Network, source
|
||||
}
|
||||
|
||||
return TelegramMediaInvoice(title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), receiptMessageId: nil, currency: parsedInvoice.currency, totalAmount: 0, startParam: "", extendedMedia: nil, flags: parsedFlags, version: TelegramMediaInvoice.lastVersion)
|
||||
case let .paymentFormStars(_, _, _, title, description, photo, invoice, _):
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
return TelegramMediaInvoice(title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), receiptMessageId: nil, currency: parsedInvoice.currency, totalAmount: 0, startParam: "", extendedMedia: nil, flags: [], version: TelegramMediaInvoice.lastVersion)
|
||||
}
|
||||
}
|
||||
|> mapError { _ -> BotPaymentFormRequestError in }
|
||||
@@ -354,32 +357,43 @@ func _internal_fetchBotPaymentForm(accountPeerId: PeerId, postbox: Postbox, netw
|
||||
|> mapToSignal { result -> Signal<BotPaymentForm, BotPaymentFormRequestError> in
|
||||
return postbox.transaction { transaction -> BotPaymentForm in
|
||||
switch result {
|
||||
case let .paymentForm(flags, id, botId, title, description, photo, invoice, providerId, url, nativeProvider, nativeParams, additionalMethods, savedInfo, savedCredentials, apiUsers):
|
||||
let _ = title
|
||||
let _ = description
|
||||
let _ = photo
|
||||
|
||||
let parsedPeers = AccumulatedPeers(users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
case let .paymentForm(flags, id, botId, title, description, photo, invoice, providerId, url, nativeProvider, nativeParams, additionalMethods, savedInfo, savedCredentials, apiUsers):
|
||||
let _ = title
|
||||
let _ = description
|
||||
let _ = photo
|
||||
|
||||
let parsedPeers = AccumulatedPeers(users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
var parsedNativeProvider: BotPaymentNativeProvider?
|
||||
if let nativeProvider = nativeProvider, let nativeParams = nativeParams {
|
||||
switch nativeParams {
|
||||
case let .dataJSON(data):
|
||||
parsedNativeProvider = BotPaymentNativeProvider(name: nativeProvider, params: data)
|
||||
}
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
var parsedNativeProvider: BotPaymentNativeProvider?
|
||||
if let nativeProvider = nativeProvider, let nativeParams = nativeParams {
|
||||
switch nativeParams {
|
||||
case let .dataJSON(data):
|
||||
parsedNativeProvider = BotPaymentNativeProvider(name: nativeProvider, params: data)
|
||||
}
|
||||
let parsedSavedInfo = savedInfo.flatMap(BotPaymentRequestedInfo.init)
|
||||
let parsedSavedCredentials = savedCredentials?.map({ savedCredentials -> BotPaymentSavedCredentials in
|
||||
switch savedCredentials {
|
||||
case let .paymentSavedCredentialsCard(id, title):
|
||||
return .card(id: id, title: title)
|
||||
}
|
||||
}) ?? []
|
||||
}
|
||||
let parsedSavedInfo = savedInfo.flatMap(BotPaymentRequestedInfo.init)
|
||||
let parsedSavedCredentials = savedCredentials?.map({ savedCredentials -> BotPaymentSavedCredentials in
|
||||
switch savedCredentials {
|
||||
case let .paymentSavedCredentialsCard(id, title):
|
||||
return .card(id: id, title: title)
|
||||
}
|
||||
}) ?? []
|
||||
|
||||
let additionalPaymentMethods = additionalMethods?.map({ BotPaymentMethod(apiPaymentFormMethod: $0) }) ?? []
|
||||
return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials, additionalPaymentMethods: additionalPaymentMethods)
|
||||
let additionalPaymentMethods = additionalMethods?.map({ BotPaymentMethod(apiPaymentFormMethod: $0) }) ?? []
|
||||
return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials, additionalPaymentMethods: additionalPaymentMethods)
|
||||
case let .paymentFormStars(flags, id, botId, title, description, photo, invoice, apiUsers):
|
||||
let _ = flags
|
||||
let _ = title
|
||||
let _ = description
|
||||
let _ = photo
|
||||
|
||||
let parsedPeers = AccumulatedPeers(users: apiUsers)
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
|
||||
let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice)
|
||||
return BotPaymentForm(id: id, canSaveCredentials: false, passwordMissing: false, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: nil, url: nil, nativeProvider: nil, savedInfo: nil, savedCredentials: [], additionalPaymentMethods: [])
|
||||
}
|
||||
}
|
||||
|> mapError { _ -> BotPaymentFormRequestError in }
|
||||
|
||||
@@ -104,11 +104,8 @@ private func requestStarsState(account: Account, peerId: EnginePeer.Id, offset:
|
||||
|
||||
var parsedTransactions: [StarsContext.State.Transaction] = []
|
||||
for entry in history {
|
||||
switch entry {
|
||||
case let .starsTransaction(id, stars, date, peer):
|
||||
if let peer = transaction.getPeer(peer.peerId) {
|
||||
parsedTransactions.append(StarsContext.State.Transaction(id: id, count: stars, date: date, peer: EnginePeer(peer)))
|
||||
}
|
||||
if let parsedTransaction = StarsContext.State.Transaction(apiTransaction: entry, transaction: transaction) {
|
||||
parsedTransactions.append(parsedTransaction)
|
||||
}
|
||||
}
|
||||
return InternalStarsStatus(balance: balance, transactions: parsedTransactions, nextOffset: nextOffset)
|
||||
@@ -136,6 +133,7 @@ private final class StarsContextImpl {
|
||||
private var nextOffset: String?
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
private var updateDisposable: Disposable?
|
||||
|
||||
init(account: Account, peerId: EnginePeer.Id) {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
@@ -147,11 +145,20 @@ private final class StarsContextImpl {
|
||||
self._statePromise.set(.single(nil))
|
||||
|
||||
self.load()
|
||||
|
||||
self.updateDisposable = (account.stateManager.updatedStarsBalance()
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] balances in
|
||||
guard let self, let state = self._state, let balance = balances[peerId] else {
|
||||
return
|
||||
}
|
||||
self._state = StarsContext.State(balance: balance, transactions: state.transactions)
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
self.disposable.dispose()
|
||||
self.updateDisposable?.dispose()
|
||||
}
|
||||
|
||||
func load() {
|
||||
@@ -190,15 +197,45 @@ private final class StarsContextImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private extension StarsContext.State.Transaction {
|
||||
init?(apiTransaction: Api.StarsTransaction, transaction: Transaction) {
|
||||
switch apiTransaction {
|
||||
case let .starsTransaction(id, stars, date, transactionPeer):
|
||||
let parsedPeer: StarsContext.State.Transaction.Peer
|
||||
switch transactionPeer {
|
||||
case .starsTransactionPeerAppStore:
|
||||
parsedPeer = .appStore
|
||||
case .starsTransactionPeerPlayMarket:
|
||||
parsedPeer = .playMarket
|
||||
case .starsTransactionPeerFragment:
|
||||
parsedPeer = .fragment
|
||||
case let .starsTransactionPeer(apiPeer):
|
||||
guard let peer = transaction.getPeer(apiPeer.peerId) else {
|
||||
return nil
|
||||
}
|
||||
parsedPeer = .peer(EnginePeer(peer))
|
||||
}
|
||||
self.init(id: id, count: stars, date: date, peer: parsedPeer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class StarsContext {
|
||||
public struct State: Equatable {
|
||||
public struct Transaction: Equatable {
|
||||
public enum Peer: Equatable {
|
||||
case appStore
|
||||
case playMarket
|
||||
case fragment
|
||||
case peer(EnginePeer)
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public let count: Int64
|
||||
public let date: Int32
|
||||
public let peer: EnginePeer
|
||||
public let peer: Peer
|
||||
|
||||
init(id: String, count: Int64, date: Int32, peer: EnginePeer) {
|
||||
init(id: String, count: Int64, date: Int32, peer: Peer) {
|
||||
self.id = id
|
||||
self.count = count
|
||||
self.date = date
|
||||
@@ -245,3 +282,79 @@ public final class StarsContext {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputInvoice? in
|
||||
return _internal_parseInputInvoice(transaction: transaction, source: source)
|
||||
}
|
||||
|> castError(SendBotPaymentFormError.self)
|
||||
|> mapToSignal { invoice -> Signal<SendBotPaymentResult, SendBotPaymentFormError> in
|
||||
guard let invoice = invoice else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
let flags: Int32 = 0
|
||||
|
||||
return account.network.request(Api.functions.payments.sendStarsForm(flags: flags, formId: formId, invoice: invoice))
|
||||
|> map { result -> SendBotPaymentResult in
|
||||
switch result {
|
||||
case let .paymentResult(updates):
|
||||
account.stateManager.addUpdates(updates)
|
||||
var receiptMessageId: MessageId?
|
||||
for apiMessage in updates.messages {
|
||||
if let message = StoreMessage(apiMessage: apiMessage, accountPeerId: account.peerId, peerIsForum: false) {
|
||||
for media in message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
if case .paymentSent = action.action {
|
||||
switch source {
|
||||
case let .slug(slug):
|
||||
for media in message.media {
|
||||
if let action = media as? TelegramMediaAction, case let .paymentSent(_, _, invoiceSlug?, _, _) = action.action, invoiceSlug == slug {
|
||||
if case let .Id(id) = message.id {
|
||||
receiptMessageId = id
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .message(messageId):
|
||||
for attribute in message.attributes {
|
||||
if let reply = attribute as? ReplyMessageAttribute {
|
||||
if reply.messageId == messageId {
|
||||
if case let .Id(id) = message.id {
|
||||
receiptMessageId = id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .premiumGiveaway(_, _, _, _, _, _, randomId, _, _, _, _):
|
||||
if message.globallyUniqueId == randomId {
|
||||
if case let .Id(id) = message.id {
|
||||
receiptMessageId = id
|
||||
}
|
||||
}
|
||||
case .giftCode:
|
||||
receiptMessageId = nil
|
||||
case .stars:
|
||||
receiptMessageId = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return .done(receiptMessageId: receiptMessageId)
|
||||
case let .paymentVerificationNeeded(url):
|
||||
return .externalVerificationRequired(url: url)
|
||||
}
|
||||
}
|
||||
|> `catch` { error -> Signal<SendBotPaymentResult, SendBotPaymentFormError> in
|
||||
if error.errorDescription == "BOT_PRECHECKOUT_FAILED" {
|
||||
return .fail(.precheckoutFailed)
|
||||
} else if error.errorDescription == "PAYMENT_FAILED" {
|
||||
return .fail(.paymentFailed)
|
||||
} else if error.errorDescription == "INVOICE_ALREADY_PAID" {
|
||||
return .fail(.alreadyPaid)
|
||||
}
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ public extension TelegramEngine {
|
||||
public func sendBotPaymentForm(source: BotPaymentInvoiceSource, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
||||
return _internal_sendBotPaymentForm(account: self.account, formId: formId, source: source, validatedInfoId: validatedInfoId, shippingOptionId: shippingOptionId, tipAmount: tipAmount, credentials: credentials)
|
||||
}
|
||||
|
||||
|
||||
public func requestBotPaymentReceipt(messageId: MessageId) -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> {
|
||||
return _internal_requestBotPaymentReceipt(account: self.account, messageId: messageId)
|
||||
}
|
||||
@@ -73,5 +73,9 @@ public extension TelegramEngine {
|
||||
public func peerStarsContext(peerId: EnginePeer.Id) -> StarsContext {
|
||||
return StarsContext(account: self.account, peerId: peerId)
|
||||
}
|
||||
}
|
||||
|
||||
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
||||
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user