Skip to content

Commit 45baf7b

Browse files
committed
Add Link warmup pane for deferred intents
1 parent 03acd09 commit 45baf7b

File tree

5 files changed

+71
-18
lines changed

5 files changed

+71
-18
lines changed

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

+46-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 nextPane: FinancialConnectionsSessionManifest.NextPane?
1823
}
1924

2025
final class ConsentDataSourceImplementation: ConsentDataSource {
@@ -25,24 +30,61 @@ final class ConsentDataSourceImplementation: ConsentDataSource {
2530
private let apiClient: any FinancialConnectionsAPI
2631
private let clientSecret: String
2732
let analyticsClient: FinancialConnectionsAnalyticsClient
33+
private let elementsSessionContext: ElementsSessionContext?
2834

2935
init(
3036
manifest: FinancialConnectionsSessionManifest,
3137
consent: FinancialConnectionsConsent,
3238
merchantLogo: [String]?,
3339
apiClient: any FinancialConnectionsAPI,
3440
clientSecret: String,
35-
analyticsClient: FinancialConnectionsAnalyticsClient
41+
analyticsClient: FinancialConnectionsAnalyticsClient,
42+
elementsSessionContext: ElementsSessionContext?
3643
) {
3744
self.manifest = manifest
3845
self.consent = consent
3946
self.merchantLogo = merchantLogo
4047
self.apiClient = apiClient
4148
self.clientSecret = clientSecret
4249
self.analyticsClient = analyticsClient
50+
self.elementsSessionContext = elementsSessionContext
51+
}
52+
53+
func markConsentAcquired() -> Future<ConsentAcquiredResult> {
54+
return apiClient.markConsentAcquired(clientSecret: clientSecret).chained { [weak self] manifest in
55+
guard let self, manifest.shouldLookupConsumerSession, let email = elementsSessionContext?.prefillDetails?.email else {
56+
let result = ConsentAcquiredResult(manifest: manifest, nextPane: nil)
57+
return Promise(value: result)
58+
}
59+
60+
let promise = Promise<ConsentAcquiredResult>()
61+
62+
apiClient.consumerSessionLookup(
63+
emailAddress: email,
64+
clientSecret: clientSecret,
65+
sessionId: manifest.id,
66+
emailSource: .userAction,
67+
useMobileEndpoints: manifest.verified,
68+
pane: .consent
69+
).observe { lookupResult in
70+
switch lookupResult {
71+
case .success(let response):
72+
let nextPane: FinancialConnectionsSessionManifest.NextPane? = response.exists ? .networkingLinkLoginWarmup : nil
73+
let result = ConsentAcquiredResult(manifest: manifest, nextPane: nextPane)
74+
promise.resolve(with: result)
75+
case .failure:
76+
let result = ConsentAcquiredResult(manifest: manifest, nextPane: nil)
77+
promise.resolve(with: result)
78+
}
79+
}
80+
81+
return promise
82+
}
4383
}
84+
}
4485

45-
func markConsentAcquired() -> Promise<FinancialConnectionsSessionManifest> {
46-
return apiClient.markConsentAcquired(clientSecret: clientSecret)
86+
private extension FinancialConnectionsSessionManifest {
87+
var shouldLookupConsumerSession: Bool {
88+
isLinkWithStripe == true && accountholderCustomerEmailAddress == nil
4789
}
4890
}

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.nextPane)
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
@@ -696,7 +696,8 @@ extension NativeFlowController: ConsentViewControllerDelegate {
696696

697697
func consentViewController(
698698
_ viewController: ConsentViewController,
699-
didConsentWithManifest manifest: FinancialConnectionsSessionManifest
699+
didConsentWithManifest manifest: FinancialConnectionsSessionManifest,
700+
customNextPane: FinancialConnectionsSessionManifest.NextPane?
700701
) {
701702
delegate?.nativeFlowController(
702703
self,
@@ -705,7 +706,7 @@ extension NativeFlowController: ConsentViewControllerDelegate {
705706

706707
dataManager.manifest = manifest
707708

708-
let nextPane = manifest.nextPane
709+
let nextPane = customNextPane ?? manifest.nextPane
709710
if nextPane == .networkingLinkLoginWarmup {
710711
presentPaneAsSheet(nextPane)
711712
} else {
@@ -1453,7 +1454,8 @@ private func CreatePaneViewController(
14531454
merchantLogo: dataManager.merchantLogo,
14541455
apiClient: dataManager.apiClient,
14551456
clientSecret: dataManager.clientSecret,
1456-
analyticsClient: dataManager.analyticsClient
1457+
analyticsClient: dataManager.analyticsClient,
1458+
elementsSessionContext: dataManager.elementsSessionContext
14571459
)
14581460
let consentViewController = ConsentViewController(dataSource: consentDataSource)
14591461
consentViewController.delegate = nativeFlowController
@@ -1540,9 +1542,10 @@ private func CreatePaneViewController(
15401542
case .networkingLinkVerification:
15411543
let accountholderCustomerEmailAddress = dataManager.manifest.accountholderCustomerEmailAddress
15421544
let consumerSessionEmailAddress = dataManager.consumerSession?.emailAddress
1543-
if let accountholderCustomerEmailAddress = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress {
1545+
let prefillEmailAddress = dataManager.elementsSessionContext?.prefillDetails?.email
1546+
if let email = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress ?? prefillEmailAddress {
15441547
let networkingLinkVerificationDataSource = NetworkingLinkVerificationDataSourceImplementation(
1545-
accountholderCustomerEmailAddress: accountholderCustomerEmailAddress,
1548+
accountholderCustomerEmailAddress: email,
15461549
manifest: dataManager.manifest,
15471550
apiClient: dataManager.apiClient,
15481551
clientSecret: dataManager.clientSecret,
@@ -1667,7 +1670,8 @@ private func CreatePaneViewController(
16671670
apiClient: dataManager.apiClient,
16681671
clientSecret: dataManager.clientSecret,
16691672
analyticsClient: dataManager.analyticsClient,
1670-
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta
1673+
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta,
1674+
elementsSessionContext: dataManager.elementsSessionContext
16711675
)
16721676
let networkingLinkWarmupViewController = NetworkingLinkLoginWarmupViewController(
16731677
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: any FinancialConnectionsAPI,
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)