From 5ab494dc1b0cc8548b7bee73658a6f92ff18cfe6 Mon Sep 17 00:00:00 2001 From: Dave Hole Date: Fri, 23 Jan 2026 12:19:49 +1100 Subject: [PATCH 1/2] Add getAuthorizedLocation to iOS plugin --- ios/Classes/Extensions/AuthorizationExtension.swift | 10 ++++++++++ ios/Classes/Modules/AuthModule.swift | 7 +++++++ ios/Classes/SquareMobilePaymentsSdkPlugin.swift | 2 ++ 3 files changed, 19 insertions(+) diff --git a/ios/Classes/Extensions/AuthorizationExtension.swift b/ios/Classes/Extensions/AuthorizationExtension.swift index ad92d11..b3596a8 100644 --- a/ios/Classes/Extensions/AuthorizationExtension.swift +++ b/ios/Classes/Extensions/AuthorizationExtension.swift @@ -34,4 +34,14 @@ extension AuthorizationError { default: "unknown" } } +} + +extension Location { + func toMap() -> [String: Any] { + return [ + "id": id, + "currencyCode": currency.getCurrencyCode(), + "name": name + ] + } } \ No newline at end of file diff --git a/ios/Classes/Modules/AuthModule.swift b/ios/Classes/Modules/AuthModule.swift index ea2aca6..698328a 100644 --- a/ios/Classes/Modules/AuthModule.swift +++ b/ios/Classes/Modules/AuthModule.swift @@ -8,6 +8,13 @@ public class AuthModule { return result(authManager.state.getName()) } + public static func getAuthorizedLocation(result: @escaping FlutterResult) { + guard let location = authManager.location else { + return result(nil) + } + return result(location.toMap()) + } + public static func authorize( result: @escaping FlutterResult, accessToken: String, diff --git a/ios/Classes/SquareMobilePaymentsSdkPlugin.swift b/ios/Classes/SquareMobilePaymentsSdkPlugin.swift index 0ac8926..a3b0735 100644 --- a/ios/Classes/SquareMobilePaymentsSdkPlugin.swift +++ b/ios/Classes/SquareMobilePaymentsSdkPlugin.swift @@ -43,6 +43,8 @@ public class SquareMobilePaymentsSdkPlugin: NSObject, FlutterPlugin, FlutterStre AuthModule.deauthorize(result: result) case "getAuthorizationState": AuthModule.getAuthorizationState(result: result) + case "getAuthorizedLocation": + AuthModule.getAuthorizedLocation(result: result) case "showMockReaderUI": ReaderModule.showMockReaderUI(result: result) case "hideMockReaderUI": From 88960e3e98d7f29a7fcdccadd8d6fbec3658c008 Mon Sep 17 00:00:00 2001 From: Dave Hole Date: Tue, 7 Apr 2026 18:09:58 +1000 Subject: [PATCH 2/2] disable mock UI for release builds --- ios/Classes/Extensions/ReaderExtension.swift | 2 + ios/Classes/Modules/ReaderModule.swift | 12 ++++++ ios/enable_mock_reader.rb | 39 ++++++++++++++++++++ ios/square_mobile_payments_sdk.podspec | 6 ++- 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 ios/enable_mock_reader.rb diff --git a/ios/Classes/Extensions/ReaderExtension.swift b/ios/Classes/Extensions/ReaderExtension.swift index 0fc07c1..5f7e5a7 100644 --- a/ios/Classes/Extensions/ReaderExtension.swift +++ b/ios/Classes/Extensions/ReaderExtension.swift @@ -1,4 +1,5 @@ import SquareMobilePaymentsSDK +#if MOCK_READER_UI_ENABLED import MockReaderUI extension MockReaderUIError { @@ -18,3 +19,4 @@ extension MockReaderUIError { } } } +#endif diff --git a/ios/Classes/Modules/ReaderModule.swift b/ios/Classes/Modules/ReaderModule.swift index 6d3a0ac..14d4ad4 100644 --- a/ios/Classes/Modules/ReaderModule.swift +++ b/ios/Classes/Modules/ReaderModule.swift @@ -1,11 +1,14 @@ import Flutter import SquareMobilePaymentsSDK +#if MOCK_READER_UI_ENABLED import MockReaderUI +#endif public class ReaderModule { private static var globalReaderObserver: ReaderObserverCallback? private static var globalPairingHandle: PairingHandle? + #if MOCK_READER_UI_ENABLED static var mockReader: MockReaderUI? = { do { return try MockReaderUI(for: MobilePaymentsSDK.shared) @@ -13,6 +16,7 @@ public class ReaderModule { return nil } }() + #endif static func parseTapToPayError(error: NSError, defaultError: String) -> String { let tapToPayReaderError = TapToPayReaderError(rawValue: error.code) @@ -53,17 +57,25 @@ public class ReaderModule { } public static func showMockReaderUI(result: @escaping FlutterResult) { + #if MOCK_READER_UI_ENABLED do { try mockReader?.present() result("Mock Reader has been successfully presented.") } catch let error { result(FlutterError(code: "SHOW_MOCK_READER_UI", message: error.localizedDescription, details: nil)) } + #else + result(FlutterError(code: "MOCK_READER_UNAVAILABLE", message: "MockReaderUI is not available. Add MockReaderUI to your Podfile to enable mock reader support.", details: nil)) + #endif } public static func hideMockReaderUI(result: @escaping FlutterResult) { + #if MOCK_READER_UI_ENABLED mockReader?.dismiss() result("Mock Reader has been successfully hidden.") + #else + result(FlutterError(code: "MOCK_READER_UNAVAILABLE", message: "MockReaderUI is not available. Add MockReaderUI to your Podfile to enable mock reader support.", details: nil)) + #endif } public static func linkAppleAccount(result: @escaping FlutterResult) { diff --git a/ios/enable_mock_reader.rb b/ios/enable_mock_reader.rb new file mode 100644 index 0000000..464f6b9 --- /dev/null +++ b/ios/enable_mock_reader.rb @@ -0,0 +1,39 @@ +# Helper to enable MockReaderUI in the square_mobile_payments_sdk Flutter plugin. +# +# MockReaderUI is a debug/sandbox-only tool provided by Square for testing +# in-person payments without physical hardware. It should NOT be included +# in release/production builds submitted to the App Store. +# +# Usage in your app's Podfile: +# +# pod 'MockReaderUI', '~> 2.4.0', :configurations => ['Debug'] +# +# post_install do |installer| +# require_relative '.symlinks/plugins/square_mobile_payments_sdk/ios/enable_mock_reader' +# enable_square_mock_reader(installer) +# end +# + +def enable_square_mock_reader(installer, configurations: ['Debug']) + installer.pods_project.targets.each do |target| + next unless target.name == 'square_mobile_payments_sdk' + + target.build_configurations.each do |config| + next unless configurations.include?(config.name) + + # Set the Swift compilation flag so #if MOCK_READER_UI_ENABLED guards compile in + swift_flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' + unless swift_flags.include?('MOCK_READER_UI_ENABLED') + config.build_settings['OTHER_SWIFT_FLAGS'] = "#{swift_flags} -DMOCK_READER_UI_ENABLED" + end + + # Add MockReaderUI to framework search paths so the compiler and linker can find it + search_paths = config.build_settings['FRAMEWORK_SEARCH_PATHS'] || ['$(inherited)'] + mock_reader_path = '"${PODS_CONFIGURATION_BUILD_DIR}/MockReaderUI"' + unless search_paths.include?(mock_reader_path) + search_paths << mock_reader_path + config.build_settings['FRAMEWORK_SEARCH_PATHS'] = search_paths + end + end + end +end \ No newline at end of file diff --git a/ios/square_mobile_payments_sdk.podspec b/ios/square_mobile_payments_sdk.podspec index 7fdab09..7bfa0b7 100644 --- a/ios/square_mobile_payments_sdk.podspec +++ b/ios/square_mobile_payments_sdk.podspec @@ -18,7 +18,11 @@ Allows developers to take in-person payments using Square hardware. s.platform = :ios, '16.0' s.dependency "SquareMobilePaymentsSDK", "~> 2.4.0" - s.dependency "MockReaderUI", "~> 2.4.0" + # MockReaderUI is intentionally NOT a hard dependency. It is a sandbox/debug-only + # framework that must not be embedded in App Store builds. Consumer apps that + # need it for development should add it to their Podfile as a Debug-only pod + # and call `enable_square_mock_reader(installer)` from `post_install` (see + # ios/enable_mock_reader.rb). # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }