Skip to content

Commit 009a740

Browse files
committed
8290 Use one ReaderConfigProvider for the app’s lifetime
Once the CardReaderConfigProvider is set on the Terminal, it can’t be changed. This means we need to keep the same one around for the lifetime of the app in order to change it when the user logs out and back in again. Failing to do this results in serious errors when using a second account to take IPP transactions.
1 parent 434bfdd commit 009a740

File tree

8 files changed

+134
-76
lines changed

8 files changed

+134
-76
lines changed

Hardware/Hardware/CardReader/StripeCardReader/StripeCardReaderService.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,11 +861,11 @@ private extension StripeCardReaderService {
861861

862862
private extension StripeCardReaderService {
863863
private func setConfigProvider(_ configProvider: CardReaderConfigProvider) {
864-
readerLocationProvider = configProvider
864+
if !Terminal.hasTokenProvider() {
865+
readerLocationProvider = configProvider
865866

866-
let tokenProvider = DefaultConnectionTokenProvider(provider: configProvider)
867+
let tokenProvider = DefaultConnectionTokenProvider(provider: configProvider)
867868

868-
if !Terminal.hasTokenProvider() {
869869
Terminal.setTokenProvider(tokenProvider)
870870
}
871871
}

WooCommerce/Classes/ServiceLocator/ServiceLocator.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ final class ServiceLocator {
7979
private static var _cardReader: CardReaderService = NoOpCardReaderService()
8080
#endif
8181

82+
private static var _cardReaderConfigProvider: CommonReaderConfigProviding = CommonReaderConfigProvider()
83+
8284
/// Support for printing receipts
8385
///
8486
private static var _receiptPrinter: PrinterService = AirPrintReceiptPrinterService()
@@ -207,6 +209,10 @@ final class ServiceLocator {
207209
_cardReader
208210
}
209211

212+
static var cardReaderConfigProvider: CommonReaderConfigProviding {
213+
_cardReaderConfigProvider
214+
}
215+
210216
/// Provides the access point to the ReceiptPrinterService.
211217
/// - Returns: An implementation of the ReceiptPrinterService protocol.
212218
static var receiptPrinterService: PrinterService {
@@ -336,6 +342,14 @@ extension ServiceLocator {
336342
#endif
337343
}
338344

345+
static func setCardReaderConfigProvider(_ mock: CommonReaderConfigProviding) {
346+
guard isRunningTests() else {
347+
return
348+
}
349+
350+
_cardReaderConfigProvider = mock
351+
}
352+
339353
static func setReceiptPrinter(_ mock: PrinterService) {
340354
guard isRunningTests() else {
341355
return

WooCommerce/Classes/Yosemite/AuthenticatedState.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class AuthenticatedState: StoresManagerState {
7575
CardPresentPaymentStore(dispatcher: dispatcher,
7676
storageManager: storageManager,
7777
network: network,
78-
cardReaderService: ServiceLocator.cardReaderService),
78+
cardReaderService: ServiceLocator.cardReaderService,
79+
cardReaderConfigProvider: ServiceLocator.cardReaderConfigProvider),
7980
ReceiptStore(dispatcher: dispatcher,
8081
storageManager: storageManager,
8182
network: network,

Yosemite/Yosemite.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@
108108
02FF056B23DED3670058E6E7 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 02FF056A23DED3670058E6E7 /* Media.xcassets */; };
109109
02FF056D23DEDCB90058E6E7 /* MockImageSourceWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FF056C23DEDCB90058E6E7 /* MockImageSourceWriter.swift */; };
110110
02FF056F23E04F320058E6E7 /* MockMediaExportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FF056E23E04F320058E6E7 /* MockMediaExportService.swift */; };
111+
030C94A62971C73700F7F65D /* MockCommonReaderConfigProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030C94A52971C73700F7F65D /* MockCommonReaderConfigProviding.swift */; };
112+
030C94A82971C96F00F7F65D /* CommonReaderConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030C94A72971C96F00F7F65D /* CommonReaderConfigProvider.swift */; };
111113
031C1EAA27B1702800298699 /* WCPayCharge+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C1EA927B1702800298699 /* WCPayCharge+ReadOnlyConvertible.swift */; };
112114
031C1EAC27B1873200298699 /* WCPayCardPresentReceiptDetails+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C1EAB27B1873200298699 /* WCPayCardPresentReceiptDetails+ReadOnlyConvertible.swift */; };
113115
031C1EAE27B1877000298699 /* WCPayCardPresentPaymentDetails+ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031C1EAD27B1877000298699 /* WCPayCardPresentPaymentDetails+ReadOnlyConvertible.swift */; };
@@ -541,6 +543,8 @@
541543
02FF056A23DED3670058E6E7 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
542544
02FF056C23DEDCB90058E6E7 /* MockImageSourceWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageSourceWriter.swift; sourceTree = "<group>"; };
543545
02FF056E23E04F320058E6E7 /* MockMediaExportService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockMediaExportService.swift; sourceTree = "<group>"; };
546+
030C94A52971C73700F7F65D /* MockCommonReaderConfigProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCommonReaderConfigProviding.swift; sourceTree = "<group>"; };
547+
030C94A72971C96F00F7F65D /* CommonReaderConfigProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonReaderConfigProvider.swift; sourceTree = "<group>"; };
544548
031C1EA927B1702800298699 /* WCPayCharge+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WCPayCharge+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
545549
031C1EAB27B1873200298699 /* WCPayCardPresentReceiptDetails+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WCPayCardPresentReceiptDetails+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
546550
031C1EAD27B1877000298699 /* WCPayCardPresentPaymentDetails+ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WCPayCardPresentPaymentDetails+ReadOnlyConvertible.swift"; sourceTree = "<group>"; };
@@ -1382,6 +1386,7 @@
13821386
B56C1EC120EAE2E500D749F9 /* ReadOnlyConvertible.swift */,
13831387
B52E002D211A3F5500700FDE /* ReadOnlyType.swift */,
13841388
0271E1652509CF0100633F7A /* AnyError.swift */,
1389+
030C94A72971C96F00F7F65D /* CommonReaderConfigProvider.swift */,
13851390
);
13861391
path = Tools;
13871392
sourceTree = "<group>";
@@ -1727,6 +1732,7 @@
17271732
isa = PBXGroup;
17281733
children = (
17291734
D88303EF25E45E6F00C877F9 /* MockCardReaderService.swift */,
1735+
030C94A52971C73700F7F65D /* MockCommonReaderConfigProviding.swift */,
17301736
D87F27DA25E7E8EA006EC8C9 /* MockCardReader.swift */,
17311737
D8652E4726307A5000350F37 /* MockReceiptPrinterService.swift */,
17321738
);
@@ -2057,6 +2063,7 @@
20572063
02124DAE2431C11600980D74 /* Media+ProductImage.swift in Sources */,
20582064
DEFD6D9526443CA100E51E0D /* SitePluginStore.swift in Sources */,
20592065
26577517243D5E42003168A5 /* ProductCategoryUpdated.swift in Sources */,
2066+
030C94A82971C96F00F7F65D /* CommonReaderConfigProvider.swift in Sources */,
20602067
261CF1F1255B389F0090D8D3 /* PaymentGatewayStore.swift in Sources */,
20612068
E18FDAFE28F97EB9008519BA /* AppAccountToken.swift in Sources */,
20622069
02FF055023D983F30058E6E7 /* ExportableAsset.swift in Sources */,
@@ -2300,6 +2307,7 @@
23002307
B9AECD482851F28E00E78584 /* Order+CardPresentPaymentTests.swift in Sources */,
23012308
02124DB02431C18700980D74 /* Media+ProductImageTests.swift in Sources */,
23022309
0248B3672459020500A271A4 /* ResultsController+FilterProductTests.swift in Sources */,
2310+
030C94A62971C73700F7F65D /* MockCommonReaderConfigProviding.swift in Sources */,
23032311
B54EAF2121188C470029C35E /* EntityListenerTests.swift in Sources */,
23042312
02FF056F23E04F320058E6E7 /* MockMediaExportService.swift in Sources */,
23052313
DE6831DD26445B2B00E88B9E /* SitePluginStoreTests.swift in Sources */,

Yosemite/Yosemite/Stores/CardPresentPaymentStore.swift

Lines changed: 4 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public final class CardPresentPaymentStore: Store {
1515

1616
/// Card reader config provider
1717
///
18-
private let commonReaderConfigProvider: CommonReaderConfigProvider
18+
private let commonReaderConfigProvider: CommonReaderConfigProviding
1919

2020
private var paymentGatewayAccount: PaymentGatewayAccount? {
2121
didSet {
@@ -51,10 +51,11 @@ public final class CardPresentPaymentStore: Store {
5151
dispatcher: Dispatcher,
5252
storageManager: StorageManagerType,
5353
network: Network,
54-
cardReaderService: CardReaderService
54+
cardReaderService: CardReaderService,
55+
cardReaderConfigProvider: CommonReaderConfigProviding
5556
) {
5657
self.cardReaderService = cardReaderService
57-
self.commonReaderConfigProvider = CommonReaderConfigProvider()
58+
self.commonReaderConfigProvider = cardReaderConfigProvider
5859
self.remote = WCPayRemote(network: network)
5960
self.stripeRemote = StripeRemote(network: network)
6061
super.init(dispatcher: dispatcher, storageManager: storageManager, network: network)
@@ -370,74 +371,6 @@ private extension CardPresentPaymentStore {
370371
onCompletion(publisher)
371372
}
372373
}
373-
private extension CardPresentPaymentStore {
374-
final class CommonReaderConfigProvider: CardReaderConfigProvider {
375-
var siteID: Int64?
376-
var readerConfigRemote: CardReaderCapableRemote?
377-
378-
public func setContext(siteID: Int64, remote: CardReaderCapableRemote) {
379-
self.siteID = siteID
380-
self.readerConfigRemote = remote
381-
}
382-
383-
public func fetchToken(completion: @escaping(Result<String, Error>) -> Void) {
384-
guard let siteID = self.siteID else {
385-
return
386-
}
387-
388-
readerConfigRemote?.loadConnectionToken(for: siteID) { result in
389-
switch result {
390-
case .success(let token):
391-
completion(.success(token.token))
392-
case .failure(let error):
393-
if let configError = CardReaderConfigError(error: error) {
394-
completion(.failure(configError))
395-
} else {
396-
completion(.failure(error))
397-
}
398-
}
399-
}
400-
}
401-
402-
public func fetchDefaultLocationID(completion: @escaping(Result<String, Error>) -> Void) {
403-
guard let siteID = self.siteID else {
404-
return
405-
}
406-
407-
readerConfigRemote?.loadDefaultReaderLocation(for: siteID) { result in
408-
switch result {
409-
case .success(let location):
410-
let readerLocation = location.toReaderLocation(siteID: siteID)
411-
completion(.success(readerLocation.id))
412-
case .failure(let error):
413-
if let configError = CardReaderConfigError(error: error) {
414-
completion(.failure(configError))
415-
} else {
416-
completion(.failure(error))
417-
}
418-
}
419-
}
420-
}
421-
}
422-
}
423-
424-
private extension CardReaderConfigError {
425-
init?(error: Error) {
426-
guard let dotcomError = error as? DotcomError else {
427-
return nil
428-
}
429-
switch dotcomError {
430-
case .unknown("store_address_is_incomplete", let message):
431-
self = .incompleteStoreAddress(adminUrl: URL(string: message ?? ""))
432-
return
433-
case .unknown("postal_code_invalid", _):
434-
self = .invalidPostalCode
435-
return
436-
default:
437-
return nil
438-
}
439-
}
440-
}
441374

442375
// MARK: Networking Methods
443376
private extension CardPresentPaymentStore {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import Foundation
2+
import Hardware
3+
import Networking
4+
5+
public protocol CardReaderRemoteConfigLoading {
6+
func setContext(siteID: Int64, remote: CardReaderCapableRemote)
7+
}
8+
9+
public protocol CommonReaderConfigProviding: CardReaderRemoteConfigLoading & CardReaderConfigProvider {}
10+
11+
12+
final public class CommonReaderConfigProvider: CommonReaderConfigProviding {
13+
var siteID: Int64?
14+
var readerConfigRemote: CardReaderCapableRemote?
15+
16+
public init(siteID: Int64? = nil, readerConfigRemote: CardReaderCapableRemote? = nil) {
17+
self.siteID = siteID
18+
self.readerConfigRemote = readerConfigRemote
19+
}
20+
21+
public func setContext(siteID: Int64, remote: CardReaderCapableRemote) {
22+
self.siteID = siteID
23+
self.readerConfigRemote = remote
24+
}
25+
26+
public func fetchToken(completion: @escaping(Result<String, Error>) -> Void) {
27+
guard let siteID = self.siteID else {
28+
return
29+
}
30+
31+
readerConfigRemote?.loadConnectionToken(for: siteID) { result in
32+
switch result {
33+
case .success(let token):
34+
completion(.success(token.token))
35+
case .failure(let error):
36+
if let configError = CardReaderConfigError(error: error) {
37+
completion(.failure(configError))
38+
} else {
39+
completion(.failure(error))
40+
}
41+
}
42+
}
43+
}
44+
45+
public func fetchDefaultLocationID(completion: @escaping(Result<String, Error>) -> Void) {
46+
guard let siteID = self.siteID else {
47+
return
48+
}
49+
50+
readerConfigRemote?.loadDefaultReaderLocation(for: siteID) { result in
51+
switch result {
52+
case .success(let location):
53+
let readerLocation = location.toReaderLocation(siteID: siteID)
54+
completion(.success(readerLocation.id))
55+
case .failure(let error):
56+
if let configError = CardReaderConfigError(error: error) {
57+
completion(.failure(configError))
58+
} else {
59+
completion(.failure(error))
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
private extension CardReaderConfigError {
67+
init?(error: Error) {
68+
guard let dotcomError = error as? DotcomError else {
69+
return nil
70+
}
71+
switch dotcomError {
72+
case .unknown("store_address_is_incomplete", let message):
73+
self = .incompleteStoreAddress(adminUrl: URL(string: message ?? ""))
74+
return
75+
case .unknown("postal_code_invalid", _):
76+
self = .invalidPostalCode
77+
return
78+
default:
79+
return nil
80+
}
81+
}
82+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Foundation
2+
3+
@testable import Yosemite
4+
5+
final class MockCommonReaderConfigProviding: CommonReaderConfigProviding {
6+
func fetchToken(completion: @escaping (Result<String, Error>) -> Void) {
7+
completion(.success("mock_token"))
8+
}
9+
10+
func fetchDefaultLocationID(completion: @escaping (Result<String, Error>) -> Void) {
11+
completion(.success("mock_location"))
12+
}
13+
14+
func setContext(siteID: Int64, remote: Yosemite.CardReaderCapableRemote) {
15+
// no-op
16+
}
17+
}

Yosemite/YosemiteTests/Stores/CardPresentPaymentStoreTests.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ final class CardPresentPaymentStoreTests: XCTestCase {
3232
/// Mock Card Reader Service: In memory
3333
private var mockCardReaderService: MockCardReaderService!
3434

35+
private var mockCardReaderConfigProvider: CommonReaderConfigProviding!
36+
3537
private var cardPresentStore: CardPresentPaymentStore!
3638

3739
/// Dummy Site ID
@@ -72,7 +74,8 @@ final class CardPresentPaymentStoreTests: XCTestCase {
7274
cardPresentStore = CardPresentPaymentStore(dispatcher: dispatcher,
7375
storageManager: storageManager,
7476
network: network,
75-
cardReaderService: mockCardReaderService)
77+
cardReaderService: mockCardReaderService,
78+
cardReaderConfigProvider: mockCardReaderConfigProvider)
7679
}
7780

7881
override func tearDown() {

0 commit comments

Comments
 (0)