Skip to content

Commit eee66d1

Browse files
committed
Add Link warmup pane for deferred intents
1 parent 165dcf0 commit eee66d1

File tree

5 files changed

+76
-18
lines changed

5 files changed

+76
-18
lines changed

StripeFinancialConnections/StripeFinancialConnections/Source/Native/Consent/ConsentDataSource.swift

+51-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ protocol ConsentDataSource: AnyObject {
1414
var merchantLogo: [String]? { get }
1515
var analyticsClient: FinancialConnectionsAnalyticsClient { get }
1616

17-
func markConsentAcquired() -> Promise<FinancialConnectionsSessionManifest>
17+
func markConsentAcquired() -> Future<ConsentAcquiredResult>
18+
}
19+
20+
struct ConsentAcquiredResult {
21+
var manifest: FinancialConnectionsSessionManifest
22+
var customNextPane: FinancialConnectionsSessionManifest.NextPane?
1823
}
1924

2025
final class ConsentDataSourceImplementation: ConsentDataSource {
@@ -25,24 +30,66 @@ final class ConsentDataSourceImplementation: ConsentDataSource {
2530
private let apiClient: FinancialConnectionsAPIClient
2631
private let clientSecret: String
2732
let analyticsClient: FinancialConnectionsAnalyticsClient
33+
private let elementsSessionContext: ElementsSessionContext?
34+
35+
private var isLinkWithStripe: Bool {
36+
manifest.isLinkWithStripe ?? false
37+
}
2838

2939
init(
3040
manifest: FinancialConnectionsSessionManifest,
3141
consent: FinancialConnectionsConsent,
3242
merchantLogo: [String]?,
3343
apiClient: FinancialConnectionsAPIClient,
3444
clientSecret: String,
35-
analyticsClient: FinancialConnectionsAnalyticsClient
45+
analyticsClient: FinancialConnectionsAnalyticsClient,
46+
elementsSessionContext: ElementsSessionContext?
3647
) {
3748
self.manifest = manifest
3849
self.consent = consent
3950
self.merchantLogo = merchantLogo
4051
self.apiClient = apiClient
4152
self.clientSecret = clientSecret
4253
self.analyticsClient = analyticsClient
54+
self.elementsSessionContext = elementsSessionContext
4355
}
4456

45-
func markConsentAcquired() -> Promise<FinancialConnectionsSessionManifest> {
46-
return apiClient.markConsentAcquired(clientSecret: clientSecret)
57+
func markConsentAcquired() -> Future<ConsentAcquiredResult> {
58+
return apiClient.markConsentAcquired(clientSecret: clientSecret).chained { [weak self] manifest in
59+
let promise = Promise<ConsentAcquiredResult>()
60+
61+
guard let self, self.isLinkWithStripe, self.manifest.accountholderCustomerEmailAddress == nil else {
62+
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: nil)
63+
return Promise(value: result)
64+
}
65+
66+
guard let email = elementsSessionContext?.prefillDetails?.email else {
67+
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: nil)
68+
return Promise(value: result)
69+
}
70+
71+
apiClient.consumerSessionLookup(
72+
emailAddress: email,
73+
clientSecret: clientSecret
74+
).observe { lookupResult in
75+
let customNextPane = lookupResult.hasConsumer ? FinancialConnectionsSessionManifest.NextPane.networkingLinkLoginWarmup : nil
76+
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: customNextPane)
77+
promise.resolve(with: result)
78+
}
79+
80+
return promise
81+
}
82+
}
83+
}
84+
85+
private extension Swift.Result<LookupConsumerSessionResponse, any Error> {
86+
87+
var hasConsumer: Bool {
88+
switch self {
89+
case .success(let lookup):
90+
return lookup.exists
91+
case .failure:
92+
return false
93+
}
4794
}
4895
}

StripeFinancialConnections/StripeFinancialConnections/Source/Native/Consent/ConsentViewController.swift

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ protocol ConsentViewControllerDelegate: AnyObject {
1919
)
2020
func consentViewController(
2121
_ viewController: ConsentViewController,
22-
didConsentWithManifest manifest: FinancialConnectionsSessionManifest
22+
didConsentWithManifest manifest: FinancialConnectionsSessionManifest,
23+
customNextPane: FinancialConnectionsSessionManifest.NextPane?
2324
)
2425
}
2526

