Skip to content

Commit

Permalink
Removed Venmo fallbacktoWeb (#1434)
Browse files Browse the repository at this point in the history
* Removed Venmo `fallbacktoWeb`

* Addressed PR comment

* Updated CHANGELOG

* Removed `LinkType` and `urlSchemeURL()`

* Added link type back to PayPal

* Fixed `linkType` error

* Removed Venmo UI tests. Updated docstrings

* Updated CHANGELOG

* Revert "Merge branch 'v7' of https://github.com/braintree/braintree_ios into v7-venmo-universal-link"

This reverts commit 438dfc7, reversing
changes made to 1a24560.

* Revert "Revert "Merge branch 'v7' of https://github.com/braintree/braintree_ios into v7-venmo-universal-link""

This reverts commit 2d0d7e0.

* Reset v7 files

* Removed duplicate LinkType file

* Removed unused `return`

* Reverted cocoapods version

* Updated migration guide. Added `TODO`
  • Loading branch information
stechiu authored Nov 12, 2024
1 parent 3fba4f1 commit 3867268
Show file tree
Hide file tree
Showing 13 changed files with 30 additions and 203 deletions.
8 changes: 4 additions & 4 deletions Braintree.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
04ECD8A02CC9CB1E000329EC /* LinkType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ECD89F2CC9CB1A000329EC /* LinkType.swift */; };
0917F6E42A27BDC700ACED2E /* BTVenmoLineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 096C6B2529CCDCEB00912863 /* BTVenmoLineItem.swift */; };
09357DCB2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09357DCA2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift */; };
1FEB89E614CB6BF0B9858EE4 /* Pods_Tests_IntegrationTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 85BD589D380436A0C9D1DEC1 /* Pods_Tests_IntegrationTests.framework */; };
Expand Down Expand Up @@ -313,7 +314,6 @@
BED00CAE28A5419900D74AEC /* BTBinData.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED00CAD28A5419900D74AEC /* BTBinData.swift */; };
BED00CB028A579D700D74AEC /* BTClientToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED00CAF28A579D700D74AEC /* BTClientToken.swift */; };
BED00CB228A57AD400D74AEC /* BTClientTokenError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED00CB128A57AD400D74AEC /* BTClientTokenError.swift */; };
BED3A2C62C5D74B20034D9A6 /* LinkType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED3A2C52C5D74AC0034D9A6 /* LinkType.swift */; };
BED7493628579BAC0074C818 /* BTURLUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED7493528579BAC0074C818 /* BTURLUtils.swift */; };
BEDA91A028EDDE64007441D9 /* FakeAnalyticsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEDA919F28EDDE64007441D9 /* FakeAnalyticsService.swift */; };
BEDB820229B109EE00075AF3 /* BTApplePayAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEDB820129B109EE00075AF3 /* BTApplePayAnalytics.swift */; };
Expand Down Expand Up @@ -677,6 +677,7 @@
035A59D91EA5DE97002960C8 /* BTLocalPaymentClient_UnitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTLocalPaymentClient_UnitTests.swift; sourceTree = "<group>"; };
039A8BD91F9E993500D607E7 /* BTAmericanExpressRewardsBalance_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTAmericanExpressRewardsBalance_Tests.swift; sourceTree = "<group>"; };
03F921C1200EBB200076CD80 /* BTThreeDSecurePostalAddress_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTThreeDSecurePostalAddress_Tests.swift; sourceTree = "<group>"; };
04ECD89F2CC9CB1A000329EC /* LinkType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkType.swift; sourceTree = "<group>"; };
09357DCA2A2FBEC10096D449 /* BTVenmoLineItem_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem_Tests.swift; sourceTree = "<group>"; };
096C6B2529CCDCEB00912863 /* BTVenmoLineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTVenmoLineItem.swift; sourceTree = "<group>"; };
162174E1192D9220008DC35D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -996,7 +997,6 @@
BED00CAD28A5419900D74AEC /* BTBinData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTBinData.swift; sourceTree = "<group>"; };
BED00CAF28A579D700D74AEC /* BTClientToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTClientToken.swift; sourceTree = "<group>"; };
BED00CB128A57AD400D74AEC /* BTClientTokenError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTClientTokenError.swift; sourceTree = "<group>"; };
BED3A2C52C5D74AC0034D9A6 /* LinkType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkType.swift; sourceTree = "<group>"; };
BED7493528579BAC0074C818 /* BTURLUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTURLUtils.swift; sourceTree = "<group>"; };
BEDA919F28EDDE64007441D9 /* FakeAnalyticsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeAnalyticsService.swift; sourceTree = "<group>"; };
BEDB820129B109EE00075AF3 /* BTApplePayAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTApplePayAnalytics.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1554,13 +1554,13 @@
80F4F4D529F8A628003EACB1 /* Analytics */ = {
isa = PBXGroup;
children = (
04ECD89F2CC9CB1A000329EC /* LinkType.swift */,
808E4A152C581CD40006A737 /* AnalyticsSendable.swift */,
BE549F132BF6576300B6F441 /* BTAnalyticsEventsStorage.swift */,
BEE2E4E329007FF100C03FDD /* BTAnalyticsService.swift */,
BEE2E4E5290080BD00C03FDD /* BTAnalyticsServiceError.swift */,
BEF388C02BE52CD2000965C8 /* BTCoreAnalytics.swift */,
800E78C329E0DD5300D1B0FC /* FPTIBatchData.swift */,
BED3A2C52C5D74AC0034D9A6 /* LinkType.swift */,
457D7FC72C29CEC300EF6523 /* RepeatingTimer.swift */,
);
path = Analytics;
Expand Down Expand Up @@ -3123,6 +3123,7 @@
files = (
BE9FB82D28984ADE00D6FE2F /* BTPaymentMethodNonceParser.swift in Sources */,
BED00CAE28A5419900D74AEC /* BTBinData.swift in Sources */,
04ECD8A02CC9CB1E000329EC /* LinkType.swift in Sources */,
BE549F142BF6576300B6F441 /* BTAnalyticsEventsStorage.swift in Sources */,
BC17F9BE28D25054004B18CC /* BTGraphQLErrorNode.swift in Sources */,
800E78C429E0DD5300D1B0FC /* FPTIBatchData.swift in Sources */,
Expand Down Expand Up @@ -3159,7 +3160,6 @@
BE63A3A7288F3026001936DA /* BTPostalAddress.swift in Sources */,
BE2F98D028A2BCCD008EF189 /* BTConfiguration.swift in Sources */,
804DC45D2B2D08FF00F17A15 /* BTConfigurationRequest.swift in Sources */,
BED3A2C62C5D74B20034D9A6 /* LinkType.swift in Sources */,
BED00CB228A57AD400D74AEC /* BTClientTokenError.swift in Sources */,
BE24C67328E73E810067B11A /* BTAPIClientHTTPType.swift in Sources */,
457D7FC82C29CEC300EF6523 /* RepeatingTimer.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Remove entire PayPal Native Checkout module
* BraintreeVenmo
* Update `BTVenmoRequest` to make all properties accessible on the initializer only vs via the dot syntax.
* Remove `fallbacktoWeb` property from `BTVenmoRequest`. All Venmo flows will now use universal links to switch to the Venmo app or fallback to the web flow if the Venmo app is not installed
* BraintreeSEPADirectDebit
* Update `BTSEPADirectDebitRequest` to make all properties accessible on the initializer only vs via the dot syntax.
* BraintreeLocalPayment
Expand Down
7 changes: 2 additions & 5 deletions Demo/Application/Features/VenmoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class VenmoViewController: PaymentButtonBaseViewController {
// swiftlint:disable:next implicitly_unwrapped_optional
var venmoClient: BTVenmoClient!

let webFallbackToggle = Toggle(title: "Enable Web Fallback")
let vaultToggle = Toggle(title: "Vault")

override func viewDidLoad() {
Expand All @@ -18,7 +17,7 @@ class VenmoViewController: PaymentButtonBaseViewController {
override func createPaymentButton() -> UIView {
let venmoButton = createButton(title: "Venmo", action: #selector(tappedVenmo))

let stackView = UIStackView(arrangedSubviews: [webFallbackToggle, vaultToggle, venmoButton])
let stackView = UIStackView(arrangedSubviews: [vaultToggle, venmoButton])
stackView.axis = .vertical
stackView.spacing = 15
stackView.alignment = .fill
Expand All @@ -31,12 +30,10 @@ class VenmoViewController: PaymentButtonBaseViewController {
@objc func tappedVenmo() {
self.progressBlock("Tapped Venmo - initiating Venmo auth")

let isWebFallbackEnabled = webFallbackToggle.isOn
let isVaultingEnabled = vaultToggle.isOn
let venmoRequest = BTVenmoRequest(
paymentMethodUsage: .multiUse,
vault: isVaultingEnabled,
fallbackToWeb: isWebFallbackEnabled
vault: isVaultingEnabled
)

Task {
Expand Down
44 changes: 1 addition & 43 deletions Demo/UI Tests/Venmo UI Tests/Venmo_UITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,18 @@ class Venmo_UITests: XCTestCase {

// swiftlint:disable implicitly_unwrapped_optional
var demoApp: XCUIApplication!
var mockVenmo: XCUIApplication!
// swiftlint:enable implicitly_unwrapped_optional

override func setUp() {
super.setUp()
continueAfterFailure = false

mockVenmo = XCUIApplication(bundleIdentifier: "com.braintreepayments.MockVenmo")
mockVenmo.activate()

demoApp = XCUIApplication(bundleIdentifier: "com.braintreepayments.Demo")
demoApp.launchArguments.append("-EnvironmentSandbox")
demoApp.launchArguments.append("-ClientToken")
demoApp.launchArguments.append("-Integration:VenmoViewController")
demoApp.launch()
}

func testTokenizeVenmo_whenSignInSuccessfulWithPaymentContext_returnsNonce() {
waitForElementToBeHittable(demoApp.buttons["Venmo"])
demoApp.buttons["Venmo"].tap()

waitForElementToBeHittable(mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"])
mockVenmo.buttons["SUCCESS WITH PAYMENT CONTEXT"].tap()

XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 30))
}

func testTokenizeVenmo_whenSignInSuccessfulWithoutPaymentContext_returnsNonce() {
waitForElementToBeHittable(demoApp.buttons["Venmo"])
demoApp.buttons["Venmo"].tap()

waitForElementToBeHittable(mockVenmo.buttons["SUCCESS WITHOUT PAYMENT CONTEXT"])
mockVenmo.buttons["SUCCESS WITHOUT PAYMENT CONTEXT"].tap()

XCTAssertTrue(demoApp.buttons["Got a nonce. Tap to make a transaction."].waitForExistence(timeout: 30))
}

func testTokenizeVenmo_whenErrorOccurs_returnsError() {
waitForElementToBeHittable(demoApp.buttons["Venmo"])
demoApp.buttons["Venmo"].tap()

waitForElementToBeHittable(mockVenmo.buttons["ERROR"])
mockVenmo.buttons["ERROR"].tap()

XCTAssertTrue(demoApp.buttons["An error occurred during the Venmo flow"].waitForExistence(timeout: 30))
}

func testTokenizeVenmo_whenUserCancels_returnsCancel() {
waitForElementToBeHittable(demoApp.buttons["Venmo"])
demoApp.buttons["Venmo"].tap()

waitForElementToBeHittable(mockVenmo.buttons["Cancel"])
mockVenmo.buttons["Cancel"].tap()

XCTAssertTrue(demoApp.buttons["Canceled 🔰"].waitForExistence(timeout: 30))
}
// TODO: Add UI test
}
2 changes: 1 addition & 1 deletion Sources/BraintreeCore/Analytics/LinkType.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// Used to describe the link type for analytics
/// Used to describe the type of link that directs users to a specific URL for analytics
/// :nodoc: This class is exposed for internal Braintree use only. Do not use. It is not covered by Semantic Versioning and may change or be removed at any time.
@_documentation(visibility: private)
public enum LinkType: String {
Expand Down
2 changes: 1 addition & 1 deletion Sources/BraintreePayPal/BTPayPalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import BraintreeDataCollector
/// Used for analytics purposes, to determine if brower-presentation event is associated with a locally cached, or remotely fetched `BTConfiguration`
private var isConfigFromCache: Bool?

/// Used for sending the type of flow, universal vs deeplink to FPTI
/// Used for indicating the type of URL link, universal link or deep link, that directs users to a specific URL to FPTI
private var linkType: LinkType?

// MARK: - Initializer
Expand Down
7 changes: 0 additions & 7 deletions Sources/BraintreeVenmo/BTVenmoAppSwitchRedirectURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,6 @@ struct BTVenmoAppSwitchRedirectURL {
return urlComponent.url
}

func urlSchemeURL() -> URL? {
var components = BTVenmoAppSwitchRedirectURL.appSwitchBaseURLComponents()
components.percentEncodedQuery = BTURLUtils.queryString(from: queryParameters as NSDictionary)

return components.url
}

// MARK: - Private Helper Methods

private func constructRedirectURL(with scheme: String, result: String) -> URL? {
Expand Down
51 changes: 11 additions & 40 deletions Sources/BraintreeVenmo/BTVenmoClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ import BraintreeCore
@objc(tokenizeWithVenmoRequest:completion:)
// swiftlint:disable:next function_body_length cyclomatic_complexity
public func tokenize(_ request: BTVenmoRequest, completion: @escaping (BTVenmoAccountNonce?, Error?) -> Void) {
linkType = request.fallbackToWeb ? .universal : .deeplink
apiClient.sendAnalyticsEvent(BTVenmoAnalytics.tokenizeStarted, isVaultRequest: shouldVault, linkType: linkType)
apiClient.sendAnalyticsEvent(BTVenmoAnalytics.tokenizeStarted, isVaultRequest: shouldVault)
let returnURLScheme = BTAppContextSwitcher.sharedInstance.returnURLScheme

if returnURLScheme.isEmpty {
Expand Down Expand Up @@ -100,7 +99,7 @@ import BraintreeCore
}

do {
_ = try self.verifyAppSwitch(with: configuration, fallbackToWeb: request.fallbackToWeb)
_ = try self.verifyAppSwitch(with: configuration)
} catch {
self.notifyFailure(with: error, completion: completion)
return
Expand Down Expand Up @@ -160,24 +159,15 @@ import BraintreeCore
environment: configuration.venmoEnvironment
)

if request.fallbackToWeb {
guard let universalLinksURL = appSwitchURL.universalLinksURL() else {
self.notifyFailure(
with: BTVenmoError.invalidReturnURL("Universal links URL cannot be nil"),
completion: completion
)
return
}

self.startVenmoFlow(with: universalLinksURL, shouldVault: request.vault, completion: completion)
} else {
guard let urlSchemeURL = appSwitchURL.urlSchemeURL() else {
self.notifyFailure(with: BTVenmoError.invalidReturnURL("App switch URL cannot be nil"), completion: completion)
return
}

self.startVenmoFlow(with: urlSchemeURL, shouldVault: request.vault, completion: completion)
guard let universalLinksURL = appSwitchURL.universalLinksURL() else {
self.notifyFailure(
with: BTVenmoError.invalidReturnURL("Universal links URL cannot be nil"),
completion: completion
)
return
}

self.startVenmoFlow(with: universalLinksURL, shouldVault: request.vault, completion: completion)
} catch {
self.notifyFailure(with: error, completion: completion)
return
Expand All @@ -202,15 +192,6 @@ import BraintreeCore
}
}

/// Returns true if the proper Venmo app is installed and configured correctly, returns false otherwise.
@objc public func isVenmoAppInstalled() -> Bool {
guard let appSwitchURL = BTVenmoAppSwitchRedirectURL.baseAppSwitchURL else {
return false
}

return application.canOpenURL(appSwitchURL)
}

/// Switches to the App Store to download the Venmo application.
@objc public func openVenmoAppPageInAppStore() {
application.open(appStoreURL, completionHandler: nil)
Expand Down Expand Up @@ -291,7 +272,6 @@ import BraintreeCore
apiClient.sendAnalyticsEvent(
BTVenmoAnalytics.handleReturnStarted,
isVaultRequest: shouldVault,
linkType: linkType,
payPalContextID: payPalContextID
)
guard let cleanedURL = URL(string: url.absoluteString.replacingOccurrences(of: "#", with: "?")) else {
Expand Down Expand Up @@ -394,7 +374,6 @@ import BraintreeCore
apiClient.sendAnalyticsEvent(
BTVenmoAnalytics.appSwitchSucceeded,
isVaultRequest: shouldVault,
linkType: linkType,
payPalContextID: payPalContextID,
appSwitchURL: appSwitchURL
)
Expand Down Expand Up @@ -443,16 +422,11 @@ import BraintreeCore

// MARK: - App Switch Methods

func verifyAppSwitch(with configuration: BTConfiguration, fallbackToWeb: Bool) throws -> Bool {
func verifyAppSwitch(with configuration: BTConfiguration) throws -> Bool {
if !configuration.isVenmoEnabled {
throw BTVenmoError.disabled
}


if !fallbackToWeb && !isVenmoAppInstalled() {
throw BTVenmoError.appNotAvailable
}

guard bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") != nil else {
throw BTVenmoError.bundleDisplayNameMissing
}
Expand All @@ -469,7 +443,6 @@ import BraintreeCore
apiClient.sendAnalyticsEvent(
BTVenmoAnalytics.tokenizeSucceeded,
isVaultRequest: shouldVault,
linkType: linkType,
payPalContextID: payPalContextID
)
completion(result, nil)
Expand All @@ -480,7 +453,6 @@ import BraintreeCore
BTVenmoAnalytics.tokenizeFailed,
errorDescription: error.localizedDescription,
isVaultRequest: shouldVault,
linkType: linkType,
payPalContextID: payPalContextID
)
completion(nil, error)
Expand All @@ -490,7 +462,6 @@ import BraintreeCore
apiClient.sendAnalyticsEvent(
BTVenmoAnalytics.appSwitchCanceled,
isVaultRequest: shouldVault,
linkType: linkType,
payPalContextID: payPalContextID
)
completion(nil, BTVenmoError.canceled)
Expand Down
8 changes: 2 additions & 6 deletions Sources/BraintreeVenmo/BTVenmoRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import Foundation
var shippingAmount: String?
var totalAmount: String?
var lineItems: [BTVenmoLineItem]?
var fallbackToWeb: Bool = false

// MARK: - Initializer

Expand All @@ -57,9 +56,8 @@ import Foundation
/// - shippingAmount: The shipping amount for the transaction to be displayed on the paysheet. If this value is set, `totalAmount` must also be set.
/// - totalAmount: The grand total amount on the transaction that should be displayed on the paysheet.
/// - lineItems: The line items for this transaction. It can include up to 249 line items. If this value is set, `totalAmount` must also be set.
/// - fallbackToWeb: Used to determine if the customer should fallback to the web flow if Venmo app is not installed. Defaults to `false`
@objc(initWithPaymentMethodUsage:profileID:vault:displayName:collectCustomerBillingAddress:collectCustomerShippingAddress:
isFinalAmount:subTotalAmount:discountAmount:taxAmount:shippingAmount:totalAmount:lineItems:fallbackToWeb:)
isFinalAmount:subTotalAmount:discountAmount:taxAmount:shippingAmount:totalAmount:lineItems:)
public init(
paymentMethodUsage: BTVenmoPaymentMethodUsage,
profileID: String? = nil,
Expand All @@ -73,8 +71,7 @@ import Foundation
taxAmount: String? = nil,
shippingAmount: String? = nil,
totalAmount: String? = nil,
lineItems: [BTVenmoLineItem]? = [],
fallbackToWeb: Bool = false
lineItems: [BTVenmoLineItem]? = []
) {
self.paymentMethodUsage = paymentMethodUsage
self.profileID = profileID
Expand All @@ -89,6 +86,5 @@ import Foundation
self.shippingAmount = shippingAmount
self.totalAmount = totalAmount
self.lineItems = lineItems
self.fallbackToWeb = fallbackToWeb
}
}
Loading

0 comments on commit 3867268

Please sign in to comment.