diff --git a/Demo/Application/Base/Base View Controllers/BraintreeDemoPaymentButtonBaseViewController.m b/Demo/Application/Base/Base View Controllers/BraintreeDemoPaymentButtonBaseViewController.m index b4f7fa6121..076042c8b0 100644 --- a/Demo/Application/Base/Base View Controllers/BraintreeDemoPaymentButtonBaseViewController.m +++ b/Demo/Application/Base/Base View Controllers/BraintreeDemoPaymentButtonBaseViewController.m @@ -23,7 +23,8 @@ - (void)viewDidLoad { [self.view addSubview:self.paymentButton]; [NSLayoutConstraint activateConstraints:@[ - [self.paymentButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.paymentButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.paymentButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.paymentButton.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor constant:self.centerYConstant], [self.paymentButton.heightAnchor constraintEqualToConstant:44.0] ]]; diff --git a/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.h b/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.h deleted file mode 100644 index 801bf94ddf..0000000000 --- a/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -#import "BraintreeDemoBaseViewController.h" - -@interface BraintreeDemoBTDataCollectorViewController : BraintreeDemoBaseViewController - -@end diff --git a/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.m b/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.m deleted file mode 100644 index 9e37bd5f61..0000000000 --- a/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.m +++ /dev/null @@ -1,112 +0,0 @@ -#import "BraintreeDemoBTDataCollectorViewController.h" -#import "Demo-Swift.h" -@import BraintreeDataCollector; -@import CoreLocation; -@import BraintreeCore; - -@interface BraintreeDemoBTDataCollectorViewController () - -/// Retain BTDataCollector for entire lifecycle of view controller -@property (nonatomic, strong) BTDataCollector *dataCollector; -@property (nonatomic, strong) UILabel *dataLabel; -@property (nonatomic, strong) BTAPIClient *apiClient; -@property (nonatomic, strong) CLLocationManager *locationManager; - -@end - -@implementation BraintreeDemoBTDataCollectorViewController - -- (instancetype)initWithAuthorization:(NSString *)authorization { - if (self = [super initWithAuthorization:authorization]) { - _apiClient = [[BTAPIClient alloc] initWithAuthorization:authorization]; - _locationManager = [CLLocationManager new]; - } - - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = NSLocalizedString(@"BTDataCollector Protection", nil); - - UIButton *collectButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [collectButton setTitle:NSLocalizedString(@"Collect All Data", nil) forState:UIControlStateNormal]; - [collectButton addTarget:self - action:@selector(tappedCollect) - forControlEvents:UIControlEventTouchUpInside]; - - self.dataLabel = [[UILabel alloc] init]; - self.dataLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.dataLabel.numberOfLines = 0; - - UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[collectButton, - self.dataLabel]]; - stackView.translatesAutoresizingMaskIntoConstraints = NO; - stackView.axis = UILayoutConstraintAxisVertical; - - [self.view addSubview:stackView]; - - UIButton *obtainLocationPermissionButton = [UIButton buttonWithType:UIButtonTypeSystem]; - obtainLocationPermissionButton.translatesAutoresizingMaskIntoConstraints = NO; - [obtainLocationPermissionButton setTitle:NSLocalizedString(@"Obtain Location Permission", nil) forState:UIControlStateNormal]; - [obtainLocationPermissionButton addTarget:self - action:@selector(tappedRequestLocationAuthorization:) - forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:obtainLocationPermissionButton]; - - [NSLayoutConstraint activateConstraints:@[ - [stackView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:100.0], - [stackView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor], - [stackView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor], - [obtainLocationPermissionButton.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-10.0], - [obtainLocationPermissionButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] - ]]; - - self.dataCollector = [[BTDataCollector alloc] initWithAPIClient:self.apiClient]; -} - -- (IBAction)tappedCollect { - self.progressBlock(@"Started collecting all data..."); - [self.dataCollector collectDeviceData:^(NSString * _Nullable deviceData, NSError * _Nullable error) { - self.dataLabel.text = deviceData; - self.progressBlock(@"Collected all device data!"); - }]; -} - -- (IBAction)tappedRequestLocationAuthorization:(__unused id)sender { - CLAuthorizationStatus locationStatus = kCLAuthorizationStatusNotDetermined; - locationStatus = [CLLocationManager new].authorizationStatus; - - switch (locationStatus) { - case kCLAuthorizationStatusNotDetermined: - [self.locationManager requestWhenInUseAuthorization]; - break; - - default: - self.progressBlock(@"Location authorization requested previously. Update authorization in Settings app."); - break; - } -} - -#pragma mark - BTDataCollectorDelegate - -/// The collector has started. -- (void)dataCollectorDidStart:(__unused BTDataCollector *)dataCollector { - self.progressBlock(@"Data collector did start..."); -} - -/// The collector finished successfully. -- (void)dataCollectorDidComplete:(__unused BTDataCollector *)dataCollector { - self.progressBlock(@"Data collector did complete."); -} - -/// An error occurred. -/// -/// @param error Triggering error -- (void)dataCollector:(__unused BTDataCollector *)dataCollector didFailWithError:(NSError *)error { - self.progressBlock(@"Error collecting data."); - NSLog(@"Error collecting data. error = %@", error); -} - -@end diff --git a/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.swift b/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.swift new file mode 100644 index 0000000000..7035d04696 --- /dev/null +++ b/Demo/Application/Features/Fraud Protection - BTDataCollector/BraintreeDemoBTDataCollectorViewController.swift @@ -0,0 +1,88 @@ +import UIKit +import CoreLocation +import BraintreeDataCollector +import BraintreeCore + +class BraintreeDemoBTDataCollectorViewController: BraintreeDemoPaymentButtonBaseViewController { + + let locationManager = CLLocationManager() + var dataLabel = UILabel() + + override func viewDidLoad() { + super.viewDidLoad() + title = "Braintree Data Collector" + createLocationPermissionButton() + } + + override func createPaymentButton() -> UIView! { + let dataCollectorButton = UIButton(type: .system) + dataCollectorButton.setTitle("Collect Device Data", for: .normal) + dataCollectorButton.setTitleColor(.blue, for: .normal) + dataCollectorButton.setTitleColor(.lightGray, for: .highlighted) + dataCollectorButton.setTitleColor(.lightGray, for: .disabled) + dataCollectorButton.addTarget(self, action: #selector(tappedCollect), for: .touchUpInside) + dataCollectorButton.translatesAutoresizingMaskIntoConstraints = false + + let label = UILabel() + label.numberOfLines = 0 + label.adjustsFontSizeToFitWidth = true + label.translatesAutoresizingMaskIntoConstraints = false + + self.dataLabel = label + + let stackView = UIStackView(arrangedSubviews: [dataCollectorButton, label]) + stackView.axis = .vertical + stackView.spacing = 5 + stackView.alignment = .center + stackView.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + dataCollectorButton.heightAnchor.constraint(equalToConstant: 19.5), + label.heightAnchor.constraint(equalToConstant: 19.5) + ]) + + return stackView + } + + @objc func tappedCollect() { + let dataCollector = BTDataCollector(apiClient: apiClient) + + progressBlock("Started collecting all data...") + dataCollector.collectDeviceData { deviceData, error in + guard let deviceData else { + self.progressBlock(error?.localizedDescription) + return + } + + self.dataLabel.text = deviceData + self.progressBlock("Collected all device data!") + } + } + + @objc func tappedRequestLocationAuthorization() { + let locationStatus = locationManager.authorizationStatus + + switch locationStatus { + case .notDetermined: + locationManager.requestWhenInUseAuthorization() + + default: + progressBlock("Location authorization requested previously. Update authorization in Settings app.") + } + } + + private func createLocationPermissionButton() { + let obtainLocationPermissionButton = UIButton(type: .system) + obtainLocationPermissionButton.setTitle("Obtain Location Permission", for: .normal) + obtainLocationPermissionButton.setTitleColor(.blue, for: .normal) + obtainLocationPermissionButton.addTarget(self, action: #selector(tappedRequestLocationAuthorization), for: .touchUpInside) + obtainLocationPermissionButton.translatesAutoresizingMaskIntoConstraints = false + + view.addSubview(obtainLocationPermissionButton) + + NSLayoutConstraint.activate([ + obtainLocationPermissionButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10), + obtainLocationPermissionButton.centerXAnchor.constraint(equalTo: view.centerXAnchor) + ]) + } +} diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 657cfda895..501c306995 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -55,7 +55,6 @@ A0988FE324DB44B20095EEEE /* Main.strings in Resources */ = {isa = PBXBuildFile; fileRef = A0988F5224DB44B10095EEEE /* Main.strings */; }; A0988FE424DB44B20095EEEE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A0988F5424DB44B10095EEEE /* InfoPlist.strings */; }; A0988FE624DB44B20095EEEE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A0988F5824DB44B10095EEEE /* main.m */; }; - A0988FE824DB44B20095EEEE /* BraintreeDemoBTDataCollectorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0988F5D24DB44B10095EEEE /* BraintreeDemoBTDataCollectorViewController.m */; }; A0988FEA24DB44B20095EEEE /* BraintreeDemoIdealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0988F6424DB44B10095EEEE /* BraintreeDemoIdealViewController.m */; }; A0988FEE24DB44B20095EEEE /* BraintreeDemoCardTokenizationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0988F6E24DB44B10095EEEE /* BraintreeDemoCardTokenizationViewController.m */; }; A0988FF024DB44B20095EEEE /* BraintreeDemoApplePayPassKitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A0988F7424DB44B10095EEEE /* BraintreeDemoApplePayPassKitViewController.m */; }; @@ -77,6 +76,7 @@ BE9BD75A28872E4D00022983 /* BraintreeSEPADirectDebit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BE9BD75828872E4D00022983 /* BraintreeSEPADirectDebit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; BEAAAD052970A70D000BD296 /* BTSEPADirectDebitTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEAAAD042970A70D000BD296 /* BTSEPADirectDebitTestHelper.swift */; }; BEE2E4BC290043D100C03FDD /* PayPalCheckout in Frameworks */ = {isa = PBXBuildFile; productRef = BEE2E4BB290043D100C03FDD /* PayPalCheckout */; }; + BEE930492A98FE9200C85779 /* BraintreeDemoBTDataCollectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEE930482A98FE9200C85779 /* BraintreeDemoBTDataCollectorViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -177,8 +177,6 @@ A0988F5624DB44B10095EEEE /* Braintree-Demo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Braintree-Demo-Prefix.pch"; sourceTree = ""; }; A0988F5724DB44B10095EEEE /* Braintree-Demo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Braintree-Demo-Info.plist"; sourceTree = ""; }; A0988F5824DB44B10095EEEE /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - A0988F5D24DB44B10095EEEE /* BraintreeDemoBTDataCollectorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BraintreeDemoBTDataCollectorViewController.m; sourceTree = ""; }; - A0988F5E24DB44B10095EEEE /* BraintreeDemoBTDataCollectorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BraintreeDemoBTDataCollectorViewController.h; sourceTree = ""; }; A0988F6324DB44B10095EEEE /* BraintreeDemoIdealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BraintreeDemoIdealViewController.h; sourceTree = ""; }; A0988F6424DB44B10095EEEE /* BraintreeDemoIdealViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BraintreeDemoIdealViewController.m; sourceTree = ""; }; A0988F6C24DB44B10095EEEE /* BraintreeDemoCardTokenizationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BraintreeDemoCardTokenizationViewController.h; sourceTree = ""; }; @@ -206,6 +204,7 @@ BE777AC327D9370400487D23 /* BraintreeDemoSEPADirectDebitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BraintreeDemoSEPADirectDebitViewController.swift; sourceTree = ""; }; BE9BD75828872E4D00022983 /* BraintreeSEPADirectDebit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = BraintreeSEPADirectDebit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BEAAAD042970A70D000BD296 /* BTSEPADirectDebitTestHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTSEPADirectDebitTestHelper.swift; sourceTree = ""; }; + BEE930482A98FE9200C85779 /* BraintreeDemoBTDataCollectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BraintreeDemoBTDataCollectorViewController.swift; sourceTree = ""; }; C8E5BAD1DA81AAD310B19786 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -402,8 +401,7 @@ A0988F5C24DB44B10095EEEE /* Fraud Protection - BTDataCollector */ = { isa = PBXGroup; children = ( - A0988F5E24DB44B10095EEEE /* BraintreeDemoBTDataCollectorViewController.h */, - A0988F5D24DB44B10095EEEE /* BraintreeDemoBTDataCollectorViewController.m */, + BEE930482A98FE9200C85779 /* BraintreeDemoBTDataCollectorViewController.swift */, ); path = "Fraud Protection - BTDataCollector"; sourceTree = ""; @@ -811,10 +809,10 @@ BE4F788927EE2B6D00FF4C0E /* BraintreeDemoPayPalVaultViewController.swift in Sources */, A0988FEE24DB44B20095EEEE /* BraintreeDemoCardTokenizationViewController.m in Sources */, 42D47A152554679D0012BAF1 /* BraintreeDemoSceneDelegate.m in Sources */, - A0988FE824DB44B20095EEEE /* BraintreeDemoBTDataCollectorViewController.m in Sources */, A0988FF224DB44B20095EEEE /* BraintreeDemoThreeDSecurePaymentFlowViewController.m in Sources */, A0988F9424DB44B20095EEEE /* BraintreeDemoPaymentButtonBaseViewController.m in Sources */, 80D36DEE2A7967F20035380E /* BraintreeDemoVenmoViewController.swift in Sources */, + BEE930492A98FE9200C85779 /* BraintreeDemoBTDataCollectorViewController.swift in Sources */, A0988F9624DB44B20095EEEE /* BraintreeDemoAppDelegate.m in Sources */, BEAAAD052970A70D000BD296 /* BTSEPADirectDebitTestHelper.swift in Sources */, A0988FF024DB44B20095EEEE /* BraintreeDemoApplePayPassKitViewController.m in Sources */,