taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit 6482d336af029312de847f0f654e66b895551fc8
parent 5cc946bd500235cbd9fbc59b72162bd2b201a69f
Author: Marc Stibane <marc@taler.net>
Date:   Tue, 28 Nov 2023 11:00:41 +0100

Refund

Diffstat:
MTalerWallet.xcodeproj/project.pbxproj | 20++++++++++++++++++++
MTalerWallet1/Controllers/Controller.swift | 3+++
ATalerWallet1/Model/Model+Refund.swift | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTalerWallet1/Model/Transaction.swift | 5+++--
ATalerWallet1/Views/Sheets/Refund/RefundURIView.swift | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MTalerWallet1/Views/Sheets/URLSheet.swift | 2++
MTalerWallet1/Views/Transactions/TransactionRowView.swift | 8++++----
7 files changed, 146 insertions(+), 6 deletions(-)

diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj @@ -246,6 +246,10 @@ 4EFA39612AA7946B00742548 /* ToSButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EFA395F2AA7946B00742548 /* ToSButtonView.swift */; }; ABC13AA32859962800D23185 /* taler-swift in Frameworks */ = {isa = PBXBuildFile; productRef = ABC13AA22859962800D23185 /* taler-swift */; }; ABE97B1D286D82BF00580772 /* AnyCodable in Frameworks */ = {isa = PBXBuildFile; productRef = ABE97B1C286D82BF00580772 /* AnyCodable */; }; + E37AA62A2AF197E5003850CF /* Model+Refund.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA6292AF197E5003850CF /* Model+Refund.swift */; }; + E37AA62B2AF197E5003850CF /* Model+Refund.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA6292AF197E5003850CF /* Model+Refund.swift */; }; + E37AA62E2AF19BE0003850CF /* RefundURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift */; }; + E37AA62F2AF19BE0003850CF /* RefundURIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37AA62D2AF19BE0003850CF /* RefundURIView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -413,6 +417,8 @@ D14AFD1D24D232B300C51073 /* Taler_Wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Taler_Wallet.app; sourceTree = BUILT_PRODUCTS_DIR; }; D14AFD3324D232B500C51073 /* TalerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TalerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D14AFD3E24D232B500C51073 /* TalerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TalerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + E37AA6292AF197E5003850CF /* Model+Refund.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Model+Refund.swift"; sourceTree = "<group>"; }; + E37AA62D2AF19BE0003850CF /* RefundURIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundURIView.swift; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -607,6 +613,7 @@ 4ECB627F2A0BA6DF004ABBB7 /* Model+P2P.swift */, 4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift */, 4EB0952C2989CBFE0043A8A1 /* Model+Payment.swift */, + E37AA6292AF197E5003850CF /* Model+Refund.swift */, 4EB095102989CBB00043A8A1 /* Model+Settings.swift */, 4EB095322989CBFE0043A8A1 /* Model+Transactions.swift */, 4EB0953D2989CBFE0043A8A1 /* Model+Withdraw.swift */, @@ -765,6 +772,7 @@ 4EB095332989CBFE0043A8A1 /* URLSheet.swift */, 4EB0953B2989CBFE0043A8A1 /* WithdrawBankIntegrated */, 4EB0952A2989CBFE0043A8A1 /* Payment */, + E37AA62C2AF19BA6003850CF /* Refund */, 4E3B4BBF2A41E64000CC88B8 /* P2P_Sheets */, ); path = Sheets; @@ -813,6 +821,14 @@ path = TalerUITests; sourceTree = "<group>"; }; + E37AA62C2AF19BA6003850CF /* Refund */ = { + isa = PBXGroup; + children = ( + E37AA62D2AF19BE0003850CF /* RefundURIView.swift */, + ); + path = Refund; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1091,6 +1107,7 @@ 4E3EAE5C2A990778009F1BE8 /* Model+Pending.swift in Sources */, 4E3EAE5D2A990778009F1BE8 /* ExchangeListView.swift in Sources */, 4E3EAE5E2A990778009F1BE8 /* WithdrawProgressView.swift in Sources */, + E37AA62E2AF19BE0003850CF /* RefundURIView.swift in Sources */, 4E3EAE5F2A990778009F1BE8 /* QRSheet.swift in Sources */, 4E3EAE602A990778009F1BE8 /* P2pReceiveURIView.swift in Sources */, 4E3EAE612A990778009F1BE8 /* ListStyle.swift in Sources */, @@ -1098,6 +1115,7 @@ 4E3EAE632A990778009F1BE8 /* WalletCore.swift in Sources */, 4E3EAE642A990778009F1BE8 /* LaunchAnimationView.swift in Sources */, 4E3EAE652A990778009F1BE8 /* SideBarView.swift in Sources */, + E37AA62A2AF197E5003850CF /* Model+Refund.swift in Sources */, 4E3EAE682A990778009F1BE8 /* WalletModel.swift in Sources */, 4E3EAE692A990778009F1BE8 /* URLSheet.swift in Sources */, 4E3EAE6A2A990778009F1BE8 /* ThreeAmountsV.swift in Sources */, @@ -1196,6 +1214,7 @@ 4EB0956E2989CBFE0043A8A1 /* Model+Pending.swift in Sources */, 4EB095522989CBFE0043A8A1 /* ExchangeListView.swift in Sources */, 4EB095642989CBFE0043A8A1 /* WithdrawProgressView.swift in Sources */, + E37AA62F2AF19BE0003850CF /* RefundURIView.swift in Sources */, 4EEC157A29F9427F00D46A03 /* QRSheet.swift in Sources */, 4E3B4BC12A41E6C200CC88B8 /* P2pReceiveURIView.swift in Sources */, 4E6EDD872A363D8D0031D520 /* ListStyle.swift in Sources */, @@ -1203,6 +1222,7 @@ 4EB095202989CBCB0043A8A1 /* WalletCore.swift in Sources */, 4EB095672989CBFE0043A8A1 /* LaunchAnimationView.swift in Sources */, 4EB095662989CBFE0043A8A1 /* SideBarView.swift in Sources */, + E37AA62B2AF197E5003850CF /* Model+Refund.swift in Sources */, 4EB095162989CBB00043A8A1 /* WalletModel.swift in Sources */, 4EB0955A2989CBFE0043A8A1 /* URLSheet.swift in Sources */, 4ED2F94B2A278F5100453B40 /* ThreeAmountsV.swift in Sources */, diff --git a/TalerWallet1/Controllers/Controller.swift b/TalerWallet1/Controllers/Controller.swift @@ -24,6 +24,7 @@ enum UrlCommand { case payPull case payPush case payTemplate + case refund case reward } @@ -166,6 +167,8 @@ extension Controller { return UrlCommand.payPush case "pay-template": return UrlCommand.payTemplate + case "refund": + return UrlCommand.refund default: symLog.log("unknown command taler://\(command)") } diff --git a/TalerWallet1/Model/Model+Refund.swift b/TalerWallet1/Model/Model+Refund.swift @@ -0,0 +1,54 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import Foundation +fileprivate let ASYNCDELAY: UInt = 0 //set e.g to 6 or 9 seconds for debugging + +// MARK: - +/// A request to prepare a refund with an obtained URI +struct StartRefundURIRequest: WalletBackendFormattedRequest { + func operation() -> String { "startRefundQueryForUri" } + func args() -> Args { Args(talerRefundUri: talerRefundUri) } + + var talerRefundUri: String + + struct Args: Encodable { + var talerRefundUri: String + } + + /// returns the txID of the new refund + struct Response: Decodable { + var transactionId: String + } +} + +/// A request to prepare a refund with a transactionID +struct StartRefundQueryRequest: WalletBackendFormattedRequest { + func operation() -> String { "startRefundQuery" } + func args() -> Args { Args(transactionId: transactionId) } + + var transactionId: String + + struct Args: Encodable { + var transactionId: String + } + + /// no error means the refunds was successful + struct Response: Decodable {} +} +// MARK: - +extension WalletModel { + @MainActor + func startRefundForUriM(url: String) async throws -> String { + let request = StartRefundURIRequest(talerRefundUri: url) + let response = try await sendRequest(request, ASYNCDELAY) + return response.transactionId + } + + @MainActor + func startRefundM(transactionId: String) async throws { + let request = StartRefundQueryRequest(transactionId: transactionId) + let _ = try await sendRequest(request, ASYNCDELAY) + } +} diff --git a/TalerWallet1/Model/Transaction.swift b/TalerWallet1/Model/Transaction.swift @@ -266,13 +266,14 @@ struct WithdrawalTransaction : Sendable{ } struct PaymentTransactionDetails: Decodable { + var info: OrderShortInfo var proposalId: String var totalRefundRaw: Amount var totalRefundEffective: Amount var refundPending: Amount? + var refunds: [String]? // array of refund txIDs for this payment var refundQueryActive: Bool? - var refunds: [String]? // TODO: array type? - var info: OrderShortInfo + var posConfirmation: String? } struct PaymentTransaction : Sendable{ diff --git a/TalerWallet1/Views/Sheets/Refund/RefundURIView.swift b/TalerWallet1/Views/Sheets/Refund/RefundURIView.swift @@ -0,0 +1,60 @@ +/* + * This file is part of GNU Taler, ©2022-23 Taler Systems S.A. + * See LICENSE.md + */ +import SwiftUI +import SymLog +import taler_swift + +struct RefundURIView: View { + private let symLog = SymLogV(0) + let stack: CallStack + let url: URL + + @EnvironmentObject private var model: WalletModel + +// let navTitle = String(localized: "Refund", comment:"receive refund") + + @State var refundTransactionId: String? = nil + + func reloadOneAction(_ transactionId: String) async throws -> Transaction { + return try await model.getTransactionByIdT(transactionId) + } + + var body: some View { + if let refundTransactionId { + TransactionDetailView(stack: stack.push(), + transactionId: refundTransactionId, + reloadAction: reloadOneAction, + navTitle: nil, // navTitle, + doneAction: ViewState.shared.popToRootView, + abortAction: model.abortTransaction, + deleteAction: model.deleteTransaction, + failAction: model.failTransaction, + suspendAction: model.suspendTransaction, + resumeAction: model.resumeTransaction) + } else { + let badURL = "Error in Link: \(url)" + WithdrawProgressView(message: url.host ?? badURL) + .navigationTitle("Find Exchange") + .task { + do { + symLog.log(".task") + let result = try await model.startRefundForUriM(url: url.absoluteString) + refundTransactionId = result + } catch { // TODO: error + symLog.log(error.localizedDescription) + } + } + } + } +} + +// MARK: - +struct RefundURIView_Previews: PreviewProvider { + static var previews: some View { + let transactionId = "txn:refund:12345" + let url = URL(string: "taler://reward/survey")! + RefundURIView(stack: CallStack("Preview"), url: url, refundTransactionId: transactionId) + } +} diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift b/TalerWallet1/Views/Sheets/URLSheet.swift @@ -32,6 +32,8 @@ struct URLSheet: View { P2pReceiveURIView(stack: stack.push(), url: urlToOpen) case .payTemplate: PayTemplateView(stack: stack.push(), url: urlToOpen) + case .refund: + RefundURIView(stack: stack.push(), url: urlToOpen) // case .reward: // RewardURIView(url: urlToOpen) default: // Error view diff --git a/TalerWallet1/Views/Transactions/TransactionRowView.swift b/TalerWallet1/Views/Transactions/TransactionRowView.swift @@ -190,10 +190,10 @@ extension Transaction { // for PreViews merchant: merchant, summary: "some product summary", products: []) - let pDetails = PaymentTransactionDetails(proposalId: "some proposal ID", - totalRefundRaw: Amount(currency: LONGCURRENCY, cent: 300), - totalRefundEffective: Amount(currency: LONGCURRENCY, cent: 280), - info: info) + let pDetails = PaymentTransactionDetails(info: info, + proposalId: "some proposal ID", + totalRefundRaw: Amount(currency: LONGCURRENCY, cent: 300), + totalRefundEffective: Amount(currency: LONGCURRENCY, cent: 280)) self = .payment(PaymentTransaction(common: common, details: pDetails)) } }