taler-ios

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

commit 0353dcaea3e0aea4e1aeaca2158e2c4701b5cbf8
parent bdcb5d615442507d066b0036983abc8205ce3923
Author: Marc Stibane <marc@taler.net>
Date:   Thu,  6 Jul 2023 18:01:01 +0200

Payment model uses transactionID

Diffstat:
MTalerWallet1/Model/Model+Payment.swift | 112+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
MTalerWallet1/Views/Payment/PaymentURIView.swift | 61+++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 107 insertions(+), 66 deletions(-)

diff --git a/TalerWallet1/Model/Model+Payment.swift b/TalerWallet1/Model/Model+Payment.swift @@ -9,48 +9,72 @@ import AnyCodable fileprivate let ASYNCDELAY: UInt = 0 //set e.g to 6 or 9 seconds for debugging // MARK: - ContractTerms -struct ContractTerms: Codable { - let amount: Amount - let maxFee: Amount - let maxWireFee: Amount + +// export interface TalerProtocolDuration { +// readonly d_us: number | "forever"; +// } + +struct MerchantContractTerms: Codable { + let hWire: String // Hash of the merchant's wire details +// let autoRefund: String? // TODO: TalerProtocolDuration + let wireMethod: String // merchant wants to use + let summary: String // Human-readable short summary of the contract + let summaryI18n: String? // " localized " + let nonce: String // used to ensure freshness + let amount: Amount // Total amount payable + let payDeadline: Timestamp // Deadline to pay for the contract + let maxFee: Amount // Maximum deposit fee covered by the merchant let merchant: Merchant - let extra: Extra - let summary: String - let timestamp: Timestamp - let payDeadline: Timestamp - let refundDeadline: Timestamp - let wireTransferDeadline: Timestamp - let merchantBaseURL: String - let fulfillmentURL: String - let publicReorderURL: String - let auditors: [Auditor] + let merchantPub: String // Public key of the merchant + let deliveryDate: Timestamp? // indicating when the order should be delivered + let deliveryLocation: Location? // Delivery location for (all!) products let exchanges: [ExchangeForPay] - let orderID, nonce, merchantPub: String - let products: [Product] - let hWire: String - let wireMethod: String - let wireFeeAmortization: Int + let products: [Product]? // Products that are sold in this contract + let refundDeadline: Timestamp // Deadline for refunds + let wireTransferDeadline: Timestamp // Deadline for the wire transfer + let timestamp: Timestamp // Time when the contract was generated by the merchant + let orderID: String // uniquely identify the purchase within one merchant instance + let merchantBaseURL: String // Base URL of the merchant's backend + let fulfillmentURL: String? // Fulfillment URL to view the product or delivery status + let publicReorderURL: String? // URL meant to share the shopping cart + let fulfillmentMessage: String? // Plain text fulfillment message in the merchant's default language + let fulfillmentMessageI18n: String? // Plain text fulfillment message in the merchant's default language + let wireFeeAmortization: Int? // Share of the wire fee that must be settled with one payment + let maxWireFee: Amount? // Maximum wire fee that the merchant agrees to pay for + let minimumAge: Int? + let extra: Extra // Extra data, interpreted by the mechant only +// let auditors: [Auditor]? enum CodingKeys: String, CodingKey { + case hWire = "h_wire" +// case autoRefund = "auto_refund" + case wireMethod = "wire_method" + case summary + case summaryI18n = "summary_i18n" + case nonce case amount - case maxFee = "max_fee" - case maxWireFee = "max_wire_fee" - case merchant, extra, summary - case timestamp case payDeadline = "pay_deadline" + case maxFee = "max_fee" + case merchant + case merchantPub = "merchant_pub" + case deliveryDate = "delivery_date" + case deliveryLocation = "delivery_location" + case exchanges + case products case refundDeadline = "refund_deadline" case wireTransferDeadline = "wire_transfer_deadline" + case timestamp + case orderID = "order_id" case merchantBaseURL = "merchant_base_url" case fulfillmentURL = "fulfillment_url" case publicReorderURL = "public_reorder_url" - case auditors, exchanges - case orderID = "order_id" - case nonce - case merchantPub = "merchant_pub" - case products - case hWire = "h_wire" - case wireMethod = "wire_method" + case fulfillmentMessage = "fulfillment_message" + case fulfillmentMessageI18n = "fulfillment_message_i18n" case wireFeeAmortization = "wire_fee_amortization" + case maxWireFee = "max_wire_fee" + case minimumAge = "minimum_age" + case extra +// case auditors } } // MARK: - Auditor @@ -77,20 +101,28 @@ struct ExchangeForPay: Codable { } // MARK: - Extra struct Extra: Codable { - let articleName: String + let articleName: String? enum CodingKeys: String, CodingKey { case articleName = "article_name" } } // MARK: - +enum PreparePayResultType: String, Codable { + case paymentPossible = "payment-possible" + case alreadyConfirmed = "already-confirmed" + case insufficientBalance = "insufficient-balance" +} + /// The result from PreparePayForUri struct PaymentDetailsForUri: Codable { + let status: PreparePayResultType + let transactionId: String + let contractTerms: MerchantContractTerms + let contractTermsHash: String let amountRaw: Amount let amountEffective: Amount - let proposalId: String - let contractTerms: ContractTerms - let contractTermsHash: String + let talerUri: String } /// A request to get an exchange's payment contract terms. fileprivate struct PreparePayForUri: WalletBackendFormattedRequest { @@ -107,18 +139,18 @@ fileprivate struct PreparePayForUri: WalletBackendFormattedRequest { /// The result from confirmPayForUri struct ConfirmPayResult: Decodable { var type: String - var contractTerms: ContractTerms + var contractTerms: MerchantContractTerms var transactionId: String } /// A request to get an exchange's payment details. fileprivate struct confirmPayForUri: WalletBackendFormattedRequest { typealias Response = ConfirmPayResult func operation() -> String { return "confirmPay" } - func args() -> Args { return Args(proposalId: proposalId) } + func args() -> Args { return Args(transactionId: transactionId) } - var proposalId: String + var transactionId: String struct Args: Encodable { - var proposalId: String + var transactionId: String } } // MARK: - @@ -132,9 +164,9 @@ extension WalletModel { return response } @MainActor - func confirmPayM(_ proposalId: String) // M for MainActor + func confirmPayM(_ transactionId: String) // M for MainActor async throws -> ConfirmPayResult { - let request = confirmPayForUri(proposalId: proposalId) + let request = confirmPayForUri(transactionId: transactionId) let response = try await sendRequest(request, ASYNCDELAY) return response } diff --git a/TalerWallet1/Views/Payment/PaymentURIView.swift b/TalerWallet1/Views/Payment/PaymentURIView.swift @@ -22,7 +22,7 @@ struct PaymentURIView: View { func acceptAction(detailsForUri: PaymentDetailsForUri) { Task { do { - let confirmPayResult = try await model.confirmPayM(detailsForUri.proposalId) + let confirmPayResult = try await model.confirmPayM(detailsForUri.transactionId) symLog.log(confirmPayResult as Any) if confirmPayResult.type != "done" { controller.playSound(0) @@ -85,34 +85,43 @@ struct PaymentURIView_Previews: PreviewProvider { let merchant = Merchant(name: "Merchant") let extra = Extra(articleName: "articleName") let product = Product(description: "description") - let terms = ContractTerms(amount: try! Amount(fromString: LONGCURRENCY + ":2.2"), - maxFee: try! Amount(fromString: LONGCURRENCY + ":0.2"), - maxWireFee: try! Amount(fromString: LONGCURRENCY + ":0.2"), - merchant: merchant, - extra: extra, - summary: "summary", - timestamp: Timestamp.now(), - payDeadline: Timestamp.tomorrow(), - refundDeadline: Timestamp.tomorrow(), - wireTransferDeadline: Timestamp.tomorrow(), - merchantBaseURL: "merchantBaseURL", - fulfillmentURL: "fulfillmentURL", - publicReorderURL: "publicReorderURL", - auditors: [], - exchanges: [], - orderID: "orderID", - nonce: "nonce", - merchantPub: "merchantPub", - products: [product], - hWire: "hWire", - wireMethod: "wireMethod", - wireFeeAmortization: 0) + let terms = MerchantContractTerms(hWire: "hWire", + wireMethod: "wireMethod", + summary: "summary", + summaryI18n: nil, + nonce: "nonce", + amount: try! Amount(fromString: LONGCURRENCY + ":2.2"), + payDeadline: Timestamp.tomorrow(), + maxFee: try! Amount(fromString: LONGCURRENCY + ":0.2"), + merchant: merchant, + merchantPub: "merchantPub", + deliveryDate: nil, + deliveryLocation: nil, + exchanges: [], + products: [product], + refundDeadline: Timestamp.tomorrow(), + wireTransferDeadline: Timestamp.tomorrow(), + timestamp: Timestamp.now(), + orderID: "orderID", + merchantBaseURL: "merchantBaseURL", + fulfillmentURL: "fulfillmentURL", + publicReorderURL: "publicReorderURL", + fulfillmentMessage: nil, + fulfillmentMessageI18n: nil, + wireFeeAmortization: 0, + maxWireFee: try! Amount(fromString: LONGCURRENCY + ":0.2"), + minimumAge: nil, + extra: extra +// auditors: [], + ) let details = PaymentDetailsForUri( + status: PreparePayResultType.paymentPossible, + transactionId: "txn:payment:012345", + contractTerms: terms, + contractTermsHash: "termsHash", amountRaw: try! Amount(fromString: LONGCURRENCY + ":2.2"), amountEffective: try! Amount(fromString: LONGCURRENCY + ":2.4"), - proposalId: "proposalId", - contractTerms: terms, - contractTermsHash: "termsHash" + talerUri: "talerURI" ) let url = URL(string: "taler://pay/some_amount")!