Skip to content

Commit 76a323b

Browse files
authored
Merge pull request #5868 from woocommerce/try/5853-dual-gateways
[Mobile Payments] Consolidate CardPresent and PaymentGateway Stores; Switch Between WCPay and Stripe Backends Within
2 parents 4686863 + fc01327 commit 76a323b

File tree

17 files changed

+566
-474
lines changed

17 files changed

+566
-474
lines changed

Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,6 @@ extension StripeCardReaderService: CardReaderService {
306306
promise(.failure(CardReaderServiceError.connection()))
307307
return
308308
}
309-
310309
// Clear cached readers, as per Stripe's documentation.
311310
self.discoveredStripeReadersCache.clear()
312311

Networking/Networking/Remote/StripeRemote.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ private extension StripeRemote {
9898
enum Path {
9999
static let connectionTokens = "wc_stripe/connection_tokens"
100100
static let accounts = "wc_stripe/account/summary"
101-
static let locations = "payments/terminal/locations/store"
101+
static let locations = "wc_stripe/terminal/locations/store"
102102
static let orders = "payments/orders"
103103
static let captureTerminalPayment = "capture_terminal_payment"
104104
static let createCustomer = "create_customer"

Networking/NetworkingTests/Remote/StripeRemoteTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ final class StripeRemoteTests: XCTestCase {
594594
let expectedLocationID = "tml_0123456789abcd"
595595

596596
network.simulateResponse(
597-
requestUrlSuffix: "payments/terminal/locations/store",
597+
requestUrlSuffix: "wc_stripe/terminal/locations/store",
598598
filename: "stripe-location"
599599
)
600600

@@ -613,7 +613,7 @@ final class StripeRemoteTests: XCTestCase {
613613
let remote = StripeRemote(network: network)
614614

615615
network.simulateResponse(
616-
requestUrlSuffix: "payments/terminal/locations/store",
616+
requestUrlSuffix: "wc_stripe/terminal/locations/store",
617617
filename: "stripe-location-error"
618618
)
619619

WooCommerce/Classes/ViewModels/CardPresentPayments/PaymentCaptureOrchestrator.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class PaymentCaptureOrchestrator {
3131
/// First ask the backend to create/assign a Stripe customer for the order
3232
///
3333
var customerID: String?
34-
let customerAction = PaymentGatewayAccountAction.fetchOrderCustomer(siteID: order.siteID, orderID: order.orderID) { [self] result in
34+
let customerAction = CardPresentPaymentAction.fetchOrderCustomer(siteID: order.siteID, orderID: order.orderID) { [self] result in
3535
switch result {
3636
case .success(let customer):
3737
customerID = customer.id
@@ -176,7 +176,7 @@ private extension PaymentCaptureOrchestrator {
176176
order: Order,
177177
paymentIntent: PaymentIntent,
178178
onCompletion: @escaping (Result<CardPresentReceiptParameters, Error>) -> Void) {
179-
let action = PaymentGatewayAccountAction.captureOrderPayment(siteID: siteID,
179+
let action = CardPresentPaymentAction.captureOrderPayment(siteID: siteID,
180180
orderID: order.orderID,
181181
paymentIntentID: paymentIntent.id) { [weak self] result in
182182
guard let self = self else {

WooCommerce/Classes/ViewModels/Order Details/OrderDetailsViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ extension OrderDetailsViewModel {
458458
/// No need for a completion here. The VC will be notified of changes to the stored paymentGatewayAccounts
459459
/// by the viewModel (after passing up through the dataSource and originating in the resultsControllers)
460460
///
461-
let action = PaymentGatewayAccountAction.loadAccounts(siteID: order.siteID) {_ in}
461+
let action = CardPresentPaymentAction.loadAccounts(siteID: order.siteID) {_ in}
462462
ServiceLocator.stores.dispatch(action)
463463
}
464464

WooCommerce/Classes/ViewRelated/Dashboard/Settings/In-Person Payments/CardPresentPaymentsOnboardingUseCase.swift

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,49 @@ final class CardPresentPaymentsOnboardingUseCase: CardPresentPaymentsOnboardingU
6060
if state != .completed {
6161
state = .loading
6262
}
63-
synchronizeRequiredData { [weak self] in
63+
synchronizeStoreCountryAndPlugins { [weak self] in
64+
self?.updateAccounts()
65+
}
66+
}
67+
68+
/// We need to sync payment gateway accounts to see if the payment gateway is set up correctly.
69+
/// But first we also need to prompt the CardPresentPaymentStore to use the right backend based on the active plugin.
70+
///
71+
func updateAccounts() {
72+
guard let siteID = siteID else {
73+
return
74+
}
75+
76+
let wcPayPlugin = getWCPayPlugin()
77+
let stripePlugin = getStripePlugin()
78+
79+
/// If both plugins are active, don't bother initializing the backend nor fetching
80+
/// accounts. Fall through to updateState so the end user can fix the problem.
81+
guard !bothPluginsInstalledAndActive(wcPay: wcPayPlugin, stripe: stripePlugin) else {
82+
self.updateState()
83+
return
84+
}
85+
86+
if wcPayPlugin?.active ?? false {
87+
let useWCPayAction = CardPresentPaymentAction.useWCPay // TODO asynchronicity / ordering of actions?
88+
stores.dispatch(useWCPayAction)
89+
} else {
90+
// If the WCPayPlugin is not active and the Stripe IPP experiment is not enabled bail now.
91+
guard stripeGatewayIPPEnabled == true else {
92+
self.updateState()
93+
return
94+
}
95+
}
96+
97+
if stripePlugin?.active ?? false {
98+
let useStripeAction = CardPresentPaymentAction.useStripe // TODO asynchronicity / ordering of actions?
99+
stores.dispatch(useStripeAction)
100+
}
101+
102+
let paymentGatewayAccountsAction = CardPresentPaymentAction.loadAccounts(siteID: siteID) { [weak self] result in
64103
self?.updateState()
65104
}
105+
stores.dispatch(paymentGatewayAccountsAction)
66106
}
67107

68108
func updateState() {
@@ -73,7 +113,7 @@ final class CardPresentPaymentsOnboardingUseCase: CardPresentPaymentsOnboardingU
73113
// MARK: - Internal state
74114
//
75115
private extension CardPresentPaymentsOnboardingUseCase {
76-
func synchronizeRequiredData(completion: () -> Void) {
116+
func synchronizeStoreCountryAndPlugins(completion: () -> Void) {
77117
guard let siteID = siteID else {
78118
completion()
79119
return
@@ -93,7 +133,7 @@ private extension CardPresentPaymentsOnboardingUseCase {
93133
group.enter()
94134
stores.dispatch(settingsAction)
95135

96-
// We need to sync plugins to check if WCPay is installed, up to date, and active
136+
// We need to sync plugins to see which CPP-supporting plugins are installed, up to date, and active
97137
let systemPluginsAction = SystemStatusAction.synchronizeSystemPlugins(siteID: siteID) { result in
98138
if case let .failure(error) = result {
99139
DDLogError("[CardPresentPaymentsOnboarding] Error syncing system plugins: \(error)")
@@ -104,24 +144,13 @@ private extension CardPresentPaymentsOnboardingUseCase {
104144
group.enter()
105145
stores.dispatch(systemPluginsAction)
106146

107-
// We need to sync payment gateway accounts to see if WCPay is set up correctly
108-
let paymentGatewayAccountsAction = PaymentGatewayAccountAction.loadAccounts(siteID: siteID) { result in
109-
if case let .failure(error) = result {
110-
DDLogError("[CardPresentPaymentsOnboarding] Error syncing payment gateway accounts: \(error)")
111-
errors.append(error)
112-
}
113-
group.leave()
114-
}
115-
group.enter()
116-
stores.dispatch(paymentGatewayAccountsAction)
117-
118147
group.notify(queue: .main, execute: { [weak self] in
119148
guard let self = self else { return }
120149
if errors.isNotEmpty,
121150
errors.contains(where: self.isNetworkError(_:)) {
122151
self.state = .noConnectionError
123152
} else {
124-
self.updateState()
153+
self.updateAccounts()
125154
}
126155
})
127156
}
@@ -141,6 +170,7 @@ private extension CardPresentPaymentsOnboardingUseCase {
141170
guard stripeGatewayIPPEnabled == true else {
142171
return wcPayOnlyOnboardingState(plugin: wcPay)
143172
}
173+
144174
let stripe = getStripePlugin()
145175

146176
// If both the Stripe plugin and WCPay are installed and activated, the user needs
@@ -271,7 +301,8 @@ private extension CardPresentPaymentsOnboardingUseCase {
271301
VersionHelpers.isVersionSupported(version: plugin.version, minimumRequired: Constants.Stripe.minimumSupportedPluginVersion)
272302
}
273303

274-
// Note: This counts on synchronizeRequiredData having been called to get the appropriate account for the site, be that Stripe or WCPay
304+
// Note: This counts on synchronizeStoreCountryAndPlugins having been called to get
305+
// the appropriate account for the site, be that Stripe or WCPay
275306
func getPaymentGatewayAccount() -> PaymentGatewayAccount? {
276307
guard let siteID = siteID else {
277308
return nil

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ private extension SettingsViewModel {
284284
.compactMap { $0 }
285285
}
286286

287-
/// Ask the PaymentGatewayAccountStore to loadAccounts from the network and update storage
287+
/// Ask the CardPresentPaymentStore to loadAccounts from the network and update storage
288288
///
289289
func loadPaymentGatewayAccounts() {
290290
guard let siteID = stores.sessionManager.defaultSite?.siteID else {
@@ -293,7 +293,7 @@ private extension SettingsViewModel {
293293

294294
/// No need for a completion here. We will be notified of storage changes in `onDidChangeContent`
295295
///
296-
let action = PaymentGatewayAccountAction.loadAccounts(siteID: siteID) {_ in}
296+
let action = CardPresentPaymentAction.loadAccounts(siteID: siteID) {_ in}
297297
stores.dispatch(action)
298298
}
299299

WooCommerce/Classes/Yosemite/AuthenticatedState.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class AuthenticatedState: StoresManagerState {
2626
let storageManager = ServiceLocator.storageManager
2727
let network = AlamofireNetwork(credentials: credentials)
2828

29+
/// TODO - remove this feature flag related logic when no longer needed
30+
let allowStripeIPP = ServiceLocator.featureFlagService.isFeatureFlagEnabled(.stripeExtensionInPersonPayments)
31+
2932
services = [
3033
AccountStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
3134
AppSettingsStore(dispatcher: dispatcher, storageManager: storageManager, fileStorage: PListFileStorage()),
@@ -41,7 +44,6 @@ class AuthenticatedState: StoresManagerState {
4144
OrderStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
4245
OrderStatusStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
4346
PaymentGatewayStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
44-
PaymentGatewayAccountStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
4547
ProductAttributeStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
4648
ProductAttributeTermStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
4749
ProductReviewStore(dispatcher: dispatcher, storageManager: storageManager, network: network),
@@ -64,7 +66,8 @@ class AuthenticatedState: StoresManagerState {
6466
CardPresentPaymentStore(dispatcher: dispatcher,
6567
storageManager: storageManager,
6668
network: network,
67-
cardReaderService: ServiceLocator.cardReaderService),
69+
cardReaderService: ServiceLocator.cardReaderService,
70+
allowStripeIPP: allowStripeIPP),
6871
ReceiptStore(dispatcher: dispatcher,
6972
storageManager: storageManager,
7073
network: network,

0 commit comments

Comments
 (0)