Skip to content

Commit

Permalink
Result type for PayPal vault
Browse files Browse the repository at this point in the history
  • Loading branch information
KunJeongPark committed Jan 21, 2025
1 parent 1a4fbe7 commit 3857677
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ class PayPalVaultViewModel: VaultViewModel {
let config = try await configManager.getCoreConfig()
let paypalClient = PayPalWebCheckoutClient(config: config)
let vaultRequest = PayPalVaultRequest(setupTokenID: setupTokenID)
paypalClient.vault(vaultRequest) { result, error in
if let error {
paypalClient.vault(vaultRequest) { result in
switch result {
case .success(let cardVaultResult):
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .loaded(cardVaultResult)
}
case .failure(let error):
if error == PayPalError.vaultCanceledError {
DispatchQueue.main.async {
print("Canceled")
Expand All @@ -26,10 +31,6 @@ class PayPalVaultViewModel: VaultViewModel {
self.state.paypalVaultTokenResponse = .error(message: error.localizedDescription)
}
}
} else if let result {
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .loaded(result)
}
}
}
} catch {
Expand Down
30 changes: 17 additions & 13 deletions Sources/PayPalWebPayments/PayPalWebCheckoutClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ public class PayPalWebCheckoutClient: NSObject {
/// - Parameters:
/// - vaultRequest: Request created with url for vault approval and setupTokenID
/// - completion: A completion block that is invoked when the request is completed. If the request succeeds,
/// a `PayPalVaultResult` with `tokenID` and `approvalSessionID` are returned and `error` will be `nil`;
/// if it fails, `PayPalVaultResult will be `nil` and `error` will describe the failure
public func vault(_ vaultRequest: PayPalVaultRequest, completion: @escaping (PayPalVaultResult?, CoreSDKError?) -> Void) {
/// The closure returns a `PayPalVaultResult`:
/// - `.success(PayPalVaultResult)` containing:
/// - `tokenID`: The ID of the setup token.
/// - `approvalSessionID`: id of the PayPalWebCheckout session
/// - `.failure(CoreSDKError)`: Describes the reason for failure.
public func vault(_ vaultRequest: PayPalVaultRequest, completion: @escaping (Result<PayPalVaultResult, CoreSDKError>) -> Void) {
analyticsService = AnalyticsService(coreConfig: config, setupToken: vaultRequest.setupTokenID)
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:started")

Expand Down Expand Up @@ -191,11 +194,12 @@ public class PayPalWebCheckoutClient: NSObject {
/// - Throws: A `CoreSDKError` describing failure
public func vault(_ vaultRequest: PayPalVaultRequest) async throws -> PayPalVaultResult {
try await withCheckedThrowingContinuation { continuation in
vault(vaultRequest) { result, error in
if let error {
continuation.resume(throwing: error)
} else if let result {
vault(vaultRequest) { result in
switch result {
case .success(let result):
continuation.resume(returning: result)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
Expand Down Expand Up @@ -230,19 +234,19 @@ public class PayPalWebCheckoutClient: NSObject {
completion(.failure(error))
}

private func notifyVaultSuccess(for result: PayPalVaultResult, completion: (PayPalVaultResult?, CoreSDKError?) -> Void) {
private func notifyVaultSuccess(for result: PayPalVaultResult, completion: (Result<PayPalVaultResult, CoreSDKError>) -> Void) {
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:succeeded")
completion(result, nil)
completion(.success(result))
}

private func notifyVaultFailure(with error: CoreSDKError, completion: (PayPalVaultResult?, CoreSDKError?) -> Void) {
private func notifyVaultFailure(with error: CoreSDKError, completion: (Result<PayPalVaultResult, CoreSDKError>) -> Void) {
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:failed")
completion(nil, error)
completion(.failure(error))
}

private func notifyVaultCancelWithError(with vaultError: CoreSDKError, completion: (PayPalVaultResult?, CoreSDKError?) -> Void) {
private func notifyVaultCancelWithError(with vaultError: CoreSDKError, completion: (Result<PayPalVaultResult, CoreSDKError>) -> Void) {
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:canceled")
completion(nil, vaultError)
completion(.failure(vaultError))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class PayPalClient_Tests: XCTestCase {

func testVault_whenSandbox_launchesCorrectURLInWebSession() {
let vaultRequest = PayPalVaultRequest(setupTokenID: "fake-token")
payPalClient.vault(vaultRequest) { _, _ in }
payPalClient.vault(vaultRequest) { _ in }

XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://sandbox.paypal.com/agreements/approve?approval_session_id=fake-token")
}
Expand All @@ -40,7 +40,7 @@ class PayPalClient_Tests: XCTestCase {
)

let vaultRequest = PayPalVaultRequest(setupTokenID: "fake-token")
payPalClient.vault(vaultRequest) { _, _ in }
payPalClient.vault(vaultRequest) { _ in }

XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://paypal.com/agreements/approve?approval_session_id=fake-token")
}
Expand All @@ -55,10 +55,14 @@ class PayPalClient_Tests: XCTestCase {
let expectedSessionIDResult = "fakeSessionID"

let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest) { result, error in
XCTAssertEqual(expectedTokenIDResult, result?.tokenID)
XCTAssertEqual(expectedSessionIDResult, result?.approvalSessionID)
XCTAssertNil(error)
payPalClient.vault(vaultRequest) { result in
switch result {
case .success(let cardVaultResult):
XCTAssertEqual(expectedTokenIDResult, cardVaultResult.tokenID)
XCTAssertEqual(expectedSessionIDResult, cardVaultResult.approvalSessionID)
case .failure:
XCTFail("Expected success with CardVaultResult")
}
expectation.fulfill()
}

Expand All @@ -75,14 +79,14 @@ class PayPalClient_Tests: XCTestCase {
let expectation = expectation(description: "vault(url:) completed")

let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest) { result, error in
XCTAssertNil(result)
if let error {
payPalClient.vault(vaultRequest) { result in
switch result {
case .success:
XCTFail("Expected failure with error")
case .failure(let error):
XCTAssertEqual(error.domain, PayPalError.domain)
XCTAssertEqual(error.code, PayPalError.Code.vaultCanceledError.rawValue)
XCTAssertEqual(error.localizedDescription, "PayPal vault has been canceled by the user")
} else {
XCTFail("Expected error not to be nil")
}
expectation.fulfill()
}
Expand All @@ -100,12 +104,12 @@ class PayPalClient_Tests: XCTestCase {
let expectation = expectation(description: "vault(url:) completed")

let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest) { result, error in
if let error {
XCTAssertNil(result)
payPalClient.vault(vaultRequest) { result in
switch result {
case .success:
XCTFail("Expected failure with cancellation error")
case .failure(let error):
XCTAssertTrue(PayPalError.isVaultCanceled(error))
} else {
XCTFail("Expected error from PayPal vault cancellation")
}
expectation.fulfill()
}
Expand All @@ -125,13 +129,13 @@ class PayPalClient_Tests: XCTestCase {
let expectation = expectation(description: "vault(url:) completed")

let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest) { result, error in
XCTAssertNil(result)
if let error {
payPalClient.vault(vaultRequest) { result in
switch result {
case .success:
XCTFail("Expected failure with error")
case .failure(let error):
XCTAssertEqual(error.domain, expectedError.domain)
XCTAssertEqual(error.code, expectedError.code)
} else {
XCTFail("Expected error not to be nil")
}
expectation.fulfill()
}
Expand All @@ -140,29 +144,29 @@ class PayPalClient_Tests: XCTestCase {
}

func testVault_whenSuccessUrl_missingToken_returnsError() {

mockWebAuthenticationSession.cannedResponseURL = URL(string: "sdk.ios.paypal://vault/success?approval_token_id=&approval_session_id=fakeSessionID")

let expectation = expectation(description: "vault(url:) completed")

let expectedError = CoreSDKError(
code: PayPalError.payPalVaultResponseError.code,
domain: PayPalError.domain,
errorDescription: PayPalError.payPalVaultResponseError.errorDescription
)

let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest) { result, error in
XCTAssertNil(result)
if let error {
payPalClient.vault(vaultRequest) { result in
switch result {
case .success:
XCTFail("Expected failure with error")
case .failure(let error):
XCTAssertEqual(error.domain, expectedError.domain)
XCTAssertEqual(error.code, expectedError.code)
} else {
XCTFail("Expected error not to be nil")
}
expectation.fulfill()
}

waitForExpectations(timeout: 10)
}

Expand Down

0 comments on commit 3857677

Please sign in to comment.