@@ -146,8 +147,8 @@ class ConsentViewController: UIViewController {
146147
.observe(on: .main) { [weak self] result in
147148
guard let self = self else { return }
148149
switch result {
149-
case .success(let manifest):
150-
self.delegate?.consentViewController(self, didConsentWithManifest: manifest)
150+
case .success(let result):
151+
self.delegate?.consentViewController(self, didConsentWithManifest: result.manifest, customNextPane: result.customNextPane)
151152
case .failure(let error):
152153
// we display no errors on failure
153154
self.dataSource

StripeFinancialConnections/StripeFinancialConnections/Source/Native/NativeFlowController.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,8 @@ extension NativeFlowController: ConsentViewControllerDelegate {
674674

675675
func consentViewController(
676676
_ viewController: ConsentViewController,
677-
didConsentWithManifest manifest: FinancialConnectionsSessionManifest
677+
didConsentWithManifest manifest: FinancialConnectionsSessionManifest,
678+
customNextPane: FinancialConnectionsSessionManifest.NextPane?
678679
) {
679680
delegate?.nativeFlowController(
680681
self,
@@ -683,7 +684,7 @@ extension NativeFlowController: ConsentViewControllerDelegate {
683684

684685
dataManager.manifest = manifest
685686

686-
let nextPane = manifest.nextPane
687+
let nextPane = customNextPane ?? manifest.nextPane
687688
if nextPane == .networkingLinkLoginWarmup {
688689
presentPaneAsSheet(nextPane)
689690
} else {
@@ -1339,7 +1340,8 @@ private func CreatePaneViewController(
13391340
merchantLogo: dataManager.merchantLogo,
13401341
apiClient: dataManager.apiClient,
13411342
clientSecret: dataManager.clientSecret,
1342-
analyticsClient: dataManager.analyticsClient
1343+
analyticsClient: dataManager.analyticsClient,
1344+
elementsSessionContext: dataManager.elementsSessionContext
13431345
)
13441346
let consentViewController = ConsentViewController(dataSource: consentDataSource)
13451347
consentViewController.delegate = nativeFlowController
@@ -1426,9 +1428,10 @@ private func CreatePaneViewController(
14261428
case .networkingLinkVerification:
14271429
let accountholderCustomerEmailAddress = dataManager.manifest.accountholderCustomerEmailAddress
14281430
let consumerSessionEmailAddress = dataManager.consumerSession?.emailAddress
1429-
if let accountholderCustomerEmailAddress = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress {
1431+
let prefillEmailAddress = dataManager.elementsSessionContext?.prefillDetails?.email
1432+
if let email = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress ?? prefillEmailAddress {
14301433
let networkingLinkVerificationDataSource = NetworkingLinkVerificationDataSourceImplementation(
1431-
accountholderCustomerEmailAddress: accountholderCustomerEmailAddress,
1434+
accountholderCustomerEmailAddress: email,
14321435
manifest: dataManager.manifest,
14331436
apiClient: dataManager.apiClient,
14341437
clientSecret: dataManager.clientSecret,
@@ -1552,7 +1555,8 @@ private func CreatePaneViewController(
15521555
apiClient: dataManager.apiClient,
15531556
clientSecret: dataManager.clientSecret,
15541557
analyticsClient: dataManager.analyticsClient,
1555-
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta
1558+
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta,
1559+
elementsSessionContext: dataManager.elementsSessionContext
15561560
)
15571561
let networkingLinkWarmupViewController = NetworkingLinkLoginWarmupViewController(
15581562
dataSource: networkingLinkWarmupDataSource,

StripeFinancialConnections/StripeFinancialConnections/Source/Native/NetworkingLinkLoginWarmup/NetworkingLinkLoginWarmupDataSource.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Foundation
1111
protocol NetworkingLinkLoginWarmupDataSource: AnyObject {
1212
var manifest: FinancialConnectionsSessionManifest { get }
1313
var analyticsClient: FinancialConnectionsAnalyticsClient { get }
14+
var email: String? { get }
1415

1516
func disableNetworking() -> Future<FinancialConnectionsSessionManifest>
1617
}
@@ -22,19 +23,26 @@ final class NetworkingLinkLoginWarmupDataSourceImplementation: NetworkingLinkLog
2223
private let clientSecret: String
2324
let analyticsClient: FinancialConnectionsAnalyticsClient
2425
private let nextPaneOrDrawerOnSecondaryCta: String?
26+
private let elementsSessionContext: ElementsSessionContext?
27+
28+
var email: String? {
29+
manifest.accountholderCustomerEmailAddress ?? elementsSessionContext?.prefillDetails?.email
30+
}
2531

2632
init(
2733
manifest: FinancialConnectionsSessionManifest,
2834
apiClient: FinancialConnectionsAPIClient,
2935
clientSecret: String,
3036
analyticsClient: FinancialConnectionsAnalyticsClient,
31-
nextPaneOrDrawerOnSecondaryCta: String?
37+
nextPaneOrDrawerOnSecondaryCta: String?,
38+
elementsSessionContext: ElementsSessionContext?
3239
) {
3340
self.manifest = manifest
3441
self.apiClient = apiClient
3542
self.clientSecret = clientSecret
3643
self.analyticsClient = analyticsClient
3744
self.nextPaneOrDrawerOnSecondaryCta = nextPaneOrDrawerOnSecondaryCta
45+
self.elementsSessionContext = elementsSessionContext
3846
}
3947

4048
func disableNetworking() -> Future<FinancialConnectionsSessionManifest> {

StripeFinancialConnections/StripeFinancialConnections/Source/Native/NetworkingLinkLoginWarmup/NetworkingLinkLoginWarmupViewController.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,8 @@ final class NetworkingLinkLoginWarmupViewController: SheetViewController {
7070
"The subtitle/description of a screen where users are informed that they can sign-in-to Link."
7171
),
7272
contentView: NetworkingLinkLoginWarmupBodyView(
73-
// `accountholderCustomerEmailAddress` should always be non-null, and
74-
// since the email is only used as a visual, it's not worth to throw an error
75-
// if it is null
76-
email: dataSource.manifest.accountholderCustomerEmailAddress ?? "you"
73+
// `email` should always be non-null, and since the email is only used as a visual, it's not worth to throw an error if it is null
74+
email: dataSource.email ?? "you"
7775
)
7876
),
7977
footerView: PaneLayoutView.createFooterView(

0 commit comments

Comments
 (0)