Skip to content

Commit 768e971

Browse files
authored
Return Result type instead of tuple of optionals (#316)
* card approve with Result type * card vault Result type * Result type for PayPal checkout, docStrings * paypal start docstrings error * Result type for PayPal vault * CHANGELOG * typo in docstrings
1 parent ee43afa commit 768e971

File tree

9 files changed

+300
-249
lines changed

9 files changed

+300
-249
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11

22
# PayPal iOS SDK Release Notes
33

4+
## Unreleased
5+
* Breaking Changes
6+
* PayPalWebPayments
7+
* Update completion handler types to use `Result` instead of optional tuples
8+
* Change `start` completion from `(PayPalWebCheckoutResult?, CoreSDKError?)` to `Result<PayPalWebCheckoutResult, CoreSDKError>`
9+
* Change `vault` completion from `(PayPalVaultResult?, CoreSDKError?)` to `Result<PayPalVaultResult, CoreSDKError>`
10+
* CardPayments
11+
* Update completion handler types to use `Result` instead of optional tuples
12+
* Change `approveOrder` completion from `(CardResult?, CoreSDKError?)` to `Result<CardResult, CoreSDKError>`
13+
* Change `vault` completion from `(CardVaultResult?, CoreSDKError?)` to `Result<CardVaultResult, CoreSDKError>`
14+
415
## 2.0.0-beta2 (2024-12-11)
516
* CorePayments
617
* Make `CoreSDKError` conform to Equatable

Demo/Demo/CardPayments/CardPaymentViewModel/CardPaymentViewModel.swift

+11-10
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,22 @@ class CardPaymentViewModel: ObservableObject {
118118
cardClient = CardClient(config: config)
119119
payPalDataCollector = PayPalDataCollector(config: config)
120120
let cardRequest = CardRequest(orderID: orderID, card: card, sca: sca)
121-
cardClient?.approveOrder(request: cardRequest) { result, error in
122-
if let error {
121+
cardClient?.approveOrder(request: cardRequest) { result in
122+
switch result {
123+
case .success(let cardResult):
124+
self.setApprovalSuccessResult(
125+
approveResult: CardPaymentState.CardResult(
126+
id: cardResult.orderID,
127+
status: cardResult.status,
128+
didAttemptThreeDSecureAuthentication: cardResult.didAttemptThreeDSecureAuthentication
129+
)
130+
)
131+
case .failure(let error):
123132
if error == CardError.threeDSecureCanceledError {
124133
self.setApprovalCancelResult()
125134
} else {
126135
self.setApprovalFailureResult(error: error)
127136
}
128-
} else if let result {
129-
self.setApprovalSuccessResult(
130-
approveResult: CardPaymentState.CardResult(
131-
id: result.orderID,
132-
status: result.status,
133-
didAttemptThreeDSecureAuthentication: result.didAttemptThreeDSecureAuthentication
134-
)
135-
)
136137
}
137138
}
138139
} catch {

Demo/Demo/CardVault/CardVaultViewModel/CardVaultViewModel.swift

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ class CardVaultViewModel: VaultViewModel {
1414
let config = try await configManager.getCoreConfig()
1515
let cardClient = CardClient(config: config)
1616
let cardVaultRequest = CardVaultRequest(card: card, setupTokenID: setupToken)
17-
cardClient.vault(cardVaultRequest) { result, error in
18-
if let result {
19-
self.setUpdateSetupTokenResult(vaultResult: result, vaultError: nil)
20-
} else if let error {
17+
cardClient.vault(cardVaultRequest) { result in
18+
switch result {
19+
case .success(let cardVaultResult):
20+
self.setUpdateSetupTokenResult(vaultResult: cardVaultResult, vaultError: nil)
21+
case .failure(let error):
2122
self.setUpdateSetupTokenResult(vaultResult: nil, vaultError: error)
2223
}
2324
}

Demo/Demo/PayPalVault/PayPalVaultViewModel/PayPalVaultViewModel.swift

+7-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ class PayPalVaultViewModel: VaultViewModel {
1414
let config = try await configManager.getCoreConfig()
1515
let paypalClient = PayPalWebCheckoutClient(config: config)
1616
let vaultRequest = PayPalVaultRequest(setupTokenID: setupTokenID)
17-
paypalClient.vault(vaultRequest) { result, error in
18-
if let error {
17+
paypalClient.vault(vaultRequest) { result in
18+
switch result {
19+
case .success(let cardVaultResult):
20+
DispatchQueue.main.async {
21+
self.state.paypalVaultTokenResponse = .loaded(cardVaultResult)
22+
}
23+
case .failure(let error):
1924
if error == PayPalError.vaultCanceledError {
2025
DispatchQueue.main.async {
2126
print("Canceled")
@@ -26,10 +31,6 @@ class PayPalVaultViewModel: VaultViewModel {
2631
self.state.paypalVaultTokenResponse = .error(message: error.localizedDescription)
2732
}
2833
}
29-
} else if let result {
30-
DispatchQueue.main.async {
31-
self.state.paypalVaultTokenResponse = .loaded(result)
32-
}
3334
}
3435
}
3536
} catch {

Demo/Demo/PayPalWebPayments/PayPalWebViewModel/PayPalWebViewModel.swift

+11-10
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,17 @@ class PayPalWebViewModel: ObservableObject {
8484

8585
if let orderID = state.createOrder?.id {
8686
let payPalRequest = PayPalWebCheckoutRequest(orderID: orderID, fundingSource: funding)
87-
payPalWebCheckoutClient.start(request: payPalRequest) { result, error in
88-
if let error {
87+
payPalWebCheckoutClient.start(request: payPalRequest) { result in
88+
switch result {
89+
case .success(let paypalResult):
90+
DispatchQueue.main.async {
91+
self.state.approveResultResponse = .loaded(
92+
PayPalPaymentState.ApprovalResult(id: paypalResult.orderID, status: "APPROVED")
93+
)
94+
self.checkoutResult = paypalResult
95+
print("✅ Checkout result: \(String(describing: paypalResult))")
96+
}
97+
case .failure(let error):
8998
DispatchQueue.main.async {
9099
if error == PayPalError.checkoutCanceledError {
91100
print("Canceled")
@@ -94,14 +103,6 @@ class PayPalWebViewModel: ObservableObject {
94103
self.state.approveResultResponse = .error(message: error.localizedDescription)
95104
}
96105
}
97-
} else {
98-
DispatchQueue.main.async {
99-
self.state.approveResultResponse = .loaded(
100-
PayPalPaymentState.ApprovalResult(id: orderID, status: "APPROVED")
101-
)
102-
self.checkoutResult = result
103-
print("✅ Checkout result: \(String(describing: result))")
104-
}
105106
}
106107
}
107108
}

Sources/CardPayments/CardClient.swift

+47-37
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@ public class CardClient: NSObject {
4141
/// - Parameters:
4242
/// - vaultRequest: The request containing setupTokenID and card
4343
/// - completion: A completion block that is invoked when the request is completed. If the request succeeds,
44-
/// a `CardVaultResult` with `setupTokenID` and `status` are returned and `error` will be `nil`;
45-
/// if it fails, `CardVaultResult will be `nil` and `error` will describe the failure
46-
public func vault(_ vaultRequest: CardVaultRequest, completion: @escaping (CardVaultResult?, CoreSDKError?) -> Void) {
44+
/// The closure returns a `Result`:
45+
/// - `.success(CardVaultResult)` containing:
46+
/// - `setupTokenID`: The ID of the token that was updated.
47+
/// - `status`: The setup token status.
48+
/// - `didAttemptThreeDSecureAuthentication`: A flag indicating if 3D Secure authentication was attempted.
49+
/// - `.failure(CoreSDKError)`: Describes the reason for failure.
50+
public func vault(_ vaultRequest: CardVaultRequest, completion: @escaping (Result<CardVaultResult, CoreSDKError>) -> Void) {
4751
analyticsService = AnalyticsService(coreConfig: config, setupToken: vaultRequest.setupTokenID)
4852
analyticsService?.sendEvent("card-payments:vault-wo-purchase:started")
4953
Task {
@@ -79,11 +83,12 @@ public class CardClient: NSObject {
7983
/// - Throws: A `CoreSDKError` describing failure
8084
public func vault(_ vaultRequest: CardVaultRequest) async throws -> CardVaultResult {
8185
try await withCheckedThrowingContinuation { continuation in
82-
vault(vaultRequest) { result, error in
83-
if let error {
86+
vault(vaultRequest) { result in
87+
switch result {
88+
case .success(let cardVaultResult):
89+
continuation.resume(returning: cardVaultResult)
90+
case .failure(let error):
8491
continuation.resume(throwing: error)
85-
} else if let result {
86-
continuation.resume(returning: result)
8792
}
8893
}
8994
}
@@ -94,10 +99,14 @@ public class CardClient: NSObject {
9499
/// - Parameters:
95100
/// - orderId: Order id for approval
96101
/// - request: The request containing the card
97-
/// - completion: A completion block that is invoked when the request is completed. If the request succeeds,
98-
/// a `CardResult` with `orderID` , `status` and `didAttemptThreeDSecureAuthentication` are returned and `error` will be `nil`;
99-
/// if it fails, `CardResult will be `nil` and `error` will describe the failure
100-
public func approveOrder(request: CardRequest, completion: @escaping (CardResult?, CoreSDKError?) -> Void) {
102+
/// - completion: A completion block that is invoked when the request is completed.
103+
/// The closure returns a `Result`:
104+
/// - `.success(CardResult)` containing:
105+
/// - `orderID`: The ID of the approved order.
106+
/// - `status`: The approval status.
107+
/// - `didAttemptThreeDSecureAuthentication`: A flag indicating if 3D Secure authentication was attempted.
108+
/// - `.failure(CoreSDKError)`: Describes the reason for failure.
109+
public func approveOrder(request: CardRequest, completion: @escaping (Result<CardResult, CoreSDKError>) -> Void) {
101110
analyticsService = AnalyticsService(coreConfig: config, orderID: request.orderID)
102111
analyticsService?.sendEvent("card-payments:approve-order:started")
103112
Task {
@@ -136,11 +145,12 @@ public class CardClient: NSObject {
136145
/// - Throws: A `CoreSDKError` describing failure
137146
public func approveOrder(request: CardRequest) async throws -> CardResult {
138147
try await withCheckedThrowingContinuation { continuation in
139-
approveOrder(request: request) { result, error in
140-
if let error {
148+
approveOrder(request: request) { result in
149+
switch result {
150+
case .success(let cardResult):
151+
continuation.resume(returning: cardResult)
152+
case .failure(let error):
141153
continuation.resume(throwing: error)
142-
} else if let result {
143-
continuation.resume(returning: result)
144154
}
145155
}
146156
}
@@ -149,7 +159,7 @@ public class CardClient: NSObject {
149159
private func startThreeDSecureChallenge(
150160
url: URL,
151161
orderId: String,
152-
completion: @escaping (CardResult?, CoreSDKError?) -> Void
162+
completion: @escaping (Result<CardResult, CoreSDKError>) -> Void
153163
) {
154164

155165
webAuthenticationSession.start(
@@ -188,7 +198,7 @@ public class CardClient: NSObject {
188198
private func startVaultThreeDSecureChallenge(
189199
url: URL,
190200
setupTokenID: String,
191-
completion: @escaping (CardVaultResult?, CoreSDKError?) -> Void
201+
completion: @escaping (Result<CardVaultResult, CoreSDKError>) -> Void
192202
) {
193203

194204
webAuthenticationSession.start(
@@ -220,54 +230,54 @@ public class CardClient: NSObject {
220230
)
221231
}
222232

223-
private func notifyCheckoutSuccess(for result: CardResult, completion: (CardResult?, CoreSDKError?) -> Void) {
233+
private func notifyCheckoutSuccess(for result: CardResult, completion: (Result<CardResult, CoreSDKError>) -> Void) {
224234
analyticsService?.sendEvent("card-payments:approve-order:succeeded")
225-
completion(result, nil)
235+
completion(.success(result))
226236
}
227237

228-
private func notify3dsCheckoutSuccess(for result: CardResult, completion: (CardResult?, CoreSDKError?) -> Void) {
238+
private func notify3dsCheckoutSuccess(for result: CardResult, completion: (Result<CardResult, CoreSDKError>) -> Void) {
229239
analyticsService?.sendEvent("card-payments:approve-order:auth-challenge:succeeded")
230-
completion(result, nil)
240+
completion(.success(result))
231241
}
232242

233-
private func notifyCheckoutFailure(with error: CoreSDKError, completion: (CardResult?, CoreSDKError?) -> Void) {
243+
private func notifyCheckoutFailure(with error: CoreSDKError, completion: (Result<CardResult, CoreSDKError>) -> Void) {
234244
analyticsService?.sendEvent("card-payments:approve-order:failed")
235-
completion(nil, error)
245+
completion(.failure(error))
236246
}
237247

238-
private func notify3dsCheckoutFailure(with error: CoreSDKError, completion: (CardResult?, CoreSDKError?) -> Void) {
248+
private func notify3dsCheckoutFailure(with error: CoreSDKError, completion: (Result<CardResult, CoreSDKError>) -> Void) {
239249
analyticsService?.sendEvent("card-payments:approve-order:auth-challenge:failed")
240-
completion(nil, error)
250+
completion(.failure(error))
241251
}
242252

243-
private func notify3dsCheckoutCancelWithError(with error: CoreSDKError, completion: (CardResult?, CoreSDKError?) -> Void) {
253+
private func notify3dsCheckoutCancelWithError(with error: CoreSDKError, completion: (Result<CardResult, CoreSDKError>) -> Void) {
244254
analyticsService?.sendEvent("card-payments:approve-order:auth-challenge:canceled")
245-
completion(nil, error)
255+
completion(.failure(error))
246256
}
247257

248-
private func notifyVaultSuccess(for vaultResult: CardVaultResult, completion: (CardVaultResult?, CoreSDKError?) -> Void) {
258+
private func notifyVaultSuccess(for vaultResult: CardVaultResult, completion: (Result<CardVaultResult, CoreSDKError>) -> Void) {
249259
analyticsService?.sendEvent("card-payments:vault-wo-purchase:succeeded")
250-
completion(vaultResult, nil)
260+
completion(.success(vaultResult))
251261
}
252262

253-
private func notify3dsVaultSuccess(for vaultResult: CardVaultResult, completion: (CardVaultResult?, CoreSDKError?) -> Void) {
263+
private func notify3dsVaultSuccess(for vaultResult: CardVaultResult, completion: (Result<CardVaultResult, CoreSDKError>) -> Void) {
254264
analyticsService?.sendEvent("card-payments:vault-wo-purchase:auth-challenge:succeeded")
255-
completion(vaultResult, nil)
265+
completion(.success(vaultResult))
256266
}
257267

258-
private func notifyVaultFailure(with vaultError: CoreSDKError, completion: (CardVaultResult?, CoreSDKError?) -> Void) {
268+
private func notifyVaultFailure(with vaultError: CoreSDKError, completion: (Result<CardVaultResult, CoreSDKError>) -> Void) {
259269
analyticsService?.sendEvent("card-payments:vault-wo-purchase:failed")
260-
completion(nil, vaultError)
270+
completion(.failure(vaultError))
261271
}
262272

263-
private func notify3dsVaultFailure(with vaultError: CoreSDKError, completion: (CardVaultResult?, CoreSDKError?) -> Void) {
273+
private func notify3dsVaultFailure(with vaultError: CoreSDKError, completion: (Result<CardVaultResult, CoreSDKError>) -> Void) {
264274
analyticsService?.sendEvent("card-payments:vault-wo-purchase:auth-challenge:failed")
265-
completion(nil, vaultError)
275+
completion(.failure(vaultError))
266276
}
267277

268-
private func notify3dsVaultCancelWithError(with vaultError: CoreSDKError, completion: (CardVaultResult?, CoreSDKError?) -> Void) {
278+
private func notify3dsVaultCancelWithError(with vaultError: CoreSDKError, completion: (Result<CardVaultResult, CoreSDKError>) -> Void) {
269279
analyticsService?.sendEvent("card-payments:vault-wo-purchase:auth-challenge:canceled")
270-
completion(nil, vaultError)
280+
completion(.failure(vaultError))
271281
}
272282
}
273283

0 commit comments

Comments
 (0)