Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BTPayPalEditRequest and Tokenize for Edit FI #1358

Merged
merged 9 commits into from
Jul 11, 2024
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
16 changes: 12 additions & 4 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
3B29C3952B90F12F0077741D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3B29C3942B90F12F0077741D /* PrivacyInfo.xcprivacy */; };
3B57E9EA29ECC1AF00245174 /* BTLocalPaymentAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B57E9E929ECC1AF00245174 /* BTLocalPaymentAnalytics.swift */; };
3B5A41E92BA2375600921922 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3B5A41E82BA2375600921922 /* PrivacyInfo.xcprivacy */; };
3B5CD9B02C3C3FCC002EE8F7 /* BTPayPalEditRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B5CD9AF2C3C3FCC002EE8F7 /* BTPayPalEditRequest.swift */; };
3B610FD32C3DEE220098EFBB /* BTPayPalEditRequest_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B610FD12C3DEE1C0098EFBB /* BTPayPalEditRequest_Tests.swift */; };
3B7A261129C0CAA40087059D /* BTPayPalAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B7A261029C0CAA40087059D /* BTPayPalAnalytics.swift */; };
3B7A261429C35BD00087059D /* BTPayPalAnalytics_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B7A261229C35B670087059D /* BTPayPalAnalytics_Tests.swift */; };
3BC0E09229E4673C009217D6 /* BTSEPADirectAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC0E09129E4673C009217D6 /* BTSEPADirectAnalytics.swift */; };
Expand Down Expand Up @@ -53,10 +55,10 @@
428F976626727333001042E1 /* BTMockOpenURLContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 428F976526727333001042E1 /* BTMockOpenURLContext.m */; };
42FC218B25CDE0290047C49A /* BTPayPalRequest_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42FC218A25CDE0290047C49A /* BTPayPalRequest_Tests.swift */; };
42FC237125CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42FC237025CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift */; };
457D7FC82C29CEC300EF6523 /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */; };
457D7FCA2C2A250E00EF6523 /* RepeatingTimer_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */; };
45227FC52C330FDE00A15018 /* MockURLSessionTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45227FC32C330FDE00A15018 /* MockURLSessionTask.swift */; };
45227FC72C33104100A15018 /* MockBTHTTPNetworkTiming.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45227FC62C33104100A15018 /* MockBTHTTPNetworkTiming.swift */; };
457D7FC82C29CEC300EF6523 /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */; };
457D7FCA2C2A250E00EF6523 /* RepeatingTimer_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */; };
460C0C220F594AE8EE205E57 /* Pods_Tests_BraintreeCoreTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9239C9FE850C3587DE61A3A2 /* Pods_Tests_BraintreeCoreTests.framework */; };
5708E0A628809AD9007946B9 /* BTJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5708E0A528809AD9007946B9 /* BTJSON.swift */; };
5708E0A828809BC6007946B9 /* BTJSONError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5708E0A728809BC6007946B9 /* BTJSONError.swift */; };
Expand Down Expand Up @@ -730,6 +732,8 @@
3B29C3942B90F12F0077741D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3B57E9E929ECC1AF00245174 /* BTLocalPaymentAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTLocalPaymentAnalytics.swift; sourceTree = "<group>"; };
3B5A41E82BA2375600921922 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3B5CD9AF2C3C3FCC002EE8F7 /* BTPayPalEditRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalEditRequest.swift; sourceTree = "<group>"; };
3B610FD12C3DEE1C0098EFBB /* BTPayPalEditRequest_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalEditRequest_Tests.swift; sourceTree = "<group>"; };
3B668B7D2BFD12BE0024FB29 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3B7A261029C0CAA40087059D /* BTPayPalAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalAnalytics.swift; sourceTree = "<group>"; };
3B7A261229C35B670087059D /* BTPayPalAnalytics_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalAnalytics_Tests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -776,10 +780,10 @@
42F75E5A24D48138007DC5E7 /* BTThreeDSecureClient_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecureClient_Tests.swift; sourceTree = "<group>"; };
42FC218A25CDE0290047C49A /* BTPayPalRequest_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalRequest_Tests.swift; sourceTree = "<group>"; };
42FC237025CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTPayPalCheckoutRequest_Tests.swift; sourceTree = "<group>"; };
457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = "<group>"; };
457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer_Tests.swift; sourceTree = "<group>"; };
45227FC32C330FDE00A15018 /* MockURLSessionTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockURLSessionTask.swift; sourceTree = "<group>"; };
45227FC62C33104100A15018 /* MockBTHTTPNetworkTiming.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockBTHTTPNetworkTiming.swift; sourceTree = "<group>"; };
457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = "<group>"; };
457D7FC92C2A250E00EF6523 /* RepeatingTimer_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer_Tests.swift; sourceTree = "<group>"; };
463DED22C0F426A474E6D7E2 /* Pods-Tests-BraintreeCoreTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-BraintreeCoreTests.release.xcconfig"; path = "Target Support Files/Pods-Tests-BraintreeCoreTests/Pods-Tests-BraintreeCoreTests.release.xcconfig"; sourceTree = "<group>"; };
541AEE40A1F01913E0638CC9 /* Pods-Tests-BraintreeCoreTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-BraintreeCoreTests.debug.xcconfig"; path = "Target Support Files/Pods-Tests-BraintreeCoreTests/Pods-Tests-BraintreeCoreTests.debug.xcconfig"; sourceTree = "<group>"; };
5708E0A528809AD9007946B9 /* BTJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTJSON.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1380,6 +1384,7 @@
BE6BC22B2BA9C67600C3E321 /* BTPayPalVaultBaseRequest.swift */,
BE349110294B77E100D2CF68 /* BTPayPalVaultRequest.swift */,
62A659A32B98CB23008DFD67 /* PrivacyInfo.xcprivacy */,
3B5CD9AF2C3C3FCC002EE8F7 /* BTPayPalEditRequest.swift */,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure these files are alphabetized?

);
path = BraintreePayPal;
sourceTree = "<group>";
Expand Down Expand Up @@ -1949,6 +1954,7 @@
BEBA590E2BB1B5B9005FA8A2 /* BTPayPalReturnURL_Tests.swift */,
427F328F25D1A7B900435294 /* BTPayPalVaultRequest_Tests.swift */,
A9E5C1E424FD665D00EE691F /* Info.plist */,
3B610FD12C3DEE1C0098EFBB /* BTPayPalEditRequest_Tests.swift */,
);
path = BraintreePayPalTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -3204,6 +3210,7 @@
BE549F122BF5449E00B6F441 /* BTPayPalVaultBaseRequest.swift in Sources */,
3B7A261129C0CAA40087059D /* BTPayPalAnalytics.swift in Sources */,
BE8E5CEF294B6937001BF017 /* BTPayPalCheckoutRequest.swift in Sources */,
3B5CD9B02C3C3FCC002EE8F7 /* BTPayPalEditRequest.swift in Sources */,
5754481E294A2A1D00DEB7B0 /* BTPayPalCreditFinancingAmount.swift in Sources */,
57D9436E2968A8080079EAB1 /* BTPayPalLocaleCode.swift in Sources */,
57544F582952298900DEB7B0 /* BTPayPalAccountNonce.swift in Sources */,
Expand Down Expand Up @@ -3550,6 +3557,7 @@
42FC218B25CDE0290047C49A /* BTPayPalRequest_Tests.swift in Sources */,
42FC237125CE0E110047C49A /* BTPayPalCheckoutRequest_Tests.swift in Sources */,
BEDEAF112AC1D049004EA970 /* BTPayPalAccountNonce_Tests.swift in Sources */,
3B610FD32C3DEE220098EFBB /* BTPayPalEditRequest_Tests.swift in Sources */,
427F329025D1A7B900435294 /* BTPayPalVaultRequest_Tests.swift in Sources */,
BECB10C62B5999EE008D398E /* BTPayPalLineItem_Tests.swift in Sources */,
3B7A261429C35BD00087059D /* BTPayPalAnalytics_Tests.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Braintree iOS SDK Release Notes

## unreleased
* BraintreePayPal
* Add PayPal edit funding instrument flow (BETA)
* Add `BTPayPalEditRequest` for edit FI flow
* Add `BTPayPalClient.tokenize(_:completion:)` method that takes in a `BTPayPalEditRequest`
* **Note:** This feature is currently in beta and may change or be removed in future releases

## 6.22.0 (2024-07-02)
* BraintreeThreeDSecure
* Add `customFields` param to `BTThreeDSecureRequest`
Expand Down
38 changes: 38 additions & 0 deletions Sources/BraintreePayPal/BTPayPalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,44 @@ import BraintreeDataCollector
}
}

/// Tokenize a PayPal request to be used with the Edit FI flow.
///
/// On success, you will receive an instance of `BTPayPalAccountNonce`; on failure or user cancelation you will receive an error.
/// If the user cancels out of the flow, the error code will be `.canceled`.
///
/// - Parameters:
/// - request: A `BTPayPalEditRequest`
/// - completion: This completion will be invoked exactly once when tokenization is complete or an error occurs.
/// - Warning: This feature is currently in beta and may change or be removed in future releases.
public func tokenize(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to Jax's comment re: only supporting new features in Swift, what do folks think about only supporting new features in the async-await method syntax? We could hold on the completion style syntax and add it later based on merchant feedback? Is now a good time to trial this?

Would love folks thoughts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People I've talked to are working with async-await syntax in their code bases, but that's just a small sampling. I'm sure there are a lot of companies with legacy repos.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a great point - i wonder how many merchants are transitioning to or already using the async/await style over the completion style syntax. imo i like that having both signatures gives merchants the choice to choose what works best for them but i also feel the asyn/await reads more clearly

Copy link
Contributor

@scannillo scannillo Jul 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! I like the brevity of the async-await style lately too

I think V7 will be a good chance to yank the completion syntax 👀

_ request: BTPayPalEditRequest,
completion: @escaping (BTPayPalAccountNonce?, Error?) -> Void
) {
// TODO: call API to get FI URL and return a BTPayPalNonce or Error
completion(nil, nil)
}

/// Tokenize a PayPal request to be used with the Edit FI flow.
///
/// On success, you will receive an instance of `BTPayPalAccountNonce`; on failure or user cancelation you will receive an error.
/// If the user cancels out of the flow, the error code will be `.canceled`.
///
/// - Parameter request: A `BTPayPalEditRequest`
/// - Returns: A `BTPayPalAccountNonce` if successful
/// - Throws: An `Error` describing the failure
/// - Warning: This feature is currently in beta and may change or be removed in future releases.
public func tokenize(_ request: BTPayPalEditRequest) async throws -> BTPayPalAccountNonce {
try await withCheckedThrowingContinuation { continuation in
tokenize(request) { nonce, error in
if let error {
continuation.resume(throwing: error)
} else if let nonce {
continuation.resume(returning: nonce)
}
}
}
}

KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved
// MARK: - Internal Methods

func handleReturn(
Expand Down
19 changes: 19 additions & 0 deletions Sources/BraintreePayPal/BTPayPalEditRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation

#if canImport(BraintreeCore)
import BraintreeCore
#endif

/// Options for the PayPal Edit FI flow
/// - Warning: This feature is currently in beta and may change or be removed in future releases.
public class BTPayPalEditRequest {
private let token: String

/// Initializes a PayPal Edit Request for the Edit FI flow
/// - Parameters:
/// - token: Required: Used to initiate tokenize call to edit funding instrument in customer's PayPal account.
KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved
// TODO: specify endpoint for merchant to retrieve the token
public init(token: String) {
self.token = token
}
}
18 changes: 18 additions & 0 deletions UnitTests/BraintreePayPalTests/BTPayPalClient_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ class BTPayPalClient_Tests: XCTestCase {
self.waitForExpectations(timeout: 1)
}

func testTokenizePayPalEditRequest_whenResponseIsSuccessful_returnsPayPalAccountNonce() {
KunJeongPark marked this conversation as resolved.
Show resolved Hide resolved
let editRequest = BTPayPalEditRequest(token: "test-token")

// TODO: implement test to return PayPalAccountNonce
}

func testTokenizePayPalEditRequest_whenResponseIsError_returnsError() {
let editRequest = BTPayPalEditRequest(token: "test-token")

// TODO: implement test to return Error
}

func testTokenizePayPalEditRequest_whenUserCancels_returnsError() {
let editRequest = BTPayPalEditRequest(token: "test-token")

// TODO: implement test to return Error
}

// MARK: - PayPal approval URL to present in browser

func testTokenizePayPalAccount_checkout_whenUserActionIsNotSet_approvalUrlIsNotModified() {
Expand Down
17 changes: 17 additions & 0 deletions UnitTests/BraintreePayPalTests/BTPayPalEditRequest_Tests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import XCTest
@testable import BraintreeCore
@testable import BraintreePayPal

class BTPayPalEditRequest_Tests: XCTestCase {

override func setUp() {
super.setUp()
}

func test_returnsAllParams() {
let expectedToken = "test-token"
let editRequest = BTPayPalEditRequest(token: expectedToken)

// TODO: implement checking expected params returned
}
}
Loading