Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/unverified commits #23

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3d8826d
chore: Include swiftlint
OS-ricardomoreirasilva Jun 27, 2022
5cba766
feat: Plugin init + Setup Configurations (#1)
OS-ricardomoreirasilva Aug 3, 2022
da8347a
feat: Check Wallet and Payment Availability (#2)
OS-ricardomoreirasilva Aug 4, 2022
34a3036
feat: Set Details and Trigger Payment (#3)
OS-ricardomoreirasilva Aug 8, 2022
edd4ca4
refactor: Add DocC documentation and minor fixes. (#4)
OS-ricardomoreirasilva Aug 10, 2022
5a9e350
fix: Payment Setup Verification Failed on Invalid Configuration (#5)
OS-ricardomoreirasilva Aug 11, 2022
fbb146b
fix: Errors and Contact Management (#6)
OS-ricardomoreirasilva Aug 25, 2022
b004408
fix: Check if GivenName and FamilyName are empty (#7)
OS-ricardomoreirasilva Aug 25, 2022
f25a410
chore: Add Unreleased Section
OS-ricardomoreirasilva Nov 7, 2022
135e633
Chore: Add Podspec (#9)
OS-ricardomoreirasilva Nov 15, 2022
a3c84e5
feat: Add Stripe as First Payment Gateway (#11)
OS-ricardomoreirasilva Dec 12, 2022
26f8ae3
Feat: Add Gateway property to OSPMTDetailsModel (#12)
OS-ricardomoreirasilva Dec 13, 2022
970a9fe
feat: Add AccessToken to Full Payment Process (#13)
OS-ricardomoreirasilva Jan 6, 2023
33a9513
chore: Set Release Tag
OS-ricardomoreirasilva Jan 9, 2023
9dd0cc4
Merge Development Into Main (#10)
OS-ricardomoreirasilva Nov 16, 2022
f60ab44
feat: Make library available as xcframework (#15)
OS-ricardomoreirasilva Feb 10, 2023
e5d0e07
chore: Set Release Tag
OS-ricardomoreirasilva Mar 1, 2023
2742370
Prepare Release 1.1.0 (#14)
OS-ricardomoreirasilva Jan 10, 2023
85c6068
Prepare Release 1.1.1 (#16)
OS-ricardomoreirasilva Mar 1, 2023
c3db0e0
fix: Update GitHub Actions (#17)
OS-ricardomoreirasilva Feb 23, 2024
de55aa8
RMET-3283 ::: Add Privacy Manifest (#19)
OS-ricardomoreirasilva Apr 10, 2024
244438c
RMET-3340 ::: Prepare Release `1.2.0` (#20)
OS-ricardomoreirasilva Apr 11, 2024
69340d3
chore: include something missed
OS-ricardomoreirasilva Apr 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions .github/workflows/github_actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,45 @@ on:
jobs:
test:
name: Unit-Tests
runs-on: macos-latest

runs-on: macos-14
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v4

- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Set up XCode
run: sudo xcode-select --switch /Applications/Xcode_15.1.app

- name: Bundle Install
run: bundle install

- name: Install Cocoapods
run: bundle exec pod install

- name: Link SwiftLint or install it
run: brew link --overwrite swiftlint || brew install swiftlint || brew link --overwrite swiftlint

- name: Unit tests
run: bundle exec fastlane unit_tests
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

- name: Code Coverage
run: bundle exec fastlane coverage

- name: Lint
run: bundle exec fastlane lint

- name: Setup sonarqube
uses: warchant/setup-sonar-scanner@v3
uses: warchant/setup-sonar-scanner@v8

- name: Send to Sonarcloud
run: bundle exec fastlane sonarqube
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONARCLOUD_KEY }}
SONAR_TOKEN: ${{ secrets.SONARCLOUD_KEY }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/
Podfile.lock
Gemfile.lock
33 changes: 33 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
disabled_rules:
- trailing_whitespace
opt_in_rules:
- empty_count
- empty_string
excluded:
- Carthage
- Pods
- vendor
- SwiftLint/Common/3rdPartyLib
line_length:
warning: 150
error: 200
ignores_function_declarations: true
ignores_comments: true
ignores_urls: true
function_body_length:
warning: 300
error: 500
function_parameter_count:
warning: 6
error: 8
type_body_length:
warning: 300
error: 500
file_length:
warning: 1000
error: 1500
ignore_comment_only_lines: true
cyclomatic_complexity:
warning: 15
error: 25
reporter: "xcode"
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# O11/ODC
* @OutSystems/rd-mobile-ecosystem
5 changes: 3 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
source "https://rubygems.org"

gem "fastlane"
gem "slather"
gem 'cocoapods', '1.14.3'
gem 'fastlane'
gem 'slather'
File renamed without changes.
428 changes: 413 additions & 15 deletions OSPaymentsLib.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "stripe-ios-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stripe/stripe-ios-spm",
"state" : {
"revision" : "87e3ebe7539e4408430606a5f1fbc9b88e67ae84",
"version" : "23.2.0"
}
}
],
"version" : 2
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1330"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down Expand Up @@ -45,7 +45,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
launchStyle = "1"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
Expand Down
10 changes: 10 additions & 0 deletions OSPaymentsLib.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
14 changes: 14 additions & 0 deletions OSPaymentsLib.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "stripe-ios-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stripe/stripe-ios-spm",
"state" : {
"revision" : "3631ddcfa4c5dcccc4609b1682bbdec3d586bba8",
"version" : "23.26.0"
}
}
],
"version" : 2
}
52 changes: 52 additions & 0 deletions OSPaymentsLib/Error/OSPMTError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation

/// All plugin errors that can be thrown
public 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

case gatewaySetFailed = 12
case stripePaymentMethodCreation = 13
case paymentIssue = 14
case gatewayNotConfigured = 15
case tokenIssue = 19

/// Textual description
public 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."

case .gatewaySetFailed:
return "Couldn't set payment service provider."
case .stripePaymentMethodCreation:
return "Couldn't obtain the PaymentMethod from Stripe."
case .paymentIssue:
return "Couldn't process payment."
case .gatewayNotConfigured:
return "Couldn't trigger the payment. The requested payment service provider is not configured yet."
case .tokenIssue:
return "Couldn’t trigger the payment. The access token is not defined."
}
}
}
21 changes: 21 additions & 0 deletions OSPaymentsLib/Extensions/PKContactField+Adapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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
}
}
}
21 changes: 21 additions & 0 deletions OSPaymentsLib/Extensions/PKMerchantCapability+Adapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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
}
}
}
9 changes: 9 additions & 0 deletions OSPaymentsLib/Extensions/PKPassLibrary+Adapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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()
}
}
98 changes: 98 additions & 0 deletions OSPaymentsLib/Extensions/PKPayment+Adapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import PassKit

extension PKPayment {
/// Converts a `PKPayment` object into a `OSPMTScopeModel` one. Returns `nil` if it can't.
/// - Parameter paymentGatewayModel: model that contains the payment gateway information resulting from completing a payment process.
/// - Returns: The corresponding `OSPMTScopeModel` object. Can also return `nil` if the conversion fails.
func createScopeModel(for paymentGatewayModel: OSPMTServiceProviderInfoModel? = nil) -> OSPMTScopeModel? {
var result: [String: Any] = [OSPMTScopeModel.CodingKeys.paymentData.rawValue: self.createTokenDataData(for: paymentGatewayModel)]
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.
/// - Parameter paymentGatewayModel: model that contains the payment gateway information resulting from completing a payment process.
/// - Returns: The corresponding `OSPMTDataModel` dictionary object.
private func createTokenDataData(for paymentGatewayModel: OSPMTServiceProviderInfoModel?) -> [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
}
}
if let paymentGatewayModel = paymentGatewayModel,
let paymentGatewayData = try? JSONEncoder().encode(paymentGatewayModel),
let paymentGatewayDict = try? JSONSerialization.jsonObject(with: paymentGatewayData) as? [String: String] {
result[OSPMTDataModel.CodingKeys.paymentServiceProviderData.rawValue] = paymentGatewayDict
}

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] {
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
}
}
Loading