From d96dba9b873906c7af0e80ebcdfed9d778e3ce01 Mon Sep 17 00:00:00 2001 From: Ricardo Silva <97543217+OS-ricardomoreirasilva@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:44:56 +0000 Subject: [PATCH] Feat: Add Gateway property to OSPMTDetailsModel (#12) Add `gateway` property to `OSPMTDetailsModel` struct. When authorising payment, confirm that this property corresponds to a configured gateway (on plist). --- OSPaymentsLib/Error/OSPMTError.swift | 3 ++ OSPaymentsLib/Gateways/OSPMTGateway.swift | 5 ++- OSPaymentsLib/Models/OSPMTDetailsModel.swift | 9 +++- .../Protocols/OSPMTRequestDelegate.swift | 44 +++++++++---------- docs/CHANGELOG.md | 3 ++ 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/OSPaymentsLib/Error/OSPMTError.swift b/OSPaymentsLib/Error/OSPMTError.swift index 99edc3b..da13d1d 100644 --- a/OSPaymentsLib/Error/OSPMTError.swift +++ b/OSPaymentsLib/Error/OSPMTError.swift @@ -14,6 +14,7 @@ public enum OSPMTError: Int, CustomNSError, LocalizedError { case gatewaySetFailed = 12 case stripePaymentMethodCreation = 13 case paymentIssue = 14 + case gatewayNotConfigured = 15 /// Textual description public var errorDescription: String? { @@ -41,6 +42,8 @@ public enum OSPMTError: Int, CustomNSError, LocalizedError { return "Couldn't obtain the PaymentMethod from Stripe." case .paymentIssue: return "Couldn't process payment." + case .gatewayNotConfigured: + return "Couldn't trigger the payment because the requested payment service provider is not configured." } } } diff --git a/OSPaymentsLib/Gateways/OSPMTGateway.swift b/OSPaymentsLib/Gateways/OSPMTGateway.swift index 8626d60..b62ae05 100644 --- a/OSPaymentsLib/Gateways/OSPMTGateway.swift +++ b/OSPaymentsLib/Gateways/OSPMTGateway.swift @@ -8,7 +8,8 @@ extension OSPMTGateway { /// Converts a string into a `OSPMTGateway` object. /// - Parameter text: Text to convert. /// - Returns: A `OSPMTGateway` enum object if successful. `nil` is returned in case of error. - static func convert(from text: String) -> OSPMTGateway? { - return text.lowercased() == "stripe" ? .stripe : nil + static func convert(from text: String?) -> OSPMTGateway? { + guard let text = text, text.lowercased() == "stripe" else { return nil } + return .stripe } } diff --git a/OSPaymentsLib/Models/OSPMTDetailsModel.swift b/OSPaymentsLib/Models/OSPMTDetailsModel.swift index a991c3b..00989f2 100644 --- a/OSPaymentsLib/Models/OSPMTDetailsModel.swift +++ b/OSPaymentsLib/Models/OSPMTDetailsModel.swift @@ -47,6 +47,7 @@ struct OSPMTDetailsModel: Decodable { let status: OSPMTStatus let shippingContact: OSPMTContact let billingContact: OSPMTContact + let gateway: OSPMTGateway? /// Keys used to encode and decode the model. enum CodingKeys: String, CodingKey { @@ -55,6 +56,7 @@ struct OSPMTDetailsModel: Decodable { case status case shippingContact = "shippingContacts" case billingContact = "billingContacts" + case gateway = "psp" } /// Constructor method. @@ -64,12 +66,14 @@ struct OSPMTDetailsModel: Decodable { /// - status: Final value status. /// - shippingContact: Shipping properties required for filling. /// - billingContact: Billiing properties required for filling. - init(amount: Decimal, currency: String, status: OSPMTStatus, shippingContact: OSPMTContact, billingContact: OSPMTContact) { + /// - gateway: Payment service provided to be used for processing, if passed. + init(amount: Decimal, currency: String, status: OSPMTStatus, shippingContact: OSPMTContact, billingContact: OSPMTContact, gateway: String? = nil) { self.amount = amount self.currency = currency self.status = status self.shippingContact = shippingContact self.billingContact = billingContact + self.gateway = OSPMTGateway.convert(from: gateway) } /// Creates a new instance by decoding from the given decoder. @@ -85,8 +89,9 @@ struct OSPMTDetailsModel: Decodable { let status = try container.decode(OSPMTStatus.self, forKey: .status) let shippingContact = try container.decode(OSPMTContact.self, forKey: .shippingContact) let billingContact = try container.decode(OSPMTContact.self, forKey: .billingContact) + let gateway = try container.decodeIfPresent(String.self, forKey: .gateway) self.init( - amount: amount, currency: currency, status: status, shippingContact: shippingContact, billingContact: billingContact + amount: amount, currency: currency, status: status, shippingContact: shippingContact, billingContact: billingContact, gateway: gateway ) } } diff --git a/OSPaymentsLib/Protocols/OSPMTRequestDelegate.swift b/OSPaymentsLib/Protocols/OSPMTRequestDelegate.swift index c386c84..c8b4d5e 100644 --- a/OSPaymentsLib/Protocols/OSPMTRequestDelegate.swift +++ b/OSPaymentsLib/Protocols/OSPMTRequestDelegate.swift @@ -112,15 +112,31 @@ extension OSPMTApplePayRequestBehaviour: PKPaymentAuthorizationControllerDelegat /// - payment: The authorized payment. This object contains the payment token you need to submit to your payment processor, as well as the billing and shipping information required by the payment request. /// - completion: The completion handler to call with the result of authorizing the payment. func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { - if let paymentGateway = self.configuration.gatewayModel { - guard let paymentDetails = self.paymentDetails, let gatewayWrapper = OSPMTGatewayFactory.createWrapper(for: paymentGateway) + func setPaymentResults(with errorArray: [OSPMTError], and scopeModel: OSPMTScopeModel?, _ completion: @escaping (PKPaymentAuthorizationResult) -> Void) { + if errorArray.isEmpty, let scopeModel = scopeModel { + self.paymentScope = scopeModel + self.paymentStatus = .success + } else { + self.paymentScope = nil + self.paymentStatus = .failure + } + + completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: errorArray)) + } + + if let paymentDetails = paymentDetails, paymentDetails.gateway != nil { + guard let paymentGateway = self.configuration.gatewayModel, paymentGateway.gatewayEnum == paymentDetails.gateway else { + completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: [OSPMTError.gatewayNotConfigured])) + return + } + + guard let gatewayWrapper = OSPMTGatewayFactory.createWrapper(for: paymentGateway) else { completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: [OSPMTError.gatewaySetFailed])) return } - gatewayWrapper.process(payment, with: paymentDetails) { [weak self] result in - guard let self = self else { return } + gatewayWrapper.process(payment, with: paymentDetails) { result in var errorArray = [OSPMTError]() var paymentResultModel: OSPMTServiceProviderInfoModel? @@ -131,26 +147,10 @@ extension OSPMTApplePayRequestBehaviour: PKPaymentAuthorizationControllerDelegat errorArray += [error] } - if errorArray.isEmpty, let scopeModel = payment.createScopeModel(for: paymentResultModel) { - self.paymentScope = scopeModel - self.paymentStatus = .success - } else { - self.paymentScope = nil - self.paymentStatus = .failure - } - - completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: errorArray)) + setPaymentResults(with: errorArray, and: payment.createScopeModel(for: paymentResultModel), completion) } } else { - if let scopeModel = payment.createScopeModel() { - self.paymentScope = scopeModel - self.paymentStatus = .success - } else { - self.paymentScope = nil - self.paymentStatus = .failure - } - - completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: [])) + setPaymentResults(with: [], and: payment.createScopeModel(), completion) } } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ba549f7..f62c308 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### 2022-12-12 +- Feat: Add Payment Service Provider property to `OSPMTDetailsModel` struct (https://outsystemsrd.atlassian.net/browse/RMET-2095). + ### 2022-12-02 - Feat: Add Stripe as Payment Service Provider (https://outsystemsrd.atlassian.net/browse/RMET-2078).