@capawesome/capacitor-square-mobile-payments 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CapawesomeCapacitorSquareMobilePayments.podspec +17 -0
- package/Package.swift +30 -0
- package/README.md +1183 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/SquareMobilePayments.java +774 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/SquareMobilePaymentsPlugin.java +460 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/CustomException.java +20 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/CustomExceptions.java +41 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/AvailableCardInputMethodsDidChangeEvent.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/PaymentDidCancelEvent.java +24 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/PaymentDidFailEvent.java +34 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/PaymentDidFinishEvent.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/ReaderDidChangeEvent.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/ReaderPairingDidFailEvent.java +28 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/ReaderWasAddedEvent.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/events/ReaderWasRemovedEvent.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/AuthorizeOptions.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/ForgetReaderOptions.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/InitializeOptions.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/Money.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/PaymentParameters.java +126 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/PromptParameters.java +47 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/RetryConnectionOptions.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/options/StartPaymentOptions.java +39 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/Card.java +51 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/CardPaymentDetails.java +30 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/GetAvailableCardInputMethodsResult.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/GetReadersResult.java +29 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/GetSettingsResult.java +28 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/IsAuthorizedResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/IsPairingInProgressResult.java +22 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/MoneyResult.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/Payment.java +87 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/ReaderInfo.java +82 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/classes/results/UnavailableReasonInfo.java +30 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/interfaces/Callback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/interfaces/EmptyCallback.java +5 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/interfaces/NonEmptyCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/interfaces/NonEmptyResultCallback.java +7 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/squaremobilepayments/interfaces/Result.java +7 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +2999 -0
- package/dist/esm/definitions.d.ts +1468 -0
- package/dist/esm/definitions.js +519 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +21 -0
- package/dist/esm/web.js +55 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +588 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +591 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Classes/Options/AuthorizeOptions.swift +17 -0
- package/ios/Plugin/Classes/Options/ForgetReaderOptions.swift +17 -0
- package/ios/Plugin/Classes/Options/InitializeOptions.swift +17 -0
- package/ios/Plugin/Classes/Options/Money.swift +12 -0
- package/ios/Plugin/Classes/Options/PaymentParameters.swift +49 -0
- package/ios/Plugin/Classes/Options/PromptParameters.swift +17 -0
- package/ios/Plugin/Classes/Options/RetryConnectionOptions.swift +17 -0
- package/ios/Plugin/Classes/Options/StartPaymentOptions.swift +19 -0
- package/ios/Plugin/Classes/Results/Card.swift +34 -0
- package/ios/Plugin/Classes/Results/CardPaymentDetails.swift +34 -0
- package/ios/Plugin/Classes/Results/GetAvailableCardInputMethodsResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GetReadersResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GetSettingsResult.swift +19 -0
- package/ios/Plugin/Classes/Results/IsAuthorizedResult.swift +16 -0
- package/ios/Plugin/Classes/Results/IsPairingInProgressResult.swift +16 -0
- package/ios/Plugin/Classes/Results/MoneyResult.swift +19 -0
- package/ios/Plugin/Classes/Results/Payment.swift +58 -0
- package/ios/Plugin/Classes/Results/ReaderInfo.swift +46 -0
- package/ios/Plugin/Classes/Results/UnavailableReasonInfo.swift +19 -0
- package/ios/Plugin/Enums/CustomError.swift +81 -0
- package/ios/Plugin/Info.plist +24 -0
- package/ios/Plugin/Protocols/Result.swift +6 -0
- package/ios/Plugin/SquareMobilePayments.swift +632 -0
- package/ios/Plugin/SquareMobilePaymentsHelper.swift +212 -0
- package/ios/Plugin/SquareMobilePaymentsPlugin.swift +347 -0
- package/package.json +93 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
import SquareMobilePaymentsSDK
|
|
4
|
+
import CoreLocation
|
|
5
|
+
import CoreBluetooth
|
|
6
|
+
|
|
7
|
+
@objc public class SquareMobilePayments: NSObject {
|
|
8
|
+
private weak var plugin: SquareMobilePaymentsPlugin?
|
|
9
|
+
private var pairingHandle: SquareMobilePaymentsSDK.PairingHandle?
|
|
10
|
+
private var paymentHandle: SquareMobilePaymentsSDK.PaymentHandle?
|
|
11
|
+
private var squareApplicationId: String?
|
|
12
|
+
private var locationId: String?
|
|
13
|
+
private var locationManager: CLLocationManager?
|
|
14
|
+
private var bluetoothManager: CBCentralManager?
|
|
15
|
+
private var locationPermissionCompletion: ((CLAuthorizationStatus) -> Void)?
|
|
16
|
+
private var bluetoothPermissionCompletion: (() -> Void)?
|
|
17
|
+
|
|
18
|
+
init(plugin: SquareMobilePaymentsPlugin) {
|
|
19
|
+
self.plugin = plugin
|
|
20
|
+
super.init()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@objc public func initialize(_ options: InitializeOptions, completion: @escaping (_ error: Error?) -> Void) throws {
|
|
24
|
+
// Store location ID for later use during authorization
|
|
25
|
+
self.locationId = options.locationId
|
|
26
|
+
|
|
27
|
+
// Note: According to Square's docs, MobilePaymentsSDK.initialize should be called in AppDelegate
|
|
28
|
+
// For now, we'll just store the location ID and skip actual initialization here
|
|
29
|
+
completion(nil)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@objc public func authorize(_ options: AuthorizeOptions, completion: @escaping (_ error: Error?) -> Void) throws {
|
|
33
|
+
guard let locationId = self.locationId else {
|
|
34
|
+
throw CustomError.notInitialized
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let accessToken = options.accessToken
|
|
38
|
+
let authManager = MobilePaymentsSDK.shared.authorizationManager
|
|
39
|
+
|
|
40
|
+
guard authManager.state == .notAuthorized else {
|
|
41
|
+
// Already authorized
|
|
42
|
+
completion(nil)
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
authManager.authorize(withAccessToken: accessToken, locationID: locationId) { error in
|
|
47
|
+
if let error = error {
|
|
48
|
+
completion(error)
|
|
49
|
+
} else {
|
|
50
|
+
// Add observer for reader changes after authorization
|
|
51
|
+
MobilePaymentsSDK.shared.readerManager.add(self)
|
|
52
|
+
// Add observer for available card input methods
|
|
53
|
+
MobilePaymentsSDK.shared.paymentManager.add(self)
|
|
54
|
+
completion(nil)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc public func isAuthorized(completion: @escaping (_ result: IsAuthorizedResult?, _ error: Error?) -> Void) throws {
|
|
60
|
+
let authManager = MobilePaymentsSDK.shared.authorizationManager
|
|
61
|
+
let authorized = authManager.state == .authorized
|
|
62
|
+
let result = IsAuthorizedResult(authorized: authorized)
|
|
63
|
+
completion(result, nil)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@objc public func deauthorize(completion: @escaping (_ error: Error?) -> Void) throws {
|
|
67
|
+
guard locationId != nil else {
|
|
68
|
+
throw CustomError.notInitialized
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let authManager = MobilePaymentsSDK.shared.authorizationManager
|
|
72
|
+
|
|
73
|
+
guard authManager.state != .notAuthorized else {
|
|
74
|
+
// Already deauthorized
|
|
75
|
+
completion(nil)
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Remove observers
|
|
80
|
+
MobilePaymentsSDK.shared.readerManager.remove(self)
|
|
81
|
+
MobilePaymentsSDK.shared.paymentManager.remove(self)
|
|
82
|
+
|
|
83
|
+
authManager.deauthorize {
|
|
84
|
+
completion(nil)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@objc public func showSettings(completion: @escaping (_ error: Error?) -> Void) throws {
|
|
89
|
+
guard locationId != nil else {
|
|
90
|
+
throw CustomError.notInitialized
|
|
91
|
+
}
|
|
92
|
+
guard MobilePaymentsSDK.shared.authorizationManager.state == .authorized else {
|
|
93
|
+
throw CustomError.notAuthorized
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
guard let viewController = plugin?.bridge?.viewController else {
|
|
97
|
+
completion(NSError(domain: "SquareMobilePayments", code: -1, userInfo: [NSLocalizedDescriptionKey: "View controller not available"]))
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
MobilePaymentsSDK.shared.settingsManager.presentSettings(with: viewController) { error in
|
|
102
|
+
completion(error)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc public func getSettings(completion: @escaping (_ result: GetSettingsResult?, _ error: Error?) -> Void) throws {
|
|
107
|
+
guard locationId != nil else {
|
|
108
|
+
throw CustomError.notInitialized
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let settings = MobilePaymentsSDK.shared.settingsManager
|
|
112
|
+
let version = settings.sdkSettings.version
|
|
113
|
+
let environment = SquareMobilePaymentsHelper.convertEnvironment(settings.sdkSettings.environment)
|
|
114
|
+
|
|
115
|
+
let result = GetSettingsResult(version: version, environment: environment)
|
|
116
|
+
completion(result, nil)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@objc public func startPairing(completion: @escaping (_ error: Error?) -> Void) throws {
|
|
120
|
+
guard locationId != nil else {
|
|
121
|
+
throw CustomError.notInitialized
|
|
122
|
+
}
|
|
123
|
+
guard MobilePaymentsSDK.shared.authorizationManager.state == .authorized else {
|
|
124
|
+
throw CustomError.notAuthorized
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let readerManager = MobilePaymentsSDK.shared.readerManager
|
|
128
|
+
if readerManager.isPairingInProgress {
|
|
129
|
+
throw CustomError.pairingAlreadyInProgress
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
pairingHandle = readerManager.startPairing(with: self)
|
|
133
|
+
completion(nil)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@objc public func stopPairing(completion: @escaping (_ error: Error?) -> Void) throws {
|
|
137
|
+
guard locationId != nil else {
|
|
138
|
+
throw CustomError.notInitialized
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
pairingHandle?.stop()
|
|
142
|
+
pairingHandle = nil
|
|
143
|
+
completion(nil)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@objc public func isPairingInProgress(completion: @escaping (_ result: IsPairingInProgressResult?, _ error: Error?) -> Void) throws {
|
|
147
|
+
guard locationId != nil else {
|
|
148
|
+
throw CustomError.notInitialized
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let inProgress = MobilePaymentsSDK.shared.readerManager.isPairingInProgress
|
|
152
|
+
let result = IsPairingInProgressResult(inProgress: inProgress)
|
|
153
|
+
completion(result, nil)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@objc public func getReaders(completion: @escaping (_ result: GetReadersResult?, _ error: Error?) -> Void) throws {
|
|
157
|
+
guard locationId != nil else {
|
|
158
|
+
throw CustomError.notInitialized
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let sdkReaders = MobilePaymentsSDK.shared.readerManager.readers
|
|
162
|
+
let readers = sdkReaders.map { convertSdkReaderToReaderInfo($0) }
|
|
163
|
+
|
|
164
|
+
let result = GetReadersResult(readers: readers)
|
|
165
|
+
completion(result, nil)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@objc public func forgetReader(_ options: ForgetReaderOptions, completion: @escaping (_ error: Error?) -> Void) throws {
|
|
169
|
+
guard locationId != nil else {
|
|
170
|
+
throw CustomError.notInitialized
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let serialNumber = options.serialNumber
|
|
174
|
+
let readerManager = MobilePaymentsSDK.shared.readerManager
|
|
175
|
+
|
|
176
|
+
guard let reader = readerManager.readers.first(where: { $0.serialNumber == serialNumber }) else {
|
|
177
|
+
throw CustomError.readerNotFound
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
readerManager.forget(reader)
|
|
181
|
+
completion(nil)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@objc public func retryConnection(_ options: RetryConnectionOptions, completion: @escaping (_ error: Error?) -> Void) throws {
|
|
185
|
+
guard locationId != nil else {
|
|
186
|
+
throw CustomError.notInitialized
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let serialNumber = options.serialNumber
|
|
190
|
+
let readerManager = MobilePaymentsSDK.shared.readerManager
|
|
191
|
+
|
|
192
|
+
guard let reader = readerManager.readers.first(where: { $0.serialNumber == serialNumber }) else {
|
|
193
|
+
throw CustomError.readerNotFound
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
readerManager.retryConnection(reader)
|
|
197
|
+
completion(nil)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@objc public func startPayment(_ options: StartPaymentOptions, completion: @escaping (_ error: Error?) -> Void) throws {
|
|
201
|
+
guard locationId != nil else {
|
|
202
|
+
throw CustomError.notInitialized
|
|
203
|
+
}
|
|
204
|
+
guard MobilePaymentsSDK.shared.authorizationManager.state == .authorized else {
|
|
205
|
+
throw CustomError.notAuthorized
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
guard let viewController = plugin?.bridge?.viewController else {
|
|
209
|
+
completion(NSError(domain: "SquareMobilePayments", code: -1, userInfo: [NSLocalizedDescriptionKey: "View controller not available"]))
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let params = options.paymentParameters
|
|
214
|
+
let promptParams = options.promptParameters
|
|
215
|
+
|
|
216
|
+
// Create Money object
|
|
217
|
+
let currency = SquareMobilePaymentsHelper.convertToCurrency(params.amountMoney.currency)
|
|
218
|
+
let money = SquareMobilePaymentsSDK.Money(amount: UInt(params.amountMoney.amount), currency: currency)
|
|
219
|
+
|
|
220
|
+
// Create PaymentParameters
|
|
221
|
+
let processingMode = SquareMobilePaymentsHelper.convertToProcessingMode(params.processingMode)
|
|
222
|
+
let paymentParams = SquareMobilePaymentsSDK.PaymentParameters(
|
|
223
|
+
paymentAttemptID: params.paymentAttemptId,
|
|
224
|
+
amountMoney: money,
|
|
225
|
+
processingMode: processingMode
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
// Set optional parameters
|
|
229
|
+
if let referenceId = params.referenceId {
|
|
230
|
+
paymentParams.referenceID = referenceId
|
|
231
|
+
}
|
|
232
|
+
if let note = params.note {
|
|
233
|
+
paymentParams.note = note
|
|
234
|
+
}
|
|
235
|
+
if let orderId = params.orderId {
|
|
236
|
+
paymentParams.orderID = orderId
|
|
237
|
+
}
|
|
238
|
+
if let tipMoney = params.tipMoney {
|
|
239
|
+
let tipCurrency = SquareMobilePaymentsHelper.convertToCurrency(tipMoney.currency)
|
|
240
|
+
paymentParams.tipMoney = SquareMobilePaymentsSDK.Money(amount: UInt(tipMoney.amount), currency: tipCurrency)
|
|
241
|
+
}
|
|
242
|
+
if let applicationFee = params.applicationFee {
|
|
243
|
+
let feeCurrency = SquareMobilePaymentsHelper.convertToCurrency(applicationFee.currency)
|
|
244
|
+
paymentParams.appFeeMoney = SquareMobilePaymentsSDK.Money(amount: UInt(applicationFee.amount), currency: feeCurrency)
|
|
245
|
+
}
|
|
246
|
+
if let autocomplete = params.autocomplete {
|
|
247
|
+
paymentParams.autocomplete = autocomplete
|
|
248
|
+
}
|
|
249
|
+
if let delayDuration = params.delayDuration {
|
|
250
|
+
// Parse ISO 8601 duration string (e.g., "PT1H" = 1 hour = 3600 seconds)
|
|
251
|
+
paymentParams.delayDuration = parseISO8601Duration(delayDuration)
|
|
252
|
+
}
|
|
253
|
+
if let delayAction = params.delayAction,
|
|
254
|
+
let action = SquareMobilePaymentsHelper.convertToDelayAction(delayAction) {
|
|
255
|
+
paymentParams.delayAction = action
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Create PromptParameters
|
|
259
|
+
let mode = SquareMobilePaymentsHelper.convertToPromptMode(promptParams.mode)
|
|
260
|
+
let additionalMethods = SquareMobilePaymentsHelper.convertToAdditionalMethods(promptParams.additionalMethods)
|
|
261
|
+
let squarePromptParams = SquareMobilePaymentsSDK.PromptParameters(
|
|
262
|
+
mode: mode,
|
|
263
|
+
additionalMethods: additionalMethods
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
// Start payment
|
|
267
|
+
paymentHandle = MobilePaymentsSDK.shared.paymentManager.startPayment(
|
|
268
|
+
paymentParams,
|
|
269
|
+
promptParameters: squarePromptParams,
|
|
270
|
+
from: viewController,
|
|
271
|
+
delegate: self
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
completion(nil)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@objc public func cancelPayment(completion: @escaping (_ error: Error?) -> Void) throws {
|
|
278
|
+
guard locationId != nil else {
|
|
279
|
+
throw CustomError.notInitialized
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
guard let handle = paymentHandle else {
|
|
283
|
+
throw CustomError.noPaymentInProgress
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if handle.isPaymentCancelable {
|
|
287
|
+
handle.cancelPayment()
|
|
288
|
+
completion(nil)
|
|
289
|
+
} else {
|
|
290
|
+
completion(NSError(domain: "SquareMobilePayments", code: -1, userInfo: [NSLocalizedDescriptionKey: "Payment cannot be canceled at this time"]))
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@objc public func getAvailableCardInputMethods(completion: @escaping (_ result: GetAvailableCardInputMethodsResult?, _ error: Error?) -> Void) throws {
|
|
295
|
+
guard locationId != nil else {
|
|
296
|
+
throw CustomError.notInitialized
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let methods = MobilePaymentsSDK.shared.paymentManager.availableCardInputMethods
|
|
300
|
+
let cardInputMethods = SquareMobilePaymentsHelper.convertCardInputMethods(methods)
|
|
301
|
+
|
|
302
|
+
let result = GetAvailableCardInputMethodsResult(cardInputMethods: cardInputMethods)
|
|
303
|
+
completion(result, nil)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// MARK: - Helper Methods
|
|
307
|
+
|
|
308
|
+
private func convertSdkReaderToReaderInfo(_ sdkReader: SquareMobilePaymentsSDK.ReaderInfo) -> ReaderInfo {
|
|
309
|
+
let serialNumber = sdkReader.serialNumber ?? ""
|
|
310
|
+
let model = SquareMobilePaymentsHelper.convertReaderModel(sdkReader.model)
|
|
311
|
+
let status = SquareMobilePaymentsHelper.convertReaderStatus(sdkReader.statusInfo.status)
|
|
312
|
+
let firmwareVersion = sdkReader.firmwareInfo?.version
|
|
313
|
+
let batteryLevel = sdkReader.batteryStatus?.percentage != nil ? Int(sdkReader.batteryStatus!.percentage) : nil
|
|
314
|
+
let isCharging = sdkReader.batteryStatus?.isCharging
|
|
315
|
+
let supportedCardInputMethods = SquareMobilePaymentsHelper.convertCardInputMethods(sdkReader.supportedInputMethods)
|
|
316
|
+
|
|
317
|
+
var unavailableReasonInfo: UnavailableReasonInfo?
|
|
318
|
+
if let reasonInfo = sdkReader.statusInfo.unavailableReasonInfo {
|
|
319
|
+
let reason = SquareMobilePaymentsHelper.convertUnavailableReason(reasonInfo.reason)
|
|
320
|
+
let message = reasonInfo.title
|
|
321
|
+
unavailableReasonInfo = UnavailableReasonInfo(reason: reason, message: message)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return ReaderInfo(
|
|
325
|
+
serialNumber: serialNumber,
|
|
326
|
+
model: model,
|
|
327
|
+
status: status,
|
|
328
|
+
firmwareVersion: firmwareVersion,
|
|
329
|
+
batteryLevel: batteryLevel,
|
|
330
|
+
isCharging: isCharging,
|
|
331
|
+
supportedCardInputMethods: supportedCardInputMethods,
|
|
332
|
+
unavailableReasonInfo: unavailableReasonInfo
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
private func convertSdkPaymentToPayment(_ sdkPayment: SquareMobilePaymentsSDK.Payment) -> Payment {
|
|
337
|
+
let id: String?
|
|
338
|
+
let status: String
|
|
339
|
+
var cardDetails: CardPaymentDetails?
|
|
340
|
+
|
|
341
|
+
// Handle OnlinePayment vs OfflinePayment
|
|
342
|
+
if let onlinePayment = sdkPayment as? SquareMobilePaymentsSDK.OnlinePayment {
|
|
343
|
+
id = onlinePayment.id
|
|
344
|
+
status = SquareMobilePaymentsHelper.convertPaymentStatus(onlinePayment.status)
|
|
345
|
+
|
|
346
|
+
if let details = onlinePayment.cardDetails {
|
|
347
|
+
if let cardInfo = details.card {
|
|
348
|
+
let card = Card(
|
|
349
|
+
brand: SquareMobilePaymentsHelper.convertCardBrand(cardInfo.cardBrand),
|
|
350
|
+
lastFourDigits: cardInfo.last4 ?? "",
|
|
351
|
+
cardholderName: cardInfo.cardholderName,
|
|
352
|
+
expirationMonth: Int(cardInfo.expMonth),
|
|
353
|
+
expirationYear: Int(cardInfo.expYear)
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
cardDetails = CardPaymentDetails(
|
|
357
|
+
card: card,
|
|
358
|
+
entryMethod: SquareMobilePaymentsHelper.convertCardInputMethodFromString(nil),
|
|
359
|
+
authorizationCode: details.authResultCode,
|
|
360
|
+
applicationName: details.applicationName,
|
|
361
|
+
applicationId: details.applicationIdentifier
|
|
362
|
+
)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
} else if let offlinePayment = sdkPayment as? SquareMobilePaymentsSDK.OfflinePayment {
|
|
366
|
+
id = offlinePayment.id
|
|
367
|
+
// OfflineStatus is different, map to our PaymentStatus
|
|
368
|
+
switch offlinePayment.status {
|
|
369
|
+
case .queued: status = "PENDING"
|
|
370
|
+
case .uploaded: status = "PENDING"
|
|
371
|
+
case .processed: status = "COMPLETED"
|
|
372
|
+
case .failedToUpload: status = "FAILED"
|
|
373
|
+
case .failedToProcess: status = "FAILED"
|
|
374
|
+
case .unknown: status = "PENDING"
|
|
375
|
+
@unknown default: status = "PENDING"
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Note: OfflinePayment has OfflineCardPaymentDetails, which may have a different structure
|
|
379
|
+
// For now, we'll skip card details for offline payments
|
|
380
|
+
} else {
|
|
381
|
+
id = nil
|
|
382
|
+
status = "PENDING"
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
let type = SquareMobilePaymentsHelper.convertPaymentType(sdkPayment)
|
|
386
|
+
|
|
387
|
+
let amountMoney = MoneyResult(
|
|
388
|
+
amount: Int(sdkPayment.totalMoney.amount),
|
|
389
|
+
currency: getCurrencyString(sdkPayment.totalMoney.currency)
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
var tipMoney: MoneyResult?
|
|
393
|
+
if let tip = sdkPayment.tipMoney {
|
|
394
|
+
tipMoney = MoneyResult(amount: Int(tip.amount), currency: getCurrencyString(tip.currency))
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
var applicationFee: MoneyResult?
|
|
398
|
+
if let fee = sdkPayment.appFeeMoney {
|
|
399
|
+
applicationFee = MoneyResult(amount: Int(fee.amount), currency: getCurrencyString(fee.currency))
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
let referenceId = sdkPayment.referenceID
|
|
403
|
+
let orderId = sdkPayment.orderID
|
|
404
|
+
|
|
405
|
+
let createdAt = sdkPayment.createdAt.iso8601String
|
|
406
|
+
let updatedAt = sdkPayment.updatedAt.iso8601String
|
|
407
|
+
|
|
408
|
+
return Payment(
|
|
409
|
+
id: id,
|
|
410
|
+
type: type,
|
|
411
|
+
status: status,
|
|
412
|
+
amountMoney: amountMoney,
|
|
413
|
+
tipMoney: tipMoney,
|
|
414
|
+
applicationFee: applicationFee,
|
|
415
|
+
referenceId: referenceId,
|
|
416
|
+
orderId: orderId,
|
|
417
|
+
cardDetails: cardDetails,
|
|
418
|
+
createdAt: createdAt,
|
|
419
|
+
updatedAt: updatedAt
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// MARK: - Helper Functions
|
|
424
|
+
|
|
425
|
+
private func getCurrencyString(_ currency: SquareMobilePaymentsSDK.Currency) -> String {
|
|
426
|
+
switch currency {
|
|
427
|
+
case .USD: return "USD"
|
|
428
|
+
case .CAD: return "CAD"
|
|
429
|
+
case .AUD: return "AUD"
|
|
430
|
+
case .GBP: return "GBP"
|
|
431
|
+
case .EUR: return "EUR"
|
|
432
|
+
case .JPY: return "JPY"
|
|
433
|
+
@unknown default: return "USD"
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
private func parseISO8601Duration(_ duration: String) -> TimeInterval {
|
|
438
|
+
// Simple parser for ISO 8601 durations (e.g., "PT1H" = 1 hour)
|
|
439
|
+
// Format: P[n]Y[n]M[n]DT[n]H[n]M[n]S
|
|
440
|
+
var seconds: TimeInterval = 0
|
|
441
|
+
|
|
442
|
+
let pattern = "PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?"
|
|
443
|
+
if let regex = try? NSRegularExpression(pattern: pattern, options: []),
|
|
444
|
+
let match = regex.firstMatch(in: duration, options: [], range: NSRange(duration.startIndex..., in: duration)) {
|
|
445
|
+
|
|
446
|
+
if let hoursRange = Range(match.range(at: 1), in: duration),
|
|
447
|
+
let hours = Double(duration[hoursRange]) {
|
|
448
|
+
seconds += hours * 3600
|
|
449
|
+
}
|
|
450
|
+
if let minutesRange = Range(match.range(at: 2), in: duration),
|
|
451
|
+
let minutes = Double(duration[minutesRange]) {
|
|
452
|
+
seconds += minutes * 60
|
|
453
|
+
}
|
|
454
|
+
if let secondsRange = Range(match.range(at: 3), in: duration),
|
|
455
|
+
let secs = Double(duration[secondsRange]) {
|
|
456
|
+
seconds += secs
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return seconds > 0 ? seconds : 60 // Default to 60 seconds minimum
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// MARK: - ReaderPairingDelegate
|
|
465
|
+
|
|
466
|
+
extension SquareMobilePayments: ReaderPairingDelegate {
|
|
467
|
+
public func readerPairingDidBegin() {
|
|
468
|
+
plugin?.notifyListeners("readerPairingDidBegin", data: [:])
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
public func readerPairingDidSucceed() {
|
|
472
|
+
pairingHandle = nil
|
|
473
|
+
plugin?.notifyListeners("readerPairingDidSucceed", data: [:])
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
public func readerPairingDidFail(with error: Error) {
|
|
477
|
+
pairingHandle = nil
|
|
478
|
+
var data: [String: Any] = ["message": error.localizedDescription]
|
|
479
|
+
if let nsError = error as NSError? {
|
|
480
|
+
data["code"] = nsError.domain
|
|
481
|
+
}
|
|
482
|
+
plugin?.notifyListeners("readerPairingDidFail", data: data)
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// MARK: - ReaderObserver
|
|
487
|
+
|
|
488
|
+
extension SquareMobilePayments: ReaderObserver {
|
|
489
|
+
public func readerWasAdded(_ readerInfo: SquareMobilePaymentsSDK.ReaderInfo) {
|
|
490
|
+
let reader = convertSdkReaderToReaderInfo(readerInfo)
|
|
491
|
+
if let data = reader.toJSObject() as? JSObject {
|
|
492
|
+
plugin?.notifyListeners("readerWasAdded", data: ["reader": data])
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
public func readerWasRemoved(_ readerInfo: SquareMobilePaymentsSDK.ReaderInfo) {
|
|
497
|
+
let reader = convertSdkReaderToReaderInfo(readerInfo)
|
|
498
|
+
if let data = reader.toJSObject() as? JSObject {
|
|
499
|
+
plugin?.notifyListeners("readerWasRemoved", data: ["reader": data])
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public func readerDidChange(_ readerInfo: SquareMobilePaymentsSDK.ReaderInfo, change: SquareMobilePaymentsSDK.ReaderChange) {
|
|
504
|
+
let reader = convertSdkReaderToReaderInfo(readerInfo)
|
|
505
|
+
let changeStr = SquareMobilePaymentsHelper.convertReaderChange(change)
|
|
506
|
+
if let data = reader.toJSObject() as? JSObject {
|
|
507
|
+
plugin?.notifyListeners("readerDidChange", data: ["reader": data, "change": changeStr])
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// MARK: - AvailableCardInputMethodsObserver
|
|
513
|
+
|
|
514
|
+
extension SquareMobilePayments: AvailableCardInputMethodsObserver {
|
|
515
|
+
public func availableCardInputMethodsDidChange(_ cardInputMethods: SquareMobilePaymentsSDK.CardInputMethods) {
|
|
516
|
+
let methods = SquareMobilePaymentsHelper.convertCardInputMethods(cardInputMethods)
|
|
517
|
+
plugin?.notifyListeners("availableCardInputMethodsDidChange", data: ["cardInputMethods": methods])
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// MARK: - PaymentManagerDelegate
|
|
522
|
+
|
|
523
|
+
extension SquareMobilePayments: PaymentManagerDelegate {
|
|
524
|
+
public func paymentManager(_ paymentManager: SquareMobilePaymentsSDK.PaymentManager, didFinish payment: SquareMobilePaymentsSDK.Payment) {
|
|
525
|
+
paymentHandle = nil
|
|
526
|
+
let paymentResult = convertSdkPaymentToPayment(payment)
|
|
527
|
+
if let data = paymentResult.toJSObject() as? JSObject {
|
|
528
|
+
plugin?.notifyListeners("paymentDidFinish", data: ["payment": data])
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
public func paymentManager(_ paymentManager: SquareMobilePaymentsSDK.PaymentManager, didFail payment: SquareMobilePaymentsSDK.Payment, withError error: Error) {
|
|
533
|
+
paymentHandle = nil
|
|
534
|
+
let paymentResult = convertSdkPaymentToPayment(payment)
|
|
535
|
+
var data: [String: Any] = ["message": error.localizedDescription]
|
|
536
|
+
if let paymentData = paymentResult.toJSObject() as? JSObject {
|
|
537
|
+
data["payment"] = paymentData
|
|
538
|
+
}
|
|
539
|
+
if let nsError = error as NSError? {
|
|
540
|
+
data["code"] = nsError.domain
|
|
541
|
+
}
|
|
542
|
+
plugin?.notifyListeners("paymentDidFail", data: data)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
public func paymentManager(_ paymentManager: SquareMobilePaymentsSDK.PaymentManager, didCancel payment: SquareMobilePaymentsSDK.Payment) {
|
|
546
|
+
paymentHandle = nil
|
|
547
|
+
let paymentResult = convertSdkPaymentToPayment(payment)
|
|
548
|
+
var data: [String: Any] = [:]
|
|
549
|
+
if let paymentData = paymentResult.toJSObject() as? JSObject {
|
|
550
|
+
data["payment"] = paymentData
|
|
551
|
+
}
|
|
552
|
+
plugin?.notifyListeners("paymentDidCancel", data: data)
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// MARK: - Permission Methods
|
|
556
|
+
|
|
557
|
+
@objc public func checkLocationPermission() -> CLAuthorizationStatus {
|
|
558
|
+
if #available(iOS 14.0, *) {
|
|
559
|
+
if locationManager == nil {
|
|
560
|
+
locationManager = CLLocationManager()
|
|
561
|
+
locationManager?.delegate = self
|
|
562
|
+
}
|
|
563
|
+
return locationManager?.authorizationStatus ?? .notDetermined
|
|
564
|
+
} else {
|
|
565
|
+
return CLLocationManager.authorizationStatus()
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
@objc public func requestLocationPermission(completion: @escaping (CLAuthorizationStatus) -> Void) {
|
|
570
|
+
if locationManager == nil {
|
|
571
|
+
locationManager = CLLocationManager()
|
|
572
|
+
locationManager?.delegate = self
|
|
573
|
+
}
|
|
574
|
+
locationPermissionCompletion = completion
|
|
575
|
+
locationManager?.requestWhenInUseAuthorization()
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
@objc public func checkBluetoothPermission() -> CBManagerAuthorization {
|
|
579
|
+
if #available(iOS 13.1, *) {
|
|
580
|
+
return CBCentralManager.authorization
|
|
581
|
+
} else {
|
|
582
|
+
return .allowedAlways
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
@objc public func requestBluetoothPermission(completion: @escaping () -> Void) {
|
|
587
|
+
guard CBCentralManager.authorization == .notDetermined else {
|
|
588
|
+
completion()
|
|
589
|
+
return
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
bluetoothPermissionCompletion = completion
|
|
593
|
+
bluetoothManager = CBCentralManager(
|
|
594
|
+
delegate: self,
|
|
595
|
+
queue: .main,
|
|
596
|
+
options: nil
|
|
597
|
+
)
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// MARK: - CLLocationManagerDelegate
|
|
602
|
+
|
|
603
|
+
extension SquareMobilePayments: CLLocationManagerDelegate {
|
|
604
|
+
public func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
605
|
+
let status: CLAuthorizationStatus
|
|
606
|
+
if #available(iOS 14.0, *) {
|
|
607
|
+
status = manager.authorizationStatus
|
|
608
|
+
} else {
|
|
609
|
+
status = CLLocationManager.authorizationStatus()
|
|
610
|
+
}
|
|
611
|
+
locationPermissionCompletion?(status)
|
|
612
|
+
locationPermissionCompletion = nil
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// MARK: - CBCentralManagerDelegate
|
|
617
|
+
|
|
618
|
+
extension SquareMobilePayments: CBCentralManagerDelegate {
|
|
619
|
+
public func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
620
|
+
bluetoothPermissionCompletion?()
|
|
621
|
+
bluetoothPermissionCompletion = nil
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// MARK: - Date Extension
|
|
626
|
+
|
|
627
|
+
extension Date {
|
|
628
|
+
var iso8601String: String {
|
|
629
|
+
let formatter = ISO8601DateFormatter()
|
|
630
|
+
return formatter.string(from: self)
|
|
631
|
+
}
|
|
632
|
+
}
|