From 1c7c0f20e7da38f9dcd5d9ddffad9a04cec44d60 Mon Sep 17 00:00:00 2001 From: OS-ricardomoreirasilva Date: Fri, 11 Nov 2022 10:15:21 +0000 Subject: [PATCH 1/2] chore: replace OSPaymentsLib Remove all the OSPaymentsLib files and replace them by the new OSPaymentsPluginLib pod. --- plugin.xml | 27 +-- src/ios/Error/OSPMTError.swift | 33 --- .../Extensions/PKContactField+Adapter.swift | 21 -- .../PKMerchantCapability+Adapter.swift | 21 -- .../Extensions/PKPassLibrary+Adapter.swift | 9 - src/ios/Extensions/PKPayment+Adapter.swift | 93 -------- ...ymentAuthorizationController+Adapter.swift | 66 ------ .../Extensions/PKPaymentNetwork+Adapter.swift | 21 -- src/ios/Models/OSPMTAddressModel.swift | 74 ------- src/ios/Models/OSPMTConfigurationModel.swift | 198 ------------------ src/ios/Models/OSPMTContactInfoModel.swift | 72 ------- src/ios/Models/OSPMTDataModel.swift | 75 ------- src/ios/Models/OSPMTDetailsModel.swift | 103 --------- src/ios/Models/OSPMTScopeModel.swift | 62 ------ src/ios/Models/OSPMTTokenInfoModel.swift | 47 ----- src/ios/OSPMTApplePayHandler.swift | 58 ----- src/ios/OSPMTPayments.swift | 95 --------- src/ios/OSPayments.swift | 3 +- src/ios/Protocols/OSPMTActionDelegate.swift | 12 -- .../Protocols/OSPMTAvailabilityDelegate.swift | 98 --------- src/ios/Protocols/OSPMTCallbackDelegate.swift | 24 --- src/ios/Protocols/OSPMTHandlerDelegate.swift | 18 -- src/ios/Protocols/OSPMTRequestDelegate.swift | 123 ----------- 23 files changed, 3 insertions(+), 1350 deletions(-) delete mode 100644 src/ios/Error/OSPMTError.swift delete mode 100644 src/ios/Extensions/PKContactField+Adapter.swift delete mode 100644 src/ios/Extensions/PKMerchantCapability+Adapter.swift delete mode 100644 src/ios/Extensions/PKPassLibrary+Adapter.swift delete mode 100644 src/ios/Extensions/PKPayment+Adapter.swift delete mode 100644 src/ios/Extensions/PKPaymentAuthorizationController+Adapter.swift delete mode 100644 src/ios/Extensions/PKPaymentNetwork+Adapter.swift delete mode 100644 src/ios/Models/OSPMTAddressModel.swift delete mode 100644 src/ios/Models/OSPMTConfigurationModel.swift delete mode 100644 src/ios/Models/OSPMTContactInfoModel.swift delete mode 100644 src/ios/Models/OSPMTDataModel.swift delete mode 100644 src/ios/Models/OSPMTDetailsModel.swift delete mode 100644 src/ios/Models/OSPMTScopeModel.swift delete mode 100644 src/ios/Models/OSPMTTokenInfoModel.swift delete mode 100644 src/ios/OSPMTApplePayHandler.swift delete mode 100644 src/ios/OSPMTPayments.swift delete mode 100644 src/ios/Protocols/OSPMTActionDelegate.swift delete mode 100644 src/ios/Protocols/OSPMTAvailabilityDelegate.swift delete mode 100644 src/ios/Protocols/OSPMTCallbackDelegate.swift delete mode 100644 src/ios/Protocols/OSPMTHandlerDelegate.swift delete mode 100644 src/ios/Protocols/OSPMTRequestDelegate.swift diff --git a/plugin.xml b/plugin.xml index 1801c8f..bcf613c 100644 --- a/plugin.xml +++ b/plugin.xml @@ -100,32 +100,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -134,6 +108,7 @@ + diff --git a/src/ios/Error/OSPMTError.swift b/src/ios/Error/OSPMTError.swift deleted file mode 100644 index be763b9..0000000 --- a/src/ios/Error/OSPMTError.swift +++ /dev/null @@ -1,33 +0,0 @@ -/// All plugin errors that can be thrown -enum OSPMTError: Int, CustomNSError, LocalizedError { - case invalidConfiguration = 1 - case walletNotAvailable = 3 - case paymentNotAvailable = 5 - case setupPaymentNotAvailable = 6 - case invalidDecodeDetails = 8 - case invalidEncodeScope = 9 - case paymentTriggerPresentationFailed = 10 - case paymentCancelled = 11 - - /// Textual description - var errorDescription: String? { - switch self { - case .invalidConfiguration: - return "Couldn't obtain the payment's informations from the configurations file." - case .walletNotAvailable: - return "The Apple Pay is not available in the device." - case .paymentNotAvailable: - return "There is no payment method configured." - case .setupPaymentNotAvailable: - return "There are no valid payment cards for the supported networks and/or capabilities." - case .invalidDecodeDetails: - return "Couldn't decode the payment details." - case .invalidEncodeScope: - return "Couldn't encode the payment scope." - case .paymentTriggerPresentationFailed: - return "Couldn't present the Apple Pay screen." - case .paymentCancelled: - return "Payment was cancelled by the user." - } - } -} diff --git a/src/ios/Extensions/PKContactField+Adapter.swift b/src/ios/Extensions/PKContactField+Adapter.swift deleted file mode 100644 index 6622e90..0000000 --- a/src/ios/Extensions/PKContactField+Adapter.swift +++ /dev/null @@ -1,21 +0,0 @@ -import PassKit - -extension PKContactField { - /// Allows the conversion of the contact text associated to Shipping and Billing Information into an object of `PKContactField` type. - /// - Parameter text: Contact field text to convert. - /// - Returns: The equivalent `PKContactField` object. - static func convert(from text: String) -> PKContactField? { - switch text.lowercased() { - case "email": - return .emailAddress - case "name": - return .name - case "phone": - return .phoneNumber - case "postal_address": - return .postalAddress - default: - return nil - } - } -} diff --git a/src/ios/Extensions/PKMerchantCapability+Adapter.swift b/src/ios/Extensions/PKMerchantCapability+Adapter.swift deleted file mode 100644 index bcf2153..0000000 --- a/src/ios/Extensions/PKMerchantCapability+Adapter.swift +++ /dev/null @@ -1,21 +0,0 @@ -import PassKit - -extension PKMerchantCapability { - /// Allows the conversion of the text associated to a Merchant Capability into an object of `PKMerchantCapability` type. - /// - Parameter text: Merchant capability text to convert. - /// - Returns: The equivalent `PKMerchantCapability` object. - static func convert(from text: String) -> PKMerchantCapability? { - switch text.lowercased() { - case "debit": - return .capabilityDebit - case "credit": - return .capabilityCredit - case "3ds": - return .capability3DS - case "emv": - return .capabilityEMV - default: - return nil - } - } -} diff --git a/src/ios/Extensions/PKPassLibrary+Adapter.swift b/src/ios/Extensions/PKPassLibrary+Adapter.swift deleted file mode 100644 index b11e296..0000000 --- a/src/ios/Extensions/PKPassLibrary+Adapter.swift +++ /dev/null @@ -1,9 +0,0 @@ -import PassKit - -extension PKPassLibrary: OSPMTWalletAvailabilityDelegate { - /// Verifies if the wallet is available for usage. - /// - Returns: A boolean indicating if the wallet is available. - static func isWalletAvailable() -> Bool { - Self.isPassLibraryAvailable() - } -} diff --git a/src/ios/Extensions/PKPayment+Adapter.swift b/src/ios/Extensions/PKPayment+Adapter.swift deleted file mode 100644 index 811e251..0000000 --- a/src/ios/Extensions/PKPayment+Adapter.swift +++ /dev/null @@ -1,93 +0,0 @@ -import PassKit - -extension PKPayment { - /// Converts a `PKPayment` object into a `OSPMTScopeModel` one. Returns `nil` if it can't. - /// - Returns: The corresponding `OSPMTScopeModel` object. Can also return `nil` if the conversion fails. - func createScopeModel() -> OSPMTScopeModel? { - var result: [String: Any] = [OSPMTScopeModel.CodingKeys.paymentData.rawValue: self.createTokenDataData()] - if let shippingContact = self.shippingContact { - result[OSPMTScopeModel.CodingKeys.shippingInfo.rawValue] = self.createContactInfoData(for: shippingContact) - } - - guard - let scopeData = try? JSONSerialization.data(withJSONObject: result), - let scopeModel = try? JSONDecoder().decode(OSPMTScopeModel.self, from: scopeData) - else { return nil } - return scopeModel - } - - /// Converts a `PKPayment` object into a dictionary that relates to an `OSPMTDataModel` object. - /// - Returns: The corresponding `OSPMTDataModel` dictionary object. - private func createTokenDataData() -> [String: Any] { - var result: [String: Any] = [ - OSPMTDataModel.CodingKeys.tokenData.rawValue: self.createTokenData(for: self.token.paymentData) - ] - if let billingContact = self.billingContact { - result[OSPMTDataModel.CodingKeys.billingInfo.rawValue] = self.createContactInfoData(for: billingContact) - } - if let paymentMethodName = self.token.paymentMethod.displayName { - let cardInfo = paymentMethodName.components(separatedBy: " ") - if let cardNetwork = cardInfo.first, let cardDetails = cardInfo.last { - result[OSPMTDataModel.CodingKeys.cardDetails.rawValue] = cardDetails - result[OSPMTDataModel.CodingKeys.cardNetwork.rawValue] = cardNetwork - } - } - - return result - } - - /// Takes the passed payment data object and converts it into a dictionary that relates to an `OSPMTTokenInfoModel` object. - /// - Parameter paymentData: `Data` type object that contains information related to a payment token. - /// - Returns: The corresponding `OSPMTTokenInfoModel` dictionary object. - private func createTokenData(for paymentData: Data) -> [String: String] { - // TODO: The type passed here will probably be changed into the Payment Service Provider's name when this is implemented. - var result = [OSPMTTokenInfoModel.CodingKeys.type.rawValue: "Apple Pay"] - - if let token = String(data: paymentData, encoding: .utf8) { - result[OSPMTTokenInfoModel.CodingKeys.token.rawValue] = token - } - - return result - } - - /// Takes the passed contact object and converts it into a dictionary that relates to an `OSPMTContactInfoModel` object. - /// - Parameter contact: `PKContact` type object that contains information related to the filled Billing or Shipping Information - /// - Returns: The corresponding `OSPMTContactInfoModel` dictionary object. - private func createContactInfoData(for contact: PKContact) -> [String: Any]? { - var result = [String: Any]() - if let address = contact.postalAddress { - result[OSPMTContactInfoModel.CodingKeys.address.rawValue] = self.createAddressData(for: address) - } - if let phoneNumber = contact.phoneNumber { - result[OSPMTContactInfoModel.CodingKeys.phoneNumber.rawValue] = phoneNumber.stringValue - } - if let name = contact.name, let givenName = name.givenName, let familyName = name.familyName, !givenName.isEmpty, !familyName.isEmpty { - result[OSPMTContactInfoModel.CodingKeys.name.rawValue] = "\(givenName) \(familyName)" - } - if let email = contact.emailAddress { - result[OSPMTContactInfoModel.CodingKeys.email.rawValue] = email - } - - return !result.isEmpty ? result : nil - } - - /// Takes the passed address object and converts it into a dictionary that relates to an `OSPMTAddressModel` object. - /// - Parameter postalAddress: `CNPostalAddress` type object that contains an address related to the filled Billing or Shipping Information. - /// - Returns: The corresponding `OSPMTAddressModel` dictionary object. - private func createAddressData(for postalAddress: CNPostalAddress) -> [String: String] { - var result = [ - OSPMTAddressModel.CodingKeys.postalCode.rawValue: postalAddress.postalCode, - OSPMTAddressModel.CodingKeys.fullAddress.rawValue: postalAddress.street, - OSPMTAddressModel.CodingKeys.countryCode.rawValue: postalAddress.isoCountryCode, - OSPMTAddressModel.CodingKeys.city.rawValue: postalAddress.city - ] - if !postalAddress.subAdministrativeArea.isEmpty { - result[OSPMTAddressModel.CodingKeys.administrativeArea.rawValue] = postalAddress.subAdministrativeArea - } - if !postalAddress.state.isEmpty { - result[OSPMTAddressModel.CodingKeys.state.rawValue] = postalAddress.state - } - - return result - } -} diff --git a/src/ios/Extensions/PKPaymentAuthorizationController+Adapter.swift b/src/ios/Extensions/PKPaymentAuthorizationController+Adapter.swift deleted file mode 100644 index a449e0c..0000000 --- a/src/ios/Extensions/PKPaymentAuthorizationController+Adapter.swift +++ /dev/null @@ -1,66 +0,0 @@ -import PassKit - -extension PKPaymentAuthorizationController: OSPMTApplePaySetupAvailabilityDelegate { - /// Verifies if a payment is available for usage. - /// - Returns: A boolean indicating if a payment is available. - static func isPaymentAvailable() -> Bool { - Self.canMakePayments() - } - - /// Verifies if a payment is available for usage, given the passed payment networks and marchant capabilities - /// - Parameters: - /// - networks: Array of payment networks available by a merchant - /// - merchantCapabilities: Bit set containing the payment capabilities available by a merchant. - /// - Returns: A boolean indicating if the payment is available. - static func isPaymentAvailable(using networks: [PKPaymentNetwork]?, and merchantCapabilities: PKMerchantCapability?) -> Bool { - guard let networks = networks, let merchantCapabilities = merchantCapabilities else { return false } - return Self.canMakePayments(usingNetworks: networks, capabilities: merchantCapabilities) - } -} - -extension PKPaymentAuthorizationController: OSPMTApplePayRequestTriggerDelegate { - /// Triggers a payment request. The result is processed asyncrhonously and returned by the `completion` parameters. - /// - Parameter completion: Block that returns the success of the payment request operation. - func triggerPayment(_ completion: @escaping OSPMTRequestTriggerCompletion) { - self.present(completion: completion) - } - - /// Creates an object responsible for dealing with the payment request process, delegating the details to the passed parameter. - /// - Parameters: - /// - detailsModel: Payment details. - /// - delegate: The object responsible for the request process' response. - /// - Returns: An instance of the object or an error, it the instatiation fails. - static func createRequestTriggerBehaviour(for detailsModel: OSPMTDetailsModel, andDelegate delegate: OSPMTApplePayRequestBehaviour?) -> Result { - guard - let delegate = delegate, - let merchantIdentifier = delegate.configuration.merchantID, - let countryCode = delegate.configuration.merchantCountryCode, - let merchantCapabilities = delegate.configuration.merchantCapabilities, - let paymentSummaryItems = delegate.getPaymentSummaryItems(for: detailsModel), - let supportedNetworks = delegate.configuration.supportedNetworks - else { return .failure(.invalidConfiguration) } - - let paymentRequest = PKPaymentRequest() - paymentRequest.merchantIdentifier = merchantIdentifier - paymentRequest.countryCode = countryCode - paymentRequest.currencyCode = detailsModel.currency - paymentRequest.merchantCapabilities = merchantCapabilities - paymentRequest.paymentSummaryItems = paymentSummaryItems - paymentRequest.requiredBillingContactFields = delegate.getContactFields( - for: detailsModel.billingContact.isCustom - ? detailsModel.billingContact.contactArray - : delegate.configuration.billingSupportedContacts - ) - paymentRequest.requiredShippingContactFields = delegate.getContactFields( - for: detailsModel.shippingContact.isCustom - ? detailsModel.shippingContact.contactArray - : delegate.configuration.shippingSupportedContacts - ) - paymentRequest.supportedCountries = delegate.configuration.supportedCountries - paymentRequest.supportedNetworks = supportedNetworks - - let paymentAuthorizationController = PKPaymentAuthorizationController(paymentRequest: paymentRequest) - paymentAuthorizationController.delegate = delegate - return .success(paymentAuthorizationController) - } -} diff --git a/src/ios/Extensions/PKPaymentNetwork+Adapter.swift b/src/ios/Extensions/PKPaymentNetwork+Adapter.swift deleted file mode 100644 index 1dacb17..0000000 --- a/src/ios/Extensions/PKPaymentNetwork+Adapter.swift +++ /dev/null @@ -1,21 +0,0 @@ -import PassKit - -extension PKPaymentNetwork { - /// Allows the conversion of the text associated to a Payment Network into an object of `PKPaymentNetwork` type. - /// - Parameter text: Payment network text to convert. - /// - Returns: The equivalent `PKPaymentNetwork` object. - static func convert(from text: String) -> PKPaymentNetwork? { - switch text.lowercased() { - case "amex": - return .amex - case "discover": - return .discover - case "visa": - return .visa - case "mastercard": - return .masterCard - default: - return nil - } - } -} diff --git a/src/ios/Models/OSPMTAddressModel.swift b/src/ios/Models/OSPMTAddressModel.swift deleted file mode 100644 index 336c4f5..0000000 --- a/src/ios/Models/OSPMTAddressModel.swift +++ /dev/null @@ -1,74 +0,0 @@ -/// Address Information related to a Billing or Shipping Information -struct OSPMTAddressModel: Codable, Equatable { - let postalCode: String - let fullAddress: String - let countryCode: String - let city: String - let administrativeArea: String? - let state: String? - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case postalCode, fullAddress, countryCode, city, administrativeArea, state - } - - /// Constructor method - /// - Parameters: - /// - postalCode: Zip code. - /// - fullAddress: Text containing full address (e.g. street, door number, floor, ...) - /// - countryCode: ISO 3166-1 country code representation of the country. - /// - city: City. - /// - administrativeArea: Administrative Area, if existing. - /// - state: State, if existing. - init(postalCode: String, fullAddress: String, countryCode: String, city: String, administrativeArea: String? = nil, state: String? = nil) { - self.postalCode = postalCode - self.fullAddress = fullAddress - self.countryCode = countryCode - self.city = city - self.administrativeArea = administrativeArea - self.state = state - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let postalCode = try container.decode(String.self, forKey: .postalCode) - let fullAddress = try container.decode(String.self, forKey: .fullAddress) - let countryCode = try container.decode(String.self, forKey: .countryCode) - let city = try container.decode(String.self, forKey: .city) - let administrativeArea = try container.decodeIfPresent(String.self, forKey: .administrativeArea) - let state = try container.decodeIfPresent(String.self, forKey: .state) - self.init( - postalCode: postalCode, - fullAddress: fullAddress, - countryCode: countryCode, - city: city, - administrativeArea: administrativeArea, - state: state - ) - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(postalCode, forKey: .postalCode) - try container.encode(fullAddress, forKey: .fullAddress) - try container.encode(countryCode, forKey: .countryCode) - try container.encode(city, forKey: .city) - try container.encodeIfPresent(administrativeArea, forKey: .administrativeArea) - try container.encodeIfPresent(state, forKey: .state) - } -} diff --git a/src/ios/Models/OSPMTConfigurationModel.swift b/src/ios/Models/OSPMTConfigurationModel.swift deleted file mode 100644 index 565b10e..0000000 --- a/src/ios/Models/OSPMTConfigurationModel.swift +++ /dev/null @@ -1,198 +0,0 @@ -import PassKit - -/// Protocol that contains all properties needed to configure a payment service. -class OSPMTConfigurationModel: Encodable { - // MARK: Merchant Information - var merchantID: String? - var merchantName: String? - var merchantCountryCode: String? - - // MARK: Payment Information - var paymentAllowedNetworks: [String]? - var paymentSupportedCapabilities: [String]? - var paymentSupportedCardCountries: [String]? - - // MARK: Shipping Information - var shippingSupportedContacts: [String]? - - // MARK: Billing Information - var billingSupportedContacts: [String]? - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case merchantID - case merchantName - case merchantCountryCode - case paymentAllowedNetworks - case paymentSupportedCapabilities - case paymentSupportedCardCountries - case shippingSupportedContacts - case billingSupportedContacts - } - - /// Constructor method. - /// - Parameters: - /// - merchantID: Merchant ID configured - /// - merchantName: Merchant Name configured - /// - merchantCountryCode: Merchant Country Code configured - /// - paymentAllowedNetworks: Payment Allowed Networks configured - /// - paymentSupportedCapabilities: Payment Supported Capabilities configured - /// - paymentSupportedCardCountries: Payment Support Card Countries configured - /// - shippingSupportedContacts: Shipping Supported Contacts configured - /// - billingSupportedContacts: Billing Supported Contacts configured - init(merchantID: String?, merchantName: String?, merchantCountryCode: String?, paymentAllowedNetworks: [String]?, paymentSupportedCapabilities: [String]?, paymentSupportedCardCountries: [String]?, shippingSupportedContacts: [String]?, billingSupportedContacts: [String]?) { - self.merchantID = merchantID - self.merchantName = merchantName - self.merchantCountryCode = merchantCountryCode - self.paymentAllowedNetworks = paymentAllowedNetworks - self.paymentSupportedCapabilities = paymentSupportedCapabilities - self.paymentSupportedCardCountries = paymentSupportedCardCountries - self.shippingSupportedContacts = shippingSupportedContacts - self.billingSupportedContacts = billingSupportedContacts - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - - // MARK: Merchant Information - try container.encodeIfPresent(merchantID, forKey: .merchantID) - try container.encodeIfPresent(merchantName, forKey: .merchantName) - try container.encodeIfPresent(merchantCountryCode, forKey: .merchantCountryCode) - - // MARK: Payment Information - try container.encodeIfPresent(paymentAllowedNetworks, forKey: .paymentAllowedNetworks) - try container.encodeIfPresent(paymentSupportedCapabilities, forKey: .paymentSupportedCapabilities) - try container.encodeIfPresent(paymentSupportedCardCountries, forKey: .paymentSupportedCardCountries) - - // MARK: Shipping Information - try container.encodeIfPresent(shippingSupportedContacts, forKey: .shippingSupportedContacts) - - // MARK: Billing Information - try container.encodeIfPresent(billingSupportedContacts, forKey: .billingSupportedContacts) - } -} - -typealias OSPMTConfiguration = [String: Any] - -/// Manages all configuration properties required to enable Apple Pay in the plugin. -class OSPMTApplePayConfiguration: OSPMTConfigurationModel { - struct ConfigurationKeys { - static let merchantID = "ApplePayMerchantID" - static let merchantName = "ApplePayMerchantName" - static let merchantCountryCode = "ApplePayMerchantCountryCode" - - static let paymentAllowedNetworks = "ApplePayPaymentAllowedNetworks" - static let paymentSupportedCapabilities = "ApplePayPaymentSupportedCapabilities" - static let paymentSupportedCardCountries = "ApplePayPaymentSupportedCardCountries" - - static let shippingSupportedContacts = "ApplePayShippingSupportedContacts" - - static let billingSupportedContacts = "ApplePayBillingSupportedContacts" - } - - /// Constructor method. - /// - Parameter source: Source class contaning the configuration. - convenience init(source: OSPMTConfiguration) { - // MARK: Merchant Information - let merchantID = Self.getRequiredProperty( - ofType: String.self, forSource: source, andKey: ConfigurationKeys.merchantID - ) - let merchantName = Self.getRequiredProperty( - ofType: String.self, forSource: source, andKey: ConfigurationKeys.merchantName - ) - let merchantCountryCode = Self.getRequiredProperty( - ofType: String.self, forSource: source, andKey: ConfigurationKeys.merchantCountryCode - ) - - // MARK: Payment Information - let paymentAllowedNetworks = Self.getRequiredProperty( - ofType: [String].self, forSource: source, andKey: ConfigurationKeys.paymentAllowedNetworks - ) - let paymentSupportedCapabilities = Self.getRequiredProperty( - ofType: [String].self, forSource: source, andKey: ConfigurationKeys.paymentSupportedCapabilities - ) - let paymentSupportedCardCountries = Self.getProperty( - ofType: [String].self, forSource: source, andKey: ConfigurationKeys.paymentSupportedCardCountries - ) - - // MARK: Shipping Information - let shippingSupportedContacts = Self.getProperty( - ofType: [String].self, forSource: source, andKey: ConfigurationKeys.shippingSupportedContacts - ) - - // MARK: Billing Information - let billingSupportedContacts = Self.getProperty( - ofType: [String].self, forSource: source, andKey: ConfigurationKeys.billingSupportedContacts - ) - - self.init( - merchantID: merchantID, - merchantName: merchantName, - merchantCountryCode: merchantCountryCode, - paymentAllowedNetworks: paymentAllowedNetworks, - paymentSupportedCapabilities: paymentSupportedCapabilities, - paymentSupportedCardCountries: paymentSupportedCardCountries, - shippingSupportedContacts: shippingSupportedContacts, - billingSupportedContacts: billingSupportedContacts - ) - } -} - -private extension OSPMTApplePayConfiguration { - /// Fetches the parameter property, if it exists. - /// - Parameters: - /// - type: Type of variable to return. - /// - key: Property key to search from. - /// - isRequired: Indicates if the property is mandatory or not. - /// - Returns: The configuration property, if it exists. - static func getProperty(ofType type: T.Type, forSource source: OSPMTConfiguration, andKey key: String, isRequired: Bool = false) -> T? { - let result = source[key] as? T - return !isRequired || result?.isEmpty == false ? result : nil - } - - /// An acelerator for `getProperty(ofType:forKey:isRequired:)`, that should be used for mandatory properties. - /// - Parameters: - /// - type: Type of variable to return. - /// - key: Property key to search from. - /// - Returns: The configuration property, if it exists. - static func getRequiredProperty(ofType type: T.Type, forSource source: OSPMTConfiguration, andKey key: String) -> T? { - self.getProperty(ofType: type, forSource: source, andKey: key, isRequired: true) - } -} - -extension OSPMTApplePayConfiguration { - var supportedNetworks: [PKPaymentNetwork]? { - guard let paymentAllowedNetworks = self.paymentAllowedNetworks else { return nil } - let result = paymentAllowedNetworks.compactMap(PKPaymentNetwork.convert(from:)) - - return !result.isEmpty ? result : nil - } - - var merchantCapabilities: PKMerchantCapability? { - guard let paymentSupportedCapabilities = self.paymentSupportedCapabilities else { return nil } - - var result: PKMerchantCapability = [] - result = paymentSupportedCapabilities.reduce(into: result) { partialResult, capability in - let merchantCapability = PKMerchantCapability.convert(from: capability) - if let merchantCapability = merchantCapability { - partialResult.insert(merchantCapability) - } - } - - return !result.isEmpty ? result : nil - } - - var supportedCountries: Set? { - guard let paymentSupportedCardCountries = self.paymentSupportedCardCountries, !paymentSupportedCardCountries.isEmpty else { return nil } - return Set(paymentSupportedCardCountries) - } -} diff --git a/src/ios/Models/OSPMTContactInfoModel.swift b/src/ios/Models/OSPMTContactInfoModel.swift deleted file mode 100644 index d75fe48..0000000 --- a/src/ios/Models/OSPMTContactInfoModel.swift +++ /dev/null @@ -1,72 +0,0 @@ -/// Information related to Billing or Shipping -struct OSPMTContactInfoModel: Codable { - let address: OSPMTAddressModel? - let phoneNumber: String? - let name: String? - let email: String? - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case address, phoneNumber, name, email - } - - /// Constructor method. - /// - Parameters: - /// - address: Address information, if existing. - /// - phoneNumber: Phone number information, if existing. - /// - name: Given and family name, if existing. - /// - email: Email address, if existing. - init(address: OSPMTAddressModel? = nil, phoneNumber: String? = nil, name: String? = nil, email: String? = nil) { - self.address = address - self.phoneNumber = phoneNumber - self.name = name - self.email = email - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let address = try container.decodeIfPresent(OSPMTAddressModel.self, forKey: .address) - let phoneNumber = try container.decodeIfPresent(String.self, forKey: .phoneNumber) - let name = try container.decodeIfPresent(String.self, forKey: .name) - let email = try container.decodeIfPresent(String.self, forKey: .email) - self.init(address: address, phoneNumber: phoneNumber, name: name, email: email) - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(address, forKey: .address) - try container.encodeIfPresent(phoneNumber, forKey: .phoneNumber) - try container.encodeIfPresent(name, forKey: .name) - try container.encodeIfPresent(email, forKey: .email) - } -} - -extension OSPMTContactInfoModel: Equatable { - /// Returns a Boolean value indicating whether two values are equal. - /// - /// Equality is the inverse of inequality. For any values `a` and `b`, - /// `a == b` implies that `a != b` is `false`. - /// - /// - Parameters: - /// - lhs: A value to compare. - /// - rhs: Another value to compare. - /// - Returns: The comparison result. - static func == (lhs: OSPMTContactInfoModel, rhs: OSPMTContactInfoModel) -> Bool { - lhs.address == rhs.address && lhs.phoneNumber == rhs.phoneNumber && lhs.name == rhs.name && lhs.email == rhs.email - } -} diff --git a/src/ios/Models/OSPMTDataModel.swift b/src/ios/Models/OSPMTDataModel.swift deleted file mode 100644 index a427af8..0000000 --- a/src/ios/Models/OSPMTDataModel.swift +++ /dev/null @@ -1,75 +0,0 @@ -/// Payment Data Information -struct OSPMTDataModel: Codable { - let billingInfo: OSPMTContactInfoModel? - let cardDetails: String - let cardNetwork: String - let tokenData: OSPMTTokenInfoModel - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case billingInfo, cardDetails, cardNetwork, tokenData - } - - /// Constructor method. - /// - Parameters: - /// - billingInfo: Billing Information. - /// - cardDetails: The last four digits of the card used for payment. - /// - cardNetwork: The network of the card used for payment. - /// - tokenData: The data of the token used for payment. - init(billingInfo: OSPMTContactInfoModel? = nil, cardDetails: String, cardNetwork: String, tokenData: OSPMTTokenInfoModel) { - self.billingInfo = billingInfo - self.cardDetails = cardDetails - self.cardNetwork = cardNetwork - self.tokenData = tokenData - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let billingInfo = try container.decodeIfPresent(OSPMTContactInfoModel.self, forKey: .billingInfo) - let cardDetails = try container.decode(String.self, forKey: .cardDetails) - let cardNetwork = try container.decode(String.self, forKey: .cardNetwork) - let tokenData = try container.decode(OSPMTTokenInfoModel.self, forKey: .tokenData) - self.init(billingInfo: billingInfo, cardDetails: cardDetails, cardNetwork: cardNetwork, tokenData: tokenData) - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(billingInfo, forKey: .billingInfo) - try container.encode(cardDetails, forKey: .cardDetails) - try container.encode(cardNetwork, forKey: .cardNetwork) - try container.encode(tokenData, forKey: .tokenData) - } -} - -extension OSPMTDataModel: Equatable { - /// Returns a Boolean value indicating whether two values are equal. - /// - /// Equality is the inverse of inequality. For any values `a` and `b`, - /// `a == b` implies that `a != b` is `false`. - /// - /// - Parameters: - /// - lhs: A value to compare. - /// - rhs: Another value to compare. - /// - Returns: The comparison result. - static func == (lhs: OSPMTDataModel, rhs: OSPMTDataModel) -> Bool { - lhs.billingInfo == rhs.billingInfo - && lhs.cardDetails == rhs.cardDetails - && lhs.cardNetwork == rhs.cardNetwork - && lhs.tokenData == rhs.tokenData - } -} diff --git a/src/ios/Models/OSPMTDetailsModel.swift b/src/ios/Models/OSPMTDetailsModel.swift deleted file mode 100644 index a991c3b..0000000 --- a/src/ios/Models/OSPMTDetailsModel.swift +++ /dev/null @@ -1,103 +0,0 @@ -import PassKit - -/// Status of the final value to be charged. -enum OSPMTStatus: String, Codable { - case final - case pending -} - -/// Structure of the shipping/billing information -struct OSPMTContact: Decodable { - let isCustom: Bool - let contactArray: [String]? - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case isCustom - case contactArray = "contactInfo" - } - - /// Constructor method - /// - Parameters: - /// - isCustom: Indicates if the custom contact information should be used when trigger a payment request. - /// - contactArray: Shipping/Billing properties required for filling. - init(isCustom: Bool, contactArray: [String]?) { - self.isCustom = isCustom - self.contactArray = contactArray - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let isCustom = try container.decode(Bool.self, forKey: .isCustom) - let contactArray = isCustom ? try container.decodeIfPresent([String].self, forKey: .contactArray) : nil - self.init(isCustom: isCustom, contactArray: contactArray) - } -} - -/// Payment Details to be processed. -struct OSPMTDetailsModel: Decodable { - let amount: Decimal - let currency: String - let status: OSPMTStatus - let shippingContact: OSPMTContact - let billingContact: OSPMTContact - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case amount - case currency - case status - case shippingContact = "shippingContacts" - case billingContact = "billingContacts" - } - - /// Constructor method. - /// - Parameters: - /// - amount: Amount to be charged. - /// - currency: The three-letter ISO 4217 currency code. - /// - 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) { - self.amount = amount - self.currency = currency - self.status = status - self.shippingContact = shippingContact - self.billingContact = billingContact - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let amount = try container.decode(Decimal.self, forKey: .amount) - let currency = try container.decode(String.self, forKey: .currency) - 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) - self.init( - amount: amount, currency: currency, status: status, shippingContact: shippingContact, billingContact: billingContact - ) - } -} - -// MARK: Apple Pay extension -extension OSPMTDetailsModel { - var paymentAmount: NSDecimalNumber { - NSDecimalNumber(decimal: self.amount) - } - - var paymentSummaryItemType: PKPaymentSummaryItemType { - self.status == .pending ? .pending : .final - } -} diff --git a/src/ios/Models/OSPMTScopeModel.swift b/src/ios/Models/OSPMTScopeModel.swift deleted file mode 100644 index b20a855..0000000 --- a/src/ios/Models/OSPMTScopeModel.swift +++ /dev/null @@ -1,62 +0,0 @@ -/// Payment Scope Information -struct OSPMTScopeModel: Codable { - let paymentData: OSPMTDataModel - let shippingInfo: OSPMTContactInfoModel? - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case paymentData, shippingInfo - } - - /// Construct method. - /// - Parameters: - /// - paymentData: Payment Data Information. - /// - shippingInfo: Shipping Information Filled. - init(paymentData: OSPMTDataModel, shippingInfo: OSPMTContactInfoModel? = nil) { - self.paymentData = paymentData - self.shippingInfo = shippingInfo - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let paymentData = try container.decode(OSPMTDataModel.self, forKey: .paymentData) - let shippingInfo = try container.decodeIfPresent(OSPMTContactInfoModel.self, forKey: .shippingInfo) - self.init(paymentData: paymentData, shippingInfo: shippingInfo) - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(paymentData, forKey: .paymentData) - try container.encodeIfPresent(shippingInfo, forKey: .shippingInfo) - } -} - -extension OSPMTScopeModel: Equatable { - /// Returns a Boolean value indicating whether two values are equal. - /// - /// Equality is the inverse of inequality. For any values `a` and `b`, - /// `a == b` implies that `a != b` is `false`. - /// - /// - Parameters: - /// - lhs: A value to compare. - /// - rhs: Another value to compare. - /// - Returns: The comparison result. - static func == (lhs: OSPMTScopeModel, rhs: OSPMTScopeModel) -> Bool { - lhs.paymentData == rhs.paymentData && lhs.shippingInfo == rhs.shippingInfo - } -} diff --git a/src/ios/Models/OSPMTTokenInfoModel.swift b/src/ios/Models/OSPMTTokenInfoModel.swift deleted file mode 100644 index b3167e7..0000000 --- a/src/ios/Models/OSPMTTokenInfoModel.swift +++ /dev/null @@ -1,47 +0,0 @@ -/// Token Information Model -struct OSPMTTokenInfoModel: Codable, Equatable { - let token: String - let type: String - - /// Keys used to encode and decode the model. - enum CodingKeys: String, CodingKey { - case token, type - } - - /// Constructor method. - /// - Parameters: - /// - token: Token data text. - /// - type: Payment gateway (e.g. Payment Service Provider name). - init(token: String, type: String) { - self.token = token - self.type = type - } - - /// Creates a new instance by decoding from the given decoder. - /// - /// This initializer throws an error if reading from the decoder fails, or - /// if the data read is corrupted or otherwise invalid. - /// - /// - Parameter decoder: The decoder to read data from. - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let token = try container.decode(String.self, forKey: .token) - let type = try container.decode(String.self, forKey: .type) - self.init(token: token, type: type) - } - - /// Encodes this value into the given encoder. - /// - /// If the value fails to encode anything, `encoder` will encode an empty - /// keyed container in its place. - /// - /// This function throws an error if any values are invalid for the given - /// encoder's format. - /// - /// - Parameter encoder: The encoder to write data to. - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(token, forKey: .token) - try container.encode(type, forKey: .type) - } -} diff --git a/src/ios/OSPMTApplePayHandler.swift b/src/ios/OSPMTApplePayHandler.swift deleted file mode 100644 index b60ae67..0000000 --- a/src/ios/OSPMTApplePayHandler.swift +++ /dev/null @@ -1,58 +0,0 @@ -/// Class resopnsible to manage the Apple Pay payment service requests. It delegates every operation type to its manager. -class OSPMTApplePayHandler: NSObject { - let configuration: OSPMTConfigurationModel - let availabilityBehaviour: OSPMTAvailabilityDelegate - let requestBehaviour: OSPMTRequestDelegate - - /// Constructor .method. - /// - Parameters: - /// - configuration: Configuration manager. - /// - availabilityBehaviour: Availability manager. - /// - requestBehaviour: Request trigger manager. - init(configuration: OSPMTConfigurationModel, availabilityBehaviour: OSPMTAvailabilityDelegate, requestBehaviour: OSPMTRequestDelegate) { - self.configuration = configuration - self.availabilityBehaviour = availabilityBehaviour - self.requestBehaviour = requestBehaviour - super.init() - } - - /// Constructor method. - /// - Parameter configurationSource: Configuration source, containing all values needed to configure. - convenience init(configurationSource: OSPMTConfiguration) { - let applePayConfiguration = OSPMTApplePayConfiguration(source: configurationSource) - let applePayAvailabilityBehaviour = OSPMTApplePayAvailabilityBehaviour(configuration: applePayConfiguration) - let applePayRequestBehaviour = OSPMTApplePayRequestBehaviour(configuration: applePayConfiguration) - self.init( - configuration: applePayConfiguration, availabilityBehaviour: applePayAvailabilityBehaviour, requestBehaviour: applePayRequestBehaviour - ) - } -} - -// MARK: - OSPMTHandlerProtocol Methods -extension OSPMTApplePayHandler: OSPMTHandlerDelegate { - /// Allows the configuration of the payment service. - /// - Returns: Returns a JSON mapping if successful or an error if anything failed. - func setupConfiguration() -> Result { - guard - let configurationData = try? JSONEncoder().encode(self.configuration), - let configurationText = String(data: configurationData, encoding: .utf8) - else { return .failure(.invalidConfiguration) } - return .success(configurationText) - } - - /// Checks for the Wallet and Payment availability. - /// - Returns: Returns `nil` if successful or an error otherwise. - func checkWalletAvailability() -> OSPMTError? { - self.availabilityBehaviour.checkWallet() - ?? self.availabilityBehaviour.checkPaymentAvailability() - ?? self.availabilityBehaviour.checkPaymentAvailabilityWithSetup() - } - - /// Sets Payment details and triggers its processing. - /// - Parameters: - /// - detailsModel: payment details information. - /// - completion: an async closure that can return a successful Payment Scope Model or an error otherwise. - func set(_ detailsModel: OSPMTDetailsModel, completion: @escaping OSPMTCompletionHandler) { - self.requestBehaviour.trigger(with: detailsModel, completion) - } -} diff --git a/src/ios/OSPMTPayments.swift b/src/ios/OSPMTPayments.swift deleted file mode 100644 index 9a429c1..0000000 --- a/src/ios/OSPMTPayments.swift +++ /dev/null @@ -1,95 +0,0 @@ -/// Class that provides the bridge between the library and 3rd party consumers. -class OSPMTPayments: NSObject { - private weak var delegate: OSPMTCallbackDelegate? - private let handler: OSPMTHandlerDelegate - - /// Constructor method. - /// - Parameters: - /// - delegate: Handles the asynchronous return calls. - /// - handler: Payment service handler. - init(delegate: OSPMTCallbackDelegate, handler: OSPMTHandlerDelegate) { - self.delegate = delegate - self.handler = handler - } - - /// Convenience method for Apple Pay. - /// - Parameters: - /// - delegate: Handles the asynchronous return calls. - /// - configurationSource: Configuration source, containing all values needed to configure. - convenience init(applePayWithDelegate delegate: OSPMTCallbackDelegate, andConfiguration configurationSource: OSPMTConfiguration = Bundle.main.infoDictionary!) { - let applePayHandler = OSPMTApplePayHandler(configurationSource: configurationSource) - self.init(delegate: delegate, handler: applePayHandler) - } -} - -// MARK: - Action Methods to be called by Bridge -extension OSPMTPayments: OSPMTActionDelegate { - /// Sets up the payment configuration. - func setupConfiguration() { - let result = self.handler.setupConfiguration() - - switch result { - case .success(let message): - self.delegate?.callback(result: message) - case .failure(let error): - self.delegate?.callback(error: error) - } - } - - /// Verifies the device is ready to process a payment, considering the configuration provided before. - func checkWalletSetup() { - if let error = self.handler.checkWalletAvailability() { - self.delegate?.callback(error: error) - } else { - self.delegate?.callbackSuccess() - } - } - - /// Sets payment details and triggers the request proccess. - /// - Parameter details: Payment details model serialized into a text field. - func set(_ details: String) { - let detailsResult = self.decode(details) - switch detailsResult { - case .success(let detailsModel): - self.handler.set(detailsModel) { [weak self] result in - guard let self = self else { return } - switch result { - case .success(let scopeModel): - let scopeResult = self.encode(scopeModel) - switch scopeResult { - case .success(let scopeText): - self.delegate?.callback(result: scopeText) - case .failure(let error): - self.delegate?.callback(error: error) - } - case .failure(let error): - self.delegate?.callback(error: error) - } - } - case .failure(let error): - self.delegate?.callback(error: error) - } - } -} - -extension OSPMTPayments { - /// Decodes the payment details information text into an `OSPMTDetailsModel` instance. If not successful, returns an error - /// - Parameter detailsText: Payment details information text. - /// - Returns: The resulting `OSPMTDetailsModel` or error. - func decode(_ detailsText: String) -> Result { - guard - let detailsData = detailsText.data(using: .utf8), - let detailsModel = try? JSONDecoder().decode(OSPMTDetailsModel.self, from: detailsData) - else { return .failure(.invalidDecodeDetails) } - return .success(detailsModel) - } - - /// Encondes the payment scope information model into text. If not successful, returns an error. - /// - Parameter scopeModel: Payment scope information model. - /// - Returns: The resulting text or error. - func encode(_ scopeModel: OSPMTScopeModel) -> Result { - guard let scopeData = try? JSONEncoder().encode(scopeModel), let scopeText = String(data: scopeData, encoding: .utf8) - else { return .failure(.invalidEncodeScope) } - return .success(scopeText) - } -} diff --git a/src/ios/OSPayments.swift b/src/ios/OSPayments.swift index bbd0f1c..8506de2 100644 --- a/src/ios/OSPayments.swift +++ b/src/ios/OSPayments.swift @@ -1,8 +1,9 @@ import OSCommonPluginLib +import OSPaymentsPluginLib @objc(OSPayments) class OSPayments: CDVPlugin { - var plugin: OSPMTPayments? + var plugin: OSPMTActionDelegate? var callbackId: String = "" override func pluginInitialize() { diff --git a/src/ios/Protocols/OSPMTActionDelegate.swift b/src/ios/Protocols/OSPMTActionDelegate.swift deleted file mode 100644 index a990bcd..0000000 --- a/src/ios/Protocols/OSPMTActionDelegate.swift +++ /dev/null @@ -1,12 +0,0 @@ -/// Protocol that provides the server actions the plugin provides. -protocol OSPMTActionDelegate: AnyObject { - /// Sets up the payment configuration. - func setupConfiguration() - - /// Verifies the device is ready to process a payment, considering the configuration provided before. - func checkWalletSetup() - - /// Sets payment details and triggers the request proccess. - /// - Parameter details: Payment details model serialized into a text field. - func set(_ details: String) -} diff --git a/src/ios/Protocols/OSPMTAvailabilityDelegate.swift b/src/ios/Protocols/OSPMTAvailabilityDelegate.swift deleted file mode 100644 index e7ddf13..0000000 --- a/src/ios/Protocols/OSPMTAvailabilityDelegate.swift +++ /dev/null @@ -1,98 +0,0 @@ -import PassKit - -// MARK: - OSPMTWalletAvailabilityDelegate Protocol Methods -/// Protocol that is responsible to check if a Wallet is available to be used by the plugin. -protocol OSPMTWalletAvailabilityDelegate: AnyObject { - /// Verifies if the wallet is available for usage. - /// - Returns: A boolean indicating if the wallet is available. - static func isWalletAvailable() -> Bool -} - -// MARK: - OSPMTSetupAvailabilityDelegate Protocol and Related Methods -/// Protocol that is responsible to check if a Payment is available to be used by the plugin. -protocol OSPMTSetupAvailabilityDelegate: AnyObject { - /// Verifies if a payment is available for usage. - /// - Returns: A boolean indicating if a payment is available. - static func isPaymentAvailable() -> Bool -} - -/// Protocol that enhances the validation done by `OSPMTSetupAvailabilityDelegate` protocol and verifies Apple Pay availability. -protocol OSPMTApplePaySetupAvailabilityDelegate: OSPMTSetupAvailabilityDelegate { - /// Verifies if a payment is available for usage, given the passed payment networks and marchant capabilities - /// - Parameters: - /// - networks: Array of payment networks available by a merchant - /// - merchantCapabilities: Bit set containing the payment capabilities available by a merchant. - /// - Returns: A boolean indicating if the payment is available. - static func isPaymentAvailable(using networks: [PKPaymentNetwork]?, and merchantCapabilities: PKMerchantCapability?) -> Bool -} - -// MARK: - OSPMTAvailabilityDelegate Protocol Methods -/// Protocol that is responsible to verify if wallet and payment are ready to trigger a payment process. -protocol OSPMTAvailabilityDelegate: AnyObject { - /// Verifies if the wallet is ready to be used. - /// - Returns: A boolean indicating if it's ready or not. - func checkWallet() -> OSPMTError? - - /// Verifies if a payment request can be triggered. - /// - Parameter shouldVerifySetup: Indicates whether the plugin should also check its configuration properties. - /// - Returns: A boolean indicating if it's ready or not - func checkPayment(shouldVerifySetup: Bool) -> OSPMTError? -} - -extension OSPMTAvailabilityDelegate { - /// Verifies if a payment request can be triggered. It's the same as calling `checkPayment(shouldVerifySetup:)` with a `false` parameter. - /// - Returns: A boolean indicating if it's ready or not. - func checkPaymentAvailability() -> OSPMTError? { - self.checkPayment(shouldVerifySetup: false) - } - - /// Verifies if a payment request can be triggere, regarding its configuration properties. It's the same as calling `checkPayment(shouldVerifySetup:)` with a `true` parameter. - /// - Returns: A boolean indicating if it's ready or not. - func checkPaymentAvailabilityWithSetup() -> OSPMTError? { - self.checkPayment(shouldVerifySetup: true) - } -} - -// MARK: - OSPMTApplePayAvailabilityBehaviour Implementation Methods -/// Class responsible for verifying if Apple Wallet and Apple Pay are available and ready to be used. Apple Pay is also check against it's payment network and merchant capabilities. -class OSPMTApplePayAvailabilityBehaviour: OSPMTAvailabilityDelegate { - let configuration: OSPMTApplePayConfiguration - let walletAvailableBehaviour: OSPMTWalletAvailabilityDelegate.Type - let setupAvailableBehaviour: OSPMTApplePaySetupAvailabilityDelegate.Type - - /// Constructor method. - /// - Parameters: - /// - configuration: Apple Pay Configuration. - /// - walletAvailableBehaviour: Implementation of the protocol that verifies Apple Wallet availability. - /// - setupAvailableBehaviour: Implementation of the protocol that verifies Apple Pay payment availability. - init(configuration: OSPMTApplePayConfiguration, walletAvailableBehaviour: OSPMTWalletAvailabilityDelegate.Type = PKPassLibrary.self, setupAvailableBehaviour: OSPMTApplePaySetupAvailabilityDelegate.Type = PKPaymentAuthorizationController.self) { - self.configuration = configuration - self.walletAvailableBehaviour = walletAvailableBehaviour - self.setupAvailableBehaviour = setupAvailableBehaviour - } - - /// Verifies if the wallet is ready to be used. - /// - Returns: A boolean indicating if it's ready or not. - func checkWallet() -> OSPMTError? { - return !self.walletAvailableBehaviour.isWalletAvailable() ? .walletNotAvailable : nil - } - - /// Verifies if a payment request can be triggered. - /// - Parameter shouldVerifySetup: Indicates whether the plugin should also check its configuration properties. - /// - Returns: A boolean indicating if it's ready or not - func checkPayment(shouldVerifySetup: Bool) -> OSPMTError? { - var error: OSPMTError? - - if shouldVerifySetup { - if !self.setupAvailableBehaviour.isPaymentAvailable( - using: self.configuration.supportedNetworks, and: self.configuration.merchantCapabilities - ) { - error = .setupPaymentNotAvailable - } - } else if !self.setupAvailableBehaviour.isPaymentAvailable() { - error = .paymentNotAvailable - } - - return error - } -} diff --git a/src/ios/Protocols/OSPMTCallbackDelegate.swift b/src/ios/Protocols/OSPMTCallbackDelegate.swift deleted file mode 100644 index 3f72095..0000000 --- a/src/ios/Protocols/OSPMTCallbackDelegate.swift +++ /dev/null @@ -1,24 +0,0 @@ -/// Delegate for the callback return calls for the plugin -protocol OSPMTCallbackDelegate: AnyObject { - func callback(result: String?, error: OSPMTError?) -} - -// MARK: OSPMTCallbackProtocol Default Implementation -extension OSPMTCallbackDelegate { - /// Triggers the callback when there's an error - /// - Parameter error: Error to be thrown - func callback(error: OSPMTError) { - self.callback(result: nil, error: error) - } - - /// Triggers the callback when there's a success text - /// - Parameter result: Text to be returned - func callback(result: String) { - self.callback(result: result, error: nil) - } - - /// Triggers the callback when there's a success without text - func callbackSuccess() { - self.callback(result: "") - } -} diff --git a/src/ios/Protocols/OSPMTHandlerDelegate.swift b/src/ios/Protocols/OSPMTHandlerDelegate.swift deleted file mode 100644 index 06a759b..0000000 --- a/src/ios/Protocols/OSPMTHandlerDelegate.swift +++ /dev/null @@ -1,18 +0,0 @@ -typealias OSPMTCompletionHandler = (Result) -> Void - -/// Protocol that provides all methods a Payment Service handler should implement. -protocol OSPMTHandlerDelegate: AnyObject { - /// Allows the configuration of the payment service. - /// - Returns: Returns a JSON mapping if successful or an error if anything failed. - func setupConfiguration() -> Result - - /// Checks for the Wallet and Payment availability. - /// - Returns: Returns `nil` if successful or an error otherwise. - func checkWalletAvailability() -> OSPMTError? - - /// Sets Payment details and triggers its processing. - /// - Parameters: - /// - detailsModel: payment details information. - /// - completion: an async closure that can return a successful Payment Scope Model or an error otherwise. - func set(_ detailsModel: OSPMTDetailsModel, completion: @escaping OSPMTCompletionHandler) -} diff --git a/src/ios/Protocols/OSPMTRequestDelegate.swift b/src/ios/Protocols/OSPMTRequestDelegate.swift deleted file mode 100644 index 2a5e2c3..0000000 --- a/src/ios/Protocols/OSPMTRequestDelegate.swift +++ /dev/null @@ -1,123 +0,0 @@ -import PassKit - -// MARK: - OSPMTRequestTriggerDelegate Protocol and Related Methods -typealias OSPMTRequestTriggerCompletion = ((Bool) -> Void) - -/// Protocol that is responsible to trigger a payment request.. -protocol OSPMTRequestTriggerDelegate: AnyObject { - /// Triggers a payment request. The result is processed asyncrhonously and returned by the `completion` parameters. - /// - Parameter completion: Block that returns the success of the payment request operation. - func triggerPayment(_ completion: @escaping OSPMTRequestTriggerCompletion) -} - -/// Protocol that enhances the validation done by `OSPMTRequestTriggerDelegate` protocol and triggers a payment request for Apple Pay.. -protocol OSPMTApplePayRequestTriggerDelegate: OSPMTRequestTriggerDelegate { - /// Creates an object responsible for dealing with the payment request process, delegating the details to the passed parameter. - /// - Parameters: - /// - detailsModel: Payment details. - /// - delegate: The object responsible for the request process' response. - /// - Returns: An instance of the object or an error, it the instatiation fails. - static func createRequestTriggerBehaviour(for detailsModel: OSPMTDetailsModel, andDelegate delegate: OSPMTApplePayRequestBehaviour?) -> Result -} - -/// Protocol that manages the process request, in order to process a payment transaction. -protocol OSPMTRequestDelegate: AnyObject { - /// Sets Payment details and triggers its processing. - /// - Parameters: - /// - detailsModel: payment details information. - /// - completion: an async closure that can return a successful Payment Scope Model or an error otherwise. - func trigger(with detailsModel: OSPMTDetailsModel, _ completion: @escaping OSPMTCompletionHandler) -} - -/// Class that implements the `OSPMTRequestDelegate` for Apple Pay, providing it the required that details to work. -class OSPMTApplePayRequestBehaviour: NSObject, OSPMTRequestDelegate { - let configuration: OSPMTApplePayConfiguration - var requestTriggerType: OSPMTApplePayRequestTriggerDelegate.Type - - var paymentStatus: PKPaymentAuthorizationStatus = .failure - var paymentScope: OSPMTScopeModel? - var completionHandler: OSPMTCompletionHandler! - - /// Constructor method. - /// - Parameters: - /// - configuration: Apple Pay configuration manager. - /// - requestTriggerType: Apple Pay request type, used to create a request trigger processor class. - init(configuration: OSPMTApplePayConfiguration, requestTriggerType: OSPMTApplePayRequestTriggerDelegate.Type = PKPaymentAuthorizationController.self) { - self.configuration = configuration - self.requestTriggerType = requestTriggerType - } - - func trigger(with detailsModel: OSPMTDetailsModel, _ completion: @escaping OSPMTCompletionHandler) { - self.completionHandler = completion - - let result = self.requestTriggerType.createRequestTriggerBehaviour(for: detailsModel, andDelegate: self) - switch result { - case .success(let paymentController): - paymentController.triggerPayment { [weak self] presented in - guard let self = self else { return } - - self.paymentStatus = .failure - if !presented { - completion(.failure(.paymentTriggerPresentationFailed)) - } - } - case .failure(let error): - completion(.failure(error)) - } - } -} - -extension OSPMTApplePayRequestBehaviour { - /// Converts payment details information into an Apple Pay `PKPaymentSummaryItem` array type. - /// - Parameter detailsModel: Payment details information. - /// - Returns: The corresponding value if success, nil otherwise. - func getPaymentSummaryItems(for detailsModel: OSPMTDetailsModel) -> [PKPaymentSummaryItem]? { - guard let label = self.configuration.merchantName else { return nil } - return [PKPaymentSummaryItem(label: label, amount: detailsModel.paymentAmount, type: detailsModel.paymentSummaryItemType)] - } - - /// Converts the shipping/billing contact information text into an Apple Pay `PKContactField` set type. - /// - Parameter text: The billing/shipping contact information. - /// - Returns: The corresponding value. - func getContactFields(for text: [String]?) -> Set { - var result = [PKContactField]() - if let text = text { - result.append(contentsOf: text.compactMap(PKContactField.convert(from:))) - } - return Set(result) - } -} - -// MARK: - Set up PKPaymentAuthorizationControllerDelegate conformance -extension OSPMTApplePayRequestBehaviour: PKPaymentAuthorizationControllerDelegate { - /// Tells the delegate that payment authorization finished. - /// - Parameter controller: The payment authorization view controller. - func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) { - controller.dismiss() - // The payment sheet doesn't automatically dismiss once it has finished. Dismiss the payment sheet. - DispatchQueue.main.async { - if self.paymentStatus == .success, let paymentScope = self.paymentScope { - self.completionHandler(.success(paymentScope)) - } else { - self.completionHandler(.failure(.paymentCancelled)) - } - } - } - - /// Tells the delegate that the user authorized the payment request, and asks for a result. - /// - Parameters: - /// - controller: The payment authorization view controller. - /// - 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 scopeModel = payment.createScopeModel() { - self.paymentScope = scopeModel - self.paymentStatus = .success - } else { - self.paymentScope = nil - self.paymentStatus = .failure - } - - completion(PKPaymentAuthorizationResult(status: self.paymentStatus, errors: [])) - } -} From 70fe443e2e0c303d82c18482b8e131cec5b96a96 Mon Sep 17 00:00:00 2001 From: OS-ricardomoreirasilva Date: Mon, 28 Nov 2022 16:59:14 +0000 Subject: [PATCH 2/2] feat: Update iOS Library Update iOS library so that it includes Stripe. Add payment gateway configurations to Hook. --- CHANGELOG.md | 4 ++++ hooks/ios/iOSCopyPreferences.js | 38 ++++++++++++++++++++++++++++++++- plugin.xml | 14 ++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2870ee8..6bf819c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ The changes documented here do not include those from the original repository. ## [Unreleased] +### 2022-12-02 +- Chore: [iOS] Remove all the `OSPaymentsLib` files and replace them by the new `OSPaymentsPluginLib` pod. +- Feat: [iOS] Update hook so that it checks if Stripe's is configured as the Payment Service Provider and update `plist` file accordingly (https://outsystemsrd.atlassian.net/browse/RMET-2078). + ## [Version 1.0.1] ### 2022-11-08 diff --git a/hooks/ios/iOSCopyPreferences.js b/hooks/ios/iOSCopyPreferences.js index 21611b3..0348636 100644 --- a/hooks/ios/iOSCopyPreferences.js +++ b/hooks/ios/iOSCopyPreferences.js @@ -18,6 +18,9 @@ module.exports = function (context) { var payment_supported_card_countries = []; var shipping_supported_contacts = []; var billing_supported_contacts = []; + var payment_gateway = ""; + var payment_request_url = ""; + var stripe_publishable_key = ""; var appNamePath = path.join(projectRoot, 'config.xml'); var appNameParser = new ConfigParser(appNamePath); @@ -71,7 +74,27 @@ module.exports = function (context) { shipping_supported_contacts = configItem.shipping_supported_contacts; billing_supported_contacts = configItem.billing_supported_contacts; - payment_supported_card_countries = configItem.payment_supported_card_countries; + payment_supported_card_countries = configItem.payment_supported_card_countries; + + if (configItem.tokenization != null) { + if (configItem.tokenization.gateway != null && configItem.tokenization.gateway !== "") { + payment_gateway = configItem.tokenization.gateway; + } else { + error_list.push('Payment Gateway Name'); + } + + if (configItem.tokenization.requestURL != null && configItem.tokenization.requestURL !== "") { + payment_request_url = configItem.tokenization.requestURL; + } else { + error_list.push('Payment Request URL'); + } + + if (configItem.tokenization.stripePublishableKey != null && configItem.tokenization.stripePublishableKey !== "") { + stripe_publishable_key = configItem.tokenization.stripePublishableKey; + } else if (payment_gateway.toLowerCase() === "stripe") { + error_list.push('Stripe\'s Publishable Key'); + } + } if (error_list.length > 0) { throw new Error("Configuration is missing the following fields: " + error_list); @@ -95,6 +118,19 @@ module.exports = function (context) { infoPlist['ApplePayPaymentSupportedCardCountries'] = payment_supported_card_countries; infoPlist['ApplePayShippingSupportedContacts'] = shipping_supported_contacts; infoPlist['ApplePayBillingSupportedContacts'] = billing_supported_contacts; + if (payment_gateway !== "") { + infoPlist['ApplePayPaymentGateway']['ApplePayPaymentGatewayName'] = payment_gateway; + + if (payment_request_url !== "") { + infoPlist['ApplePayPaymentGateway']['ApplePayRequestURL'] = payment_request_url; + } + + if (stripe_publishable_key !== "") { + infoPlist['ApplePayPaymentGateway']['ApplePayStripePublishableKey'] = stripe_publishable_key; + } + } else { + delete infoPlist['ApplePayPaymentGateway']; + } fs.writeFileSync(infoPlistPath, plist.build(infoPlist, { indent: '\t' })); diff --git a/plugin.xml b/plugin.xml index bcf613c..a5c5c90 100644 --- a/plugin.xml +++ b/plugin.xml @@ -99,6 +99,19 @@ APPLE_PAY_BILLING_SUPPORTED_CONTACTS + + + ApplePayPaymentGatewayName + APPLE_PAY_PAYMENT_GATEWAY_NAME + + ApplePayRequestURL + APPLE_PAY_PAYMENT_REQUEST_URL + + ApplePayStripePublishableKey + APPLE_PAY_PAYMENT_STRIPE_PUBLISHABLE_KEY + + + @@ -109,6 +122,7 @@ +