Skip to content

Commit 1eb22f1

Browse files
authored
Remove PayPalVaultRequest required URL param (#279)
1 parent 99ed704 commit 1eb22f1

File tree

10 files changed

+66
-33
lines changed

10 files changed

+66
-33
lines changed

CHANGELOG.md

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

22
# PayPal iOS SDK Release Notes
33

4+
## unreleased
5+
* PayPalWebPayments
6+
* Deprecate `PayPalVaultRequest(url:setupTokenID:)`
7+
* Add `PayPalVaultRequest(setupTokenID:)`
8+
49
## 1.4.0 (2024-07-09)
510
* PayPalNativePayments (DEPRECATED)
611
* **Note:** This module is deprecated and will be removed in a future version of the SDK
712
* Add deprecated warning message to all public classes and methods
8-
13+
914
## 1.3.2 (2024-05-23)
1015
* PaymentButtons
1116
* Add black boundary around white buttons

Demo/Demo/Models/CreateSetupTokenResponse.swift

-9
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,9 @@ struct CreateSetupTokenResponse: Decodable, Equatable {
88

99
let id, status: String
1010
let customer: Customer?
11-
let links: [Link]
12-
var paypalURL: String? {
13-
links.first { $0.rel == "approve" }?.href
14-
}
1511

1612
struct Customer: Decodable {
1713

1814
let id: String
1915
}
20-
21-
struct Link: Decodable {
22-
23-
let href, rel, method: String
24-
}
2516
}

Demo/Demo/SwiftUIComponents/PayPalVaultViews/PayPalVaultView.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ struct PayPalVaultView: View {
1414
paymentSourceType: PaymentSourceType.paypal(usageType: "MERCHANT")
1515
)
1616
SetupTokenResultView(vaultViewModel: paypalVaultViewModel)
17-
if let urlString = paypalVaultViewModel.state.setupToken?.paypalURL,
18-
let setupTokenID = paypalVaultViewModel.state.setupToken?.id {
17+
if let setupTokenID = paypalVaultViewModel.state.setupToken?.id {
1918
Button("Vault PayPal") {
2019
Task {
21-
await paypalVaultViewModel.vault(url: urlString, setupTokenID: setupTokenID)
20+
await paypalVaultViewModel.vault(setupTokenID: setupTokenID)
2221
}
2322
}
2423
.buttonStyle(RoundedBlueButtonStyle())

Demo/Demo/SwiftUIComponents/VaultViews/SetupTokenResultView.swift

-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ struct SetupTokenResultView: View {
2828
LeadingText("\(setupTokenResponse.customer?.id ?? "")")
2929
LeadingText("Status", weight: .bold)
3030
LeadingText("\(setupTokenResponse.status)")
31-
if let url = setupTokenResponse.paypalURL {
32-
LeadingText("PayPalURL", weight: .bold)
33-
LeadingText("\(url)")
34-
}
3531
}
3632
.frame(maxWidth: .infinity)
3733
.padding()

Demo/Demo/ViewModels/PayPalVaultViewModel.swift

+2-5
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,15 @@ class PayPalVaultViewModel: VaultViewModel, PayPalVaultDelegate {
66

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

9-
func vault(url: String, setupTokenID: String) async {
10-
guard let payPalURL = URL(string: url) else {
11-
return
12-
}
9+
func vault(setupTokenID: String) async {
1310
DispatchQueue.main.async {
1411
self.state.paypalVaultTokenResponse = .loading
1512
}
1613
do {
1714
let config = try await configManager.getCoreConfig()
1815
let paypalClient = PayPalWebCheckoutClient(config: config)
1916
paypalClient.vaultDelegate = self
20-
let vaultRequest = PayPalVaultRequest(url: payPalURL, setupTokenID: setupTokenID)
17+
let vaultRequest = PayPalVaultRequest(setupTokenID: setupTokenID)
2118
paypalClient.vault(vaultRequest)
2219
} catch {
2320
print("Error in vaulting PayPal Payment")

Sources/CorePayments/Networking/Enums/Environment.swift

+10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ public enum Environment {
2323
}
2424
}
2525

26+
/// URL used to display the PayPal Vault w/o Purchase experience in web browser
27+
public var paypalVaultCheckoutURL: URL {
28+
switch self {
29+
case .sandbox:
30+
return URL(string: "https://sandbox.paypal.com/agreements/approve")!
31+
case .live:
32+
return URL(string: "https://paypal.com/agreements/approve")!
33+
}
34+
}
35+
2636
public var toString: String {
2737
switch self {
2838
case .sandbox:

Sources/PayPalWebPayments/PayPalVaultRequest.swift

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import Foundation
33
/// A request to vault a PayPal payment method
44
public struct PayPalVaultRequest {
55

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

910
/// ID for the setup token associated with the vault
1011
/// Returned as top level `id` from the setup token API call
@@ -14,8 +15,14 @@ public struct PayPalVaultRequest {
1415
/// - Parameters:
1516
/// - url: PayPal approval URL returned as the `href` from the setup token API call
1617
/// - setupTokenID: An ID for the setup token associated with the vault
18+
@available(*, deprecated, message: "Use `init(setupTokenID:)` instead.")
1719
public init(url: URL, setupTokenID: String) {
18-
self.url = url
20+
self.setupTokenID = setupTokenID
21+
}
22+
23+
/// Creates an instance of a PayPal vault request
24+
/// - Parameter setupTokenID: An ID for the setup token associated with the vault
25+
public init(setupTokenID: String) {
1926
self.setupTokenID = setupTokenID
2027
}
2128
}

Sources/PayPalWebPayments/PayPalWebCheckoutClient.swift

+10-1
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,17 @@ public class PayPalWebCheckoutClient: NSObject {
105105
analyticsService = AnalyticsService(coreConfig: config, setupToken: vaultRequest.setupTokenID)
106106
analyticsService?.sendEvent("paypal-web-payments:vault-wo-purchase:started")
107107

108+
var vaultURLComponents = URLComponents(url: config.environment.paypalVaultCheckoutURL, resolvingAgainstBaseURL: false)
109+
let queryItems = [URLQueryItem(name: "approval_session_id", value: vaultRequest.setupTokenID)]
110+
vaultURLComponents?.queryItems = queryItems
111+
112+
guard let vaultCheckoutURL = vaultURLComponents?.url else {
113+
notifyVaultFailure(with: PayPalWebCheckoutClientError.payPalURLError)
114+
return
115+
}
116+
108117
webAuthenticationSession.start(
109-
url: vaultRequest.url,
118+
url: vaultCheckoutURL,
110119
context: self,
111120
sessionDidDisplay: { [weak self] didDisplay in
112121
if didDisplay {

UnitTests/PayPalWebPaymentsTests/PayPalWebCheckoutClient_Tests.swift

+25-8
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,33 @@ class PayPalClient_Tests: XCTestCase {
2424
)
2525
}
2626

27+
func testVault_whenSandbox_launchesCorrectURLInWebSession() {
28+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fake-token")
29+
payPalClient.vault(vaultRequest)
30+
31+
XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://sandbox.paypal.com/agreements/approve?approval_session_id=fake-token")
32+
}
33+
34+
func testVault_whenLive_launchesCorrectURLInWebSession() {
35+
config = CoreConfig(clientID: "testClientID", environment: .live)
36+
let payPalClient = PayPalWebCheckoutClient(
37+
config: config,
38+
networkingClient: mockNetworkingClient,
39+
webAuthenticationSession: mockWebAuthenticationSession
40+
)
41+
42+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fake-token")
43+
payPalClient.vault(vaultRequest)
44+
45+
XCTAssertEqual(mockWebAuthenticationSession.lastLaunchedURL?.absoluteString, "https://paypal.com/agreements/approve?approval_session_id=fake-token")
46+
}
47+
2748
func testVault_whenSuccessUrl_ReturnsVaultToken() {
2849

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

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

33-
let url = URL(string: "https://sandbox.paypal.com/vault")
3454
let expectedTokenIDResult = "fakeTokenID"
3555
let expectedSessionIDResult = "fakeSessionID"
3656
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, result in
@@ -41,7 +61,7 @@ class PayPalClient_Tests: XCTestCase {
4161
XCTFail("Invoked error() callback. Should invoke success().")
4262
})
4363
payPalClient.vaultDelegate = mockVaultDelegate
44-
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
64+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
4565
payPalClient.vault(vaultRequest)
4666

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

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

59-
let url = URL(string: "https://sandbox.paypal.com/vault")
6079
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, _ in
6180
XCTFail("Invoked success callback. Should invoke cancel().")
6281
}, error: {_, _ in
@@ -66,7 +85,7 @@ class PayPalClient_Tests: XCTestCase {
6685
expectation.fulfill()
6786
})
6887
payPalClient.vaultDelegate = mockVaultDelegate
69-
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
88+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
7089
payPalClient.vault(vaultRequest)
7190

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

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

86-
let url = URL(string: "https://sandbox.paypal.com/vault")
87105
let mockVaultDelegate = MockPayPalVaultDelegate(success: {_, _ in
88106
XCTFail("Invoked success callback. Should invoke error().")
89107
}, error: {_, vaultError in
@@ -93,7 +111,7 @@ class PayPalClient_Tests: XCTestCase {
93111
XCTFail("Invoked cancel callback. Should invoke error().")
94112
})
95113
payPalClient.vaultDelegate = mockVaultDelegate
96-
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
114+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
97115
payPalClient.vault(vaultRequest)
98116

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

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

108-
let url = URL(string: "https://sandbox.paypal.com/vault")
109126
let expectedError = CoreSDKError(
110127
code: PayPalWebCheckoutClientError.payPalVaultResponseError.code,
111128
domain: PayPalWebCheckoutClientError.domain,
@@ -119,7 +136,7 @@ class PayPalClient_Tests: XCTestCase {
119136
expectation.fulfill()
120137
})
121138
payPalClient.vaultDelegate = mockVaultDelegate
122-
let vaultRequest = PayPalVaultRequest(url: url!, setupTokenID: "fakeTokenID")
139+
let vaultRequest = PayPalVaultRequest(setupTokenID: "fakeTokenID")
123140
payPalClient.vault(vaultRequest)
124141

125142
waitForExpectations(timeout: 10)

UnitTests/TestShared/MockWebAuthenticationSession.swift

+2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ class MockWebAuthenticationSession: WebAuthenticationSession {
77
var cannedResponseURL: URL?
88
var cannedErrorResponse: Error?
99
var cannedDidDisplayResult = true
10+
var lastLaunchedURL: URL?
1011

1112
override func start(
1213
url: URL,
1314
context: ASWebAuthenticationPresentationContextProviding,
1415
sessionDidDisplay: @escaping (Bool) -> Void,
1516
sessionDidComplete: @escaping (URL?, Error?) -> Void
1617
) {
18+
lastLaunchedURL = url
1719
sessionDidDisplay(cannedDidDisplayResult)
1820
sessionDidComplete(cannedResponseURL, cannedErrorResponse)
1921
}

0 commit comments

Comments
 (0)