Skip to content

Commit

Permalink
Remove PayPalVaultRequest required URL param (#279)
Browse files Browse the repository at this point in the history
  • Loading branch information
scannillo authored Jul 10, 2024
1 parent 99ed704 commit 1eb22f1
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 33 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@

# PayPal iOS SDK Release Notes

## unreleased
* PayPalWebPayments
* Deprecate `PayPalVaultRequest(url:setupTokenID:)`
* Add `PayPalVaultRequest(setupTokenID:)`

## 1.4.0 (2024-07-09)
* PayPalNativePayments (DEPRECATED)
* **Note:** This module is deprecated and will be removed in a future version of the SDK
* Add deprecated warning message to all public classes and methods

## 1.3.2 (2024-05-23)
* PaymentButtons
* Add black boundary around white buttons
Expand Down
9 changes: 0 additions & 9 deletions Demo/Demo/Models/CreateSetupTokenResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,9 @@ struct CreateSetupTokenResponse: Decodable, Equatable {

let id, status: String
let customer: Customer?
let links: [Link]
var paypalURL: String? {
links.first { $0.rel == "approve" }?.href
}

struct Customer: Decodable {

let id: String
}

struct Link: Decodable {

let href, rel, method: String
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ struct PayPalVaultView: View {
paymentSourceType: PaymentSourceType.paypal(usageType: "MERCHANT")
)
SetupTokenResultView(vaultViewModel: paypalVaultViewModel)
if let urlString = paypalVaultViewModel.state.setupToken?.paypalURL,
let setupTokenID = paypalVaultViewModel.state.setupToken?.id {
if let setupTokenID = paypalVaultViewModel.state.setupToken?.id {
Button("Vault PayPal") {
Task {
await paypalVaultViewModel.vault(url: urlString, setupTokenID: setupTokenID)
await paypalVaultViewModel.vault(setupTokenID: setupTokenID)
}
}
.buttonStyle(RoundedBlueButtonStyle())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ struct SetupTokenResultView: View {
LeadingText("\(setupTokenResponse.customer?.id ?? "")")
LeadingText("Status", weight: .bold)
LeadingText("\(setupTokenResponse.status)")
if let url = setupTokenResponse.paypalURL {
LeadingText("PayPalURL", weight: .bold)
LeadingText("\(url)")
}
}
.frame(maxWidth: .infinity)
.padding()
Expand Down
7 changes: 2 additions & 5 deletions Demo/Demo/ViewModels/PayPalVaultViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@ class PayPalVaultViewModel: VaultViewModel, PayPalVaultDelegate {

let configManager = CoreConfigManager(domain: "PayPal Vault")

func vault(url: String, setupTokenID: String) async {
guard let payPalURL = URL(string: url) else {
return
}
func vault(setupTokenID: String) async {
DispatchQueue.main.async {
self.state.paypalVaultTokenResponse = .loading
}
do {
let config = try await configManager.getCoreConfig()
let paypalClient = PayPalWebCheckoutClient(config: config)
paypalClient.vaultDelegate = self
let vaultRequest = PayPalVaultRequest(url: payPalURL, setupTokenID: setupTokenID)
let vaultRequest = PayPalVaultRequest(setupTokenID: setupTokenID)
paypalClient.vault(vaultRequest)
} catch {
print("Error in vaulting PayPal Payment")
Expand Down
10 changes: 10 additions & 0 deletions Sources/CorePayments/Networking/Enums/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ public enum Environment {
}
}

/// URL used to display the PayPal Vault w/o Purchase experience in web browser
public var paypalVaultCheckoutURL: URL {
switch self {
case .sandbox:
return URL(string: "https://sandbox.paypal.com/agreements/approve")!
case .live:
return URL(string: "https://paypal.com/agreements/approve")!
}
}

public var toString: String {
switch self {
case .sandbox:
Expand Down
11 changes: 9 additions & 2 deletions Sources/PayPalWebPayments/PayPalVaultRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import Foundation
/// A request to vault a PayPal payment method
public struct PayPalVaultRequest {

// NEXT_MAJOR_VERSION: - Remove URL property
/// PayPal approval URL returned as the `href` from the setup token API call
public let url: URL
public let url: URL? = nil

/// ID for the setup token associated with the vault
/// Returned as top level `id` from the setup token API call
Expand All @@ -14,8 +15,14 @@ public struct PayPalVaultRequest {
/// - Parameters:
/// - url: PayPal approval URL returned as the `href` from the setup token API call
/// - setupTokenID: An ID for the setup token associated with the vault
@available(*, deprecated, message: "Use `init(setupTokenID:)` instead.")
public init(url: URL, setupTokenID: String) {
self.url = url
self.setupTokenID = setupTokenID
}

/// Creates an instance of a PayPal vault request
/// - Parameter setupTokenID: An ID for the setup token associated with the vault
public init(setupTokenID: String) {
self.setupTokenID = setupTokenID
}
}
11 changes: 10 additions & 1 deletion Sources/PayPalWebPayments/PayPalWebCheckoutClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,17 @@ public class PayPalWebCheckoutClient: NSObject {
analyticsService = AnalyticsService(coreConfig: config, setupToken: vaultRequest.setupTokenID)
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:started")

var vaultURLComponents = URLComponents(url: config.environment.paypalVaultCheckoutURL, resolvingAgainstBaseURL: false)
let queryItems = [URLQueryItem(name: "approval_session_id", value: vaultRequest.setupTokenID)]
vaultURLComponents?.queryItems = queryItems

guard let vaultCheckoutURL = vaultURLComponents?.url else {
notifyVaultFailure(with: PayPalWebCheckoutClientError.payPalURLError)
return
}

webAuthenticationSession.start(
url: vaultRequest.url,
url: vaultCheckoutURL,
context: self,
sessionDidDisplay: { [weak self] didDisplay in
if didDisplay {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,33 @@ class PayPalClient_Tests: XCTestCase {
)
}

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

XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://sandbox.paypal.com/agreements/approve?approval_session_id=fake-token")
}

func testVault_whenLive_launchesCorrectURLInWebSession() {
config = CoreConfig(clientID: "testClientID", environment: .live)
let payPalClient = PayPalWebCheckoutClient(
config: config,
networkingClient: mockNetworkingClient,
webAuthenticationSession: mockWebAuthenticationSession
)

let vaultRequest = PayPalVaultRequest(setupTokenID: "fake-token")
payPalClient.vault(vaultRequest)

XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://paypal.com/agreements/approve?approval_session_id=fake-token")
}

func testVault_whenSuccessUrl_ReturnsVaultToken() {

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

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

let url = URL(string: "https://sandbox.paypal.com/vault")
let expectedTokenIDResult = "fakeTokenID"
let expectedSessionIDResult = "fakeSessionID"
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, result in
Expand All @@ -41,7 +61,7 @@ class PayPalClient_Tests: XCTestCase {
XCTFail("Invoked error() callback. Should invoke success().")
})
payPalClient.vaultDelegate = mockVaultDelegate
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest)

waitForExpectations(timeout: 10)
Expand All @@ -56,7 +76,6 @@ class PayPalClient_Tests: XCTestCase {

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

let url = URL(string: "https://sandbox.paypal.com/vault")
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, _ in
XCTFail("Invoked success callback. Should invoke cancel().")
}, error: {_, _ in
Expand All @@ -66,7 +85,7 @@ class PayPalClient_Tests: XCTestCase {
expectation.fulfill()
})
payPalClient.vaultDelegate = mockVaultDelegate
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest)

waitForExpectations(timeout: 10)
Expand All @@ -83,7 +102,6 @@ class PayPalClient_Tests: XCTestCase {

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

let url = URL(string: "https://sandbox.paypal.com/vault")
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, _ in
XCTFail("Invoked success callback. Should invoke error().")
}, error: {_, vaultError in
Expand All @@ -93,7 +111,7 @@ class PayPalClient_Tests: XCTestCase {
XCTFail("Invoked cancel callback. Should invoke error().")
})
payPalClient.vaultDelegate = mockVaultDelegate
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest)

waitForExpectations(timeout: 10)
Expand All @@ -105,7 +123,6 @@ class PayPalClient_Tests: XCTestCase {

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

let url = URL(string: "https://sandbox.paypal.com/vault")
let expectedError = CoreSDKError(
code: PayPalWebCheckoutClientError.payPalVaultResponseError.code,
domain: PayPalWebCheckoutClientError.domain,
Expand All @@ -119,7 +136,7 @@ class PayPalClient_Tests: XCTestCase {
expectation.fulfill()
})
payPalClient.vaultDelegate = mockVaultDelegate
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
payPalClient.vault(vaultRequest)

waitForExpectations(timeout: 10)
Expand Down
2 changes: 2 additions & 0 deletions UnitTests/TestShared/MockWebAuthenticationSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ class MockWebAuthenticationSession: WebAuthenticationSession {
var cannedResponseURL: URL?
var cannedErrorResponse: Error?
var cannedDidDisplayResult = true
var lastLaunchedURL: URL?

override func start(
url: URL,
context: ASWebAuthenticationPresentationContextProviding,
sessionDidDisplay: @escaping (Bool) -> Void,
sessionDidComplete: @escaping (URL?, Error?) -> Void
) {
lastLaunchedURL = url
sessionDidDisplay(cannedDidDisplayResult)
sessionDidComplete(cannedResponseURL, cannedErrorResponse)
}
Expand Down

0 comments on commit 1eb22f1

Please sign in to comment.