Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions .github/workflows/check-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ on:
- 'release/*'

env:
destination: "platform=iOS Simulator,name=iPhone 16 Pro,OS=latest"
destination: "platform=iOS Simulator,name=iPhone 17 Pro,OS=26.1"
configuration: "Debug"
noIndex: "COMPILER_INDEX_STORE_ENABLE=NO"
noSigning: "CODE_SIGNING_ALLOWED=NO"
versionXcode: "16.0"
versionXcode: "26.2"

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -126,7 +126,7 @@ jobs:

- name: Select Xcode
run: |
sudo xcode-select -switch /Applications/Xcode_16.0.app
sudo xcode-select -switch /Applications/Xcode_26.2.app

- name: Log xcodebuild Version
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ concurrency:
cancel-in-progress: true

env:
destination: "platform=iOS Simulator,name=iPhone 16 Pro,OS=latest"
destination: "platform=iOS Simulator,name=iPhone 17 Pro,OS=latest"
configuration: "Debug"
noIndex: "COMPILER_INDEX_STORE_ENABLE=NO"
noSigning: "CODE_SIGNING_ALLOWED=NO"
versionXcode: "16.0"
versionXcode: "26.2"

jobs:
analyze:
Expand Down
10 changes: 3 additions & 7 deletions .github/workflows/run-regression-tests.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
name: Run Regression Tests

on:
pull_request:
types: [ labeled ]

workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
run-regression-tests:
if: (github.event_name == 'workflow_dispatch') || (contains(github.event.pull_request.labels.*.name, 'Run Regression Tests'))
name: Run Regression Tests
runs-on: macos-15-xlarge

Expand All @@ -22,15 +18,15 @@ jobs:

- name: Select Xcode
run: |
sudo xcode-select -switch /Applications/Xcode_16.0.app
sudo xcode-select -switch /Applications/Xcode_26.2.app

- name: Log xcodebuild Version
run: |
xcodebuild -version

- name: Run Regression Tests
run: |
set -o pipefail && xcodebuild "test" "-project" "iOS Example Frame SPM/iOS Example Frame SPM.xcodeproj" "-scheme" "Regression Tests" "-configuration" "Debug" "-destination" "platform=iOS Simulator,name=iPhone 16 Pro,OS=latest" | xcpretty
set -o pipefail && xcodebuild "test" "-project" "iOS Example Frame SPM/iOS Example Frame SPM.xcodeproj" "-scheme" "Regression Tests" "-configuration" "Debug" "-destination" "platform=iOS Simulator,name=iPhone 17 Pro,OS=latest" | xcpretty

#
# Comment out below only when needed, to avoid overhead.
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,7 @@ contents.xcworkspacedata
!*.xcworkspace/contents.xcworkspacedata
**/xcshareddata/WorkspaceSettings.xcsettings

# End of https://www.toptal.com/developers/gitignore/api/macos,swift,xcode,carthage,cocoapods,swiftpm
# End of https://www.toptal.com/developers/gitignore/api/macos,swift,xcode,carthage,cocoapods,swiftpm

*.build
Package.resolved
4 changes: 2 additions & 2 deletions Checkout.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Checkout'
s.version = '4.3.8'
s.version = '4.4.0'
s.summary = 'Checkout SDK for iOS'

s.description = <<-DESC
Expand All @@ -20,6 +20,6 @@ Pod::Spec.new do |s|
s.exclude_files = "Checkout/Samples/**"

s.dependency 'CheckoutEventLoggerKit', '~> 1.2.4'
s.dependency 'Risk', '~> 3.0.2'
s.dependency 'Risk', '~> 4.0.1'

end
2 changes: 1 addition & 1 deletion Checkout/Samples/CocoapodsSample/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ target 'CheckoutCocoapodsSample' do
use_frameworks!

# Pods for CheckoutSDKCocoapodsSample
pod 'Checkout', '4.3.8'
pod 'Checkout', :path => '../../../'
end
25 changes: 14 additions & 11 deletions Checkout/Samples/CocoapodsSample/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
PODS:
- Checkout (4.3.8):
- Checkout (4.4.0):
- CheckoutEventLoggerKit (~> 1.2.4)
- Risk (~> 3.0.2)
- Risk (~> 4.0.1)
- CheckoutEventLoggerKit (1.2.4)
- FingerprintPro (2.7.0)
- Risk (3.0.4):
- FingerprintPro (2.13.0)
- Risk (4.0.1):
- CheckoutEventLoggerKit (~> 1.2.4)
- FingerprintPro (~> 2.7.0)
- FingerprintPro (< 3.0.0, >= 2.7.0)

DEPENDENCIES:
- Checkout (= 4.3.8)
- Checkout (from `../../../`)

SPEC REPOS:
trunk:
- Checkout
- CheckoutEventLoggerKit
- FingerprintPro
- Risk

EXTERNAL SOURCES:
Checkout:
:path: "../../../"

SPEC CHECKSUMS:
Checkout: 609314d0c54a079d4c0ddfcfa7011367a12f225a
Checkout: 74ea5696bde3c3b85656c2b5c6446a07c8e89195
CheckoutEventLoggerKit: b780dec46295a34942780ea6230d0d5fd08aa05a
FingerprintPro: 0c7dbd28fc83751ca64b06328e2fb22bbc7ed118
Risk: 6c0fdbf826f741b028ec9158198404ce267d0d3e
FingerprintPro: 2f419138022451a72f783db9c94967f5a68e9977
Risk: e8ee31ba847b6cce1d4c384a9bb49d78fc34cdc5

PODFILE CHECKSUM: 9b0372a870e3437a2232753690edfe8385c4d6e0
PODFILE CHECKSUM: 36c08580c11dc09229142a4df18cbb3b7682087d

COCOAPODS: 1.16.2
7 changes: 7 additions & 0 deletions Checkout/Source/Logging/LogManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ enum LogManager: LogManaging {
}
}

/// Synchronously waits for all previously enqueued log work to finish.
/// Uses `loggingQueue.sync {}` so it is safe to call from any thread except the logging queue's own thread.
/// For test use only — not part of the public API.
static func _drainLoggingQueueForTesting() {
loggingQueue.sync { }
}

private static func log(_ event: CheckoutLogEvent, date: Date) {
let logEvent = event.event(date: date)

Expand Down
40 changes: 36 additions & 4 deletions Checkout/Source/Model/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,52 @@
import Foundation

protocol BaseURLProviding {
var baseURL: URL { get }
var baseURL: URL? { get }
}

private enum APIHost {
static let production = "api.checkout.com"
static let sandbox = "api.sandbox.checkout.com"

static func prefixed(_ prefix: String, environment: Environment) -> String {
switch environment {
case .production:
return "\(prefix).\(production)"
case .sandbox:
return "\(prefix).\(sandbox)"
}
}
}

/// Environment Enum for Production and Sandbox end points.
public enum Environment: String, BaseURLProviding {
case production
case sandbox

var baseURL: URL {
var baseURL: URL? {
let host: String
switch self {
case .production:
return URL(string: "https://api.checkout.com/")
host = APIHost.production
case .sandbox:
return URL(string: "https://api.sandbox.checkout.com/")
host = APIHost.sandbox
}
return URL(string: "https://\(host)/")
}
}

/// Provides a base URL for a given environment, optionally prefixed with a subdomain.
/// When `baseURLPrefix` is set (after trimming), URLs follow the pattern `{prefix}.api[.sandbox].checkout.com`.
struct EnvironmentURLProvider: BaseURLProviding {
let environment: Environment
let baseURLPrefix: String?

var baseURL: URL? {
let trimmed = baseURLPrefix?.trimmingCharacters(in: .whitespacesAndNewlines)
guard let prefix = trimmed, !prefix.isEmpty else {
return environment.baseURL
}
let host = APIHost.prefixed(prefix, environment: environment)
return URL(string: "https://\(host)/")
}
}
4 changes: 3 additions & 1 deletion Checkout/Source/Network/RequestFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ final class RequestFactory: RequestProviding {
}

func url(baseURLProvider: BaseURLProviding) -> Result<URL, RequestError> {
guard var urlComponents = URLComponents(url: baseURLProvider.baseURL, resolvingAgainstBaseURL: false) else {
guard let baseURL = baseURLProvider.baseURL,
var urlComponents = URLComponents(url:baseURL,
resolvingAgainstBaseURL: false) else {
return .failure(.baseURLCouldNotBeConvertedToComponents)
}

Expand Down
9 changes: 7 additions & 2 deletions Checkout/Source/Tokenisation/CheckoutAPIService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
import Foundation
import UIKit
import CheckoutEventLoggerKit
#if canImport(RiskSDK)
import RiskSDK
#elseif canImport(Risk)
import Risk
#endif

public protocol CheckoutAPIProtocol {
func createToken(_ paymentSource: PaymentSource, completion: @escaping (Result<TokenDetails, TokenisationError.TokenRequest>) -> Void)
Expand Down Expand Up @@ -36,7 +40,7 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {

/// Initializes a CheckoutAPIService object with public key and Environment.
/// CheckoutAPIService holds the core tokenisation logic methods to tokenise a user’s card details
public convenience init(publicKey: String, environment: Environment) {
public convenience init(publicKey: String, environment: Environment, baseURLPrefix: String? = nil) {
let snakeCaseJSONEncoder = JSONEncoder()
let snakeCaseJSONDecoder = JSONDecoder()

Expand All @@ -46,7 +50,8 @@ final public class CheckoutAPIService: CheckoutAPIProtocol {
let cardValidator = CardValidator(environment: environment)

let networkManager = NetworkManager(decoder: snakeCaseJSONDecoder, session: .shared)
let requestFactory = RequestFactory(encoder: snakeCaseJSONEncoder, baseURLProvider: environment)
let baseURLProvider = EnvironmentURLProvider(environment: environment, baseURLPrefix: baseURLPrefix)
let requestFactory = RequestFactory(encoder: snakeCaseJSONEncoder, baseURLProvider: baseURLProvider)
let tokenRequestFactory = TokenRequestFactory(cardValidator: cardValidator, decoder: snakeCaseJSONDecoder)
let tokenDetailsFactory = TokenDetailsFactory()
let logManager = LogManager.self
Expand Down
Loading
Loading