@tapayadot/accept-react-native 1.3.2 → 1.14.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/README.md +196 -363
- package/android/build.gradle +23 -34
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/AcceptSdkReactNativeModule.kt +191 -673
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/Errors.kt +81 -0
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/Parsing.kt +166 -0
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/Serialization.kt +216 -0
- package/app.json +2 -2
- package/app.plugin.js +1 -1
- package/build/Accept.d.ts +255 -0
- package/build/Accept.d.ts.map +1 -0
- package/build/Accept.js +387 -0
- package/build/Accept.js.map +1 -0
- package/build/Accept.types.d.ts +352 -0
- package/build/Accept.types.d.ts.map +1 -0
- package/build/Accept.types.js +9 -0
- package/build/Accept.types.js.map +1 -0
- package/build/AcceptError.d.ts +53 -0
- package/build/AcceptError.d.ts.map +1 -0
- package/build/AcceptError.js +107 -0
- package/build/AcceptError.js.map +1 -0
- package/build/AcceptSdkReactNativeModule.d.ts +67 -26
- package/build/AcceptSdkReactNativeModule.d.ts.map +1 -1
- package/build/AcceptSdkReactNativeModule.js +53 -3
- package/build/AcceptSdkReactNativeModule.js.map +1 -1
- package/build/index.d.ts +7 -237
- package/build/index.d.ts.map +1 -1
- package/build/index.js +7 -254
- package/build/index.js.map +1 -1
- package/build/utils.d.ts.map +1 -1
- package/build/utils.js +2 -2
- package/build/utils.js.map +1 -1
- package/expo-module.config.json +1 -6
- package/package.json +8 -12
- package/plugin/withAcceptSdk.js +45 -0
- package/build/AcceptSdkReactNative.types.d.ts +0 -259
- package/build/AcceptSdkReactNative.types.d.ts.map +0 -1
- package/build/AcceptSdkReactNative.types.js +0 -2
- package/build/AcceptSdkReactNative.types.js.map +0 -1
- package/ios/.xcode.env +0 -11
- package/ios/AcceptSdkReactNative.podspec +0 -33
- package/ios/AcceptSdkReactNativeAppDelegate.swift +0 -13
- package/ios/AcceptSdkReactNativeModule.swift +0 -749
- package/ios/Podfile +0 -63
- package/ios/Podfile.properties.json +0 -4
- package/ios/acceptsdkreactnative.xcodeproj/project.pbxproj +0 -540
- package/ios/acceptsdkreactnative.xcodeproj/xcshareddata/xcschemes/acceptsdkreactnative.xcscheme +0 -88
- package/plugin/withCustomRepoModule.js +0 -96
|
@@ -1,749 +0,0 @@
|
|
|
1
|
-
import AcceptSDK
|
|
2
|
-
@_spi(AcceptDemo) import AcceptSDK
|
|
3
|
-
import CoreLocation
|
|
4
|
-
import ExpoModulesCore
|
|
5
|
-
import UIKit
|
|
6
|
-
|
|
7
|
-
// MARK: - Records
|
|
8
|
-
|
|
9
|
-
final class CardPaymentIntentRecord: Record {
|
|
10
|
-
@Field var paymentIntentId: String = ""
|
|
11
|
-
@Field var amount: Int = 0
|
|
12
|
-
@Field var requestedCurrency: String = ""
|
|
13
|
-
@Field var settlementCurrency: String? = nil
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
final class SepaPaymentIntentRecord: Record {
|
|
17
|
-
@Field var paymentIntentId: String = ""
|
|
18
|
-
@Field var amount: Int = 0
|
|
19
|
-
@Field var requestedCurrency: String = ""
|
|
20
|
-
@Field var settlementCurrency: String? = nil
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
final class CertisPaymentIntentRecord: Record {
|
|
24
|
-
@Field var paymentIntentId: String = ""
|
|
25
|
-
@Field var amount: Int = 0
|
|
26
|
-
@Field var requestedCurrency: String = ""
|
|
27
|
-
@Field var settlementCurrency: String? = nil
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
final class CardPaymentResultRecord: Record {
|
|
31
|
-
@Field var status: String = ""
|
|
32
|
-
@Field var last4: String? = nil
|
|
33
|
-
@Field var companyName: String = ""
|
|
34
|
-
@Field var companyAddress1: String = ""
|
|
35
|
-
@Field var companyAddress2: String? = nil
|
|
36
|
-
@Field var companyCity: String = ""
|
|
37
|
-
@Field var companyCountry: String = ""
|
|
38
|
-
@Field var terminalId: String = ""
|
|
39
|
-
@Field var authorizationCode: String? = nil
|
|
40
|
-
@Field var brand: String? = nil
|
|
41
|
-
@Field var reason: String? = nil
|
|
42
|
-
@Field var receiptUrl: String? = nil
|
|
43
|
-
@Field var refundToken: String? = nil
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
final class RefundIntentRecord: Record {
|
|
47
|
-
@Field var paymentToken: String = ""
|
|
48
|
-
@Field var refundToken: String? = nil
|
|
49
|
-
@Field var reason: String = "customerRequest"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
final class RefundResultRecord: Record {
|
|
53
|
-
@Field var refundToken: String? = nil
|
|
54
|
-
@Field var status: String = ""
|
|
55
|
-
@Field var paymentMethod: String? = nil
|
|
56
|
-
@Field var requestedAmount: Int? = nil
|
|
57
|
-
@Field var requestedCurrency: String? = nil
|
|
58
|
-
@Field var settlementAmount: Int? = nil
|
|
59
|
-
@Field var settlementCurrency: String? = nil
|
|
60
|
-
@Field var fxRate: Double? = nil
|
|
61
|
-
@Field var refundReason: String = ""
|
|
62
|
-
@Field var createdAt: String? = nil
|
|
63
|
-
@Field var processedAt: String? = nil
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
final class BankTransferPaymentResultRecord: Record {
|
|
67
|
-
@Field var status: String = ""
|
|
68
|
-
@Field var postponed: Bool = false
|
|
69
|
-
@Field var receivedAt: String? = nil
|
|
70
|
-
@Field var receivedFromIban: String? = nil
|
|
71
|
-
@Field var receiptUrl: String? = nil
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
final class GradientColorsRecord: Record {
|
|
75
|
-
@Field var start: String = ""
|
|
76
|
-
@Field var end: String = ""
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
final class AcceptColorThemeRecord: Record {
|
|
80
|
-
@Field var accent: String = ""
|
|
81
|
-
@Field var error: String = ""
|
|
82
|
-
@Field var warning: String = ""
|
|
83
|
-
@Field var success: String = ""
|
|
84
|
-
@Field var brandGradientColors: GradientColorsRecord? = nil
|
|
85
|
-
@Field var brandSubtleGradientColors: GradientColorsRecord? = nil
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
final class AcceptImageThemeRecord: Record {
|
|
89
|
-
@Field var brandLogo: String = ""
|
|
90
|
-
@Field var toolbarLogo: String = ""
|
|
91
|
-
@Field var solidLogo: String = ""
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
final class AcceptThemeConfigurationRecord: Record {
|
|
95
|
-
@Field var themeId: String? = nil
|
|
96
|
-
@Field var colors: AcceptColorThemeRecord? = nil
|
|
97
|
-
@Field var images: AcceptImageThemeRecord? = nil
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
final class KybPrefillDataRecord: Record {
|
|
101
|
-
@Field var businessType: String? = nil
|
|
102
|
-
@Field var countryCode: String? = nil
|
|
103
|
-
@Field var registrationNumber: String? = nil
|
|
104
|
-
@Field var vatNumber: String? = nil
|
|
105
|
-
@Field var legalName: String? = nil
|
|
106
|
-
@Field var addressLine1: String? = nil
|
|
107
|
-
@Field var addressLine2: String? = nil
|
|
108
|
-
@Field var city: String? = nil
|
|
109
|
-
@Field var postalCode: String? = nil
|
|
110
|
-
@Field var merchantCategoryCode: Int? = nil
|
|
111
|
-
@Field var businessEmail: String? = nil
|
|
112
|
-
@Field var bankAccountIban: String? = nil
|
|
113
|
-
@Field var businessUrl: String? = nil
|
|
114
|
-
@Field var productDescription: String? = nil
|
|
115
|
-
@Field var supportPhone: String? = nil
|
|
116
|
-
|
|
117
|
-
func toKybPrefillData() -> KybPrefillData {
|
|
118
|
-
var data = KybPrefillData()
|
|
119
|
-
data.countryCode = countryCode
|
|
120
|
-
data.registrationNumber = registrationNumber
|
|
121
|
-
data.vatNumber = vatNumber
|
|
122
|
-
data.legalName = legalName
|
|
123
|
-
data.addressLine1 = addressLine1
|
|
124
|
-
data.addressLine2 = addressLine2
|
|
125
|
-
data.city = city
|
|
126
|
-
data.postalCode = postalCode
|
|
127
|
-
data.merchantCategoryCode = merchantCategoryCode
|
|
128
|
-
data.businessEmail = businessEmail
|
|
129
|
-
data.bankAccountIban = bankAccountIban
|
|
130
|
-
data.businessUrl = businessUrl.flatMap { URL(string: $0) }
|
|
131
|
-
data.productDescription = productDescription
|
|
132
|
-
data.supportPhone = supportPhone
|
|
133
|
-
data.businessType = businessType.flatMap { value -> AcceptBusinessType? in
|
|
134
|
-
switch value {
|
|
135
|
-
case "individual": .individual
|
|
136
|
-
case "company": .company
|
|
137
|
-
case "nonProfit": .nonProfit
|
|
138
|
-
case "governmentEntity": .governmentEntity
|
|
139
|
-
default: nil
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return data
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// MARK: - Module
|
|
147
|
-
|
|
148
|
-
public class AcceptSdkReactNativeModule: Module {
|
|
149
|
-
public func definition() -> ModuleDefinition {
|
|
150
|
-
Name("AcceptSdkReactNative")
|
|
151
|
-
|
|
152
|
-
AsyncFunction("initialize") { (demo: Bool, theme: AcceptThemeConfigurationRecord?) async throws in
|
|
153
|
-
do {
|
|
154
|
-
let themeConfig = try theme?.toAcceptThemeConfiguration() ?? .default
|
|
155
|
-
try await Accept.initialize(environment: demo ? .sandbox : .production, theme: themeConfig)
|
|
156
|
-
} catch let error as AcceptSDKError {
|
|
157
|
-
throw error.toException()
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
AsyncFunction("setTheme") { (theme: AcceptThemeConfigurationRecord) async throws in
|
|
162
|
-
do {
|
|
163
|
-
try await Accept.setTheme(try theme.toAcceptThemeConfiguration())
|
|
164
|
-
} catch let error as AcceptSDKError {
|
|
165
|
-
throw error.toException()
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
AsyncFunction("setUiBehavior") { (_: [String: Any]) in
|
|
170
|
-
// No-op on iOS — UI behavior configuration is Android-only.
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
AsyncFunction("authenticate") { (token: String) async throws in
|
|
174
|
-
do {
|
|
175
|
-
try await Accept.authenticate(merchantToken: token)
|
|
176
|
-
} catch let error as AcceptSDKError {
|
|
177
|
-
throw error.toException()
|
|
178
|
-
}
|
|
179
|
-
return true
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
AsyncFunction("getStatus") { () async -> String in
|
|
183
|
-
let status = await Accept.status
|
|
184
|
-
switch status {
|
|
185
|
-
case .idle: return "IDLE"
|
|
186
|
-
case .initialized: return "INITIALIZED"
|
|
187
|
-
case .authenticated: return "LOGGED_IN"
|
|
188
|
-
@unknown default: return "IDLE"
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
AsyncFunction("isPaymentPending") { () async -> Bool in
|
|
193
|
-
await Accept.isPaymentInProgress()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
AsyncFunction("logOut") { () async throws in
|
|
197
|
-
do {
|
|
198
|
-
try await Accept.logout()
|
|
199
|
-
} catch let error as AcceptSDKError {
|
|
200
|
-
throw error.toException()
|
|
201
|
-
}
|
|
202
|
-
return true
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
AsyncFunction("presentKyb") { (prefilling: KybPrefillDataRecord?) async throws in
|
|
206
|
-
let prefillData = prefilling?.toKybPrefillData()
|
|
207
|
-
try await Accept.presentKyb(prefilling: prefillData)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
AsyncFunction("getOnboardingStatus") { () async throws -> [String: Any] in
|
|
211
|
-
do {
|
|
212
|
-
let status = try await Accept.getOnboardingStatus()
|
|
213
|
-
return [
|
|
214
|
-
"isOnboarded": status.isOnboarded,
|
|
215
|
-
"paymentMethods": status.paymentMethods.map { pm in
|
|
216
|
-
[
|
|
217
|
-
"method": pm.method.toJsString(),
|
|
218
|
-
"status": pm.status.toJsString(),
|
|
219
|
-
]
|
|
220
|
-
},
|
|
221
|
-
]
|
|
222
|
-
} catch let error as AcceptSDKError {
|
|
223
|
-
throw error.toException()
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
AsyncFunction("getPaymentMethodStatus") { (method: String) async throws -> String in
|
|
228
|
-
do {
|
|
229
|
-
let status = try await Accept.getPaymentMethodStatus(for: try AcceptPaymentMethod.fromJsString(method))
|
|
230
|
-
return status.toJsString()
|
|
231
|
-
} catch let error as AcceptSDKError {
|
|
232
|
-
throw error.toException()
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
AsyncFunction("requestLocationPermission") { () async throws -> Bool in
|
|
237
|
-
do {
|
|
238
|
-
try await Accept.requestLocationPermission()
|
|
239
|
-
} catch let error as AcceptSDKError {
|
|
240
|
-
throw error.toException()
|
|
241
|
-
}
|
|
242
|
-
return true
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
AsyncFunction("pairWithCompanionApp") { () async throws in
|
|
246
|
-
do {
|
|
247
|
-
try await Accept.pairWithCompanionApp()
|
|
248
|
-
} catch let error as AcceptSDKError {
|
|
249
|
-
throw error.toException()
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
AsyncFunction("isCompanionAppInstalled") { () async -> Bool in
|
|
254
|
-
await MainActor.run { Accept.isCompanionAppInstalled() }
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
AsyncFunction("presentCompanionAppSheet") { () async throws in
|
|
258
|
-
do {
|
|
259
|
-
try await Accept.presentCompanionAppSheet()
|
|
260
|
-
} catch let error as AcceptSDKError {
|
|
261
|
-
throw error.toException()
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
AsyncFunction("getPaymentStatus") { (paymentIntentId: String) async throws -> String in
|
|
266
|
-
do {
|
|
267
|
-
let status = try await Accept.getPaymentStatus(for: paymentIntentId)
|
|
268
|
-
return try InfoResultSerializer.serialize(status)
|
|
269
|
-
} catch let error as AcceptSDKError {
|
|
270
|
-
throw error.toException()
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
AsyncFunction("startCardPayment") { (intentRecord: CardPaymentIntentRecord) async throws -> CardPaymentResultRecord in
|
|
275
|
-
do {
|
|
276
|
-
let outcome = try await Accept.pay(intentRecord.toPaymentIntent())
|
|
277
|
-
return outcome.toCardResult()
|
|
278
|
-
} catch let error as AcceptSDKError {
|
|
279
|
-
throw error.toException()
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
AsyncFunction("startSepaPayment") { (intentRecord: SepaPaymentIntentRecord) async throws -> BankTransferPaymentResultRecord in
|
|
284
|
-
do {
|
|
285
|
-
let outcome = try await Accept.pay(intentRecord.toPaymentIntent())
|
|
286
|
-
return outcome.toBankTransferResult()
|
|
287
|
-
} catch let error as AcceptSDKError {
|
|
288
|
-
throw error.toException()
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
AsyncFunction("startCertisPayment") { (intentRecord: CertisPaymentIntentRecord) async throws -> BankTransferPaymentResultRecord in
|
|
293
|
-
do {
|
|
294
|
-
let outcome = try await Accept.pay(intentRecord.toPaymentIntent())
|
|
295
|
-
return outcome.toBankTransferResult()
|
|
296
|
-
} catch let error as AcceptSDKError {
|
|
297
|
-
throw error.toException()
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
AsyncFunction("refund") { (intent: RefundIntentRecord) async throws -> RefundResultRecord in
|
|
302
|
-
do {
|
|
303
|
-
let refund = try await Accept.refund(
|
|
304
|
-
paymentToken: intent.paymentToken,
|
|
305
|
-
refundToken: intent.refundToken,
|
|
306
|
-
reason: try AcceptRefundReason.fromJsString(intent.reason)
|
|
307
|
-
)
|
|
308
|
-
return refund.toRecord()
|
|
309
|
-
} catch let error as AcceptSDKError {
|
|
310
|
-
throw error.toException()
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
AsyncFunction("cancelActivePayment") { () async throws in
|
|
315
|
-
do {
|
|
316
|
-
try await MainActor.run { try Accept.cancelActivePayment() }
|
|
317
|
-
} catch let error as AcceptSDKError {
|
|
318
|
-
throw error.toException()
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
AsyncFunction("enableDemoMode") { () async in
|
|
323
|
-
await Accept.enableDemoMode()
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
AsyncFunction("disableDemoMode") { () async in
|
|
327
|
-
await Accept.disableDemoMode()
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
AsyncFunction("isDemoMode") { () async -> Bool in
|
|
331
|
-
return await MainActor.run { Accept.isDemoMode }
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// MARK: - Theme conversion
|
|
337
|
-
|
|
338
|
-
private extension AcceptThemeConfigurationRecord {
|
|
339
|
-
func toAcceptThemeConfiguration() throws -> AcceptThemeConfiguration {
|
|
340
|
-
if let id = themeId {
|
|
341
|
-
return .byId(id)
|
|
342
|
-
}
|
|
343
|
-
var config = AcceptThemeConfiguration()
|
|
344
|
-
if let colorsRecord = colors {
|
|
345
|
-
config.colors = .local(try colorsRecord.toAcceptColorTheme())
|
|
346
|
-
}
|
|
347
|
-
if let imagesRecord = images {
|
|
348
|
-
config.images = .local(try imagesRecord.toAcceptImageTheme())
|
|
349
|
-
}
|
|
350
|
-
return config
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
private extension AcceptColorThemeRecord {
|
|
355
|
-
func toAcceptColorTheme() throws -> AcceptColorTheme {
|
|
356
|
-
AcceptColorTheme(
|
|
357
|
-
accent: try color(fromHex: accent),
|
|
358
|
-
error: try color(fromHex: error),
|
|
359
|
-
warning: try color(fromHex: warning),
|
|
360
|
-
success: try color(fromHex: success),
|
|
361
|
-
brandGradientColors: try brandGradientColors.map { GradientColors(start: try color(fromHex: $0.start), end: try color(fromHex: $0.end)) },
|
|
362
|
-
brandSubtleGradientColors: try brandSubtleGradientColors.map { GradientColors(start: try color(fromHex: $0.start), end: try color(fromHex: $0.end)) }
|
|
363
|
-
)
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
private extension AcceptImageThemeRecord {
|
|
368
|
-
func toAcceptImageTheme() throws -> AcceptImageTheme {
|
|
369
|
-
guard
|
|
370
|
-
let brandLogoData = Data(base64Encoded: brandLogo),
|
|
371
|
-
let brandLogoImage = UIImage(data: brandLogoData),
|
|
372
|
-
let toolbarLogoData = Data(base64Encoded: toolbarLogo),
|
|
373
|
-
let toolbarLogoImage = UIImage(data: toolbarLogoData),
|
|
374
|
-
let solidLogoData = Data(base64Encoded: solidLogo),
|
|
375
|
-
let solidLogoImage = UIImage(data: solidLogoData)
|
|
376
|
-
else {
|
|
377
|
-
throw Exception(name: "ThemeError", description: "Invalid base64 image data in AcceptImageTheme")
|
|
378
|
-
}
|
|
379
|
-
return AcceptImageTheme(brandLogo: brandLogoImage, toolbarLogo: toolbarLogoImage, solidLogo: solidLogoImage)
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
private func color(fromHex input: String) throws -> AcceptColor {
|
|
384
|
-
let hex = input.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
|
385
|
-
guard hex.count == 3 || hex.count == 6 || hex.count == 8 else {
|
|
386
|
-
throw Exception(name: "ThemeError", description: "Invalid hex color '\(input)'. Expected #RRGGBB or #AARRGGBB.")
|
|
387
|
-
}
|
|
388
|
-
var int: UInt64 = 0
|
|
389
|
-
guard Scanner(string: hex).scanHexInt64(&int) else {
|
|
390
|
-
throw Exception(name: "ThemeError", description: "Invalid hex color '\(input)'.")
|
|
391
|
-
}
|
|
392
|
-
let a, r, g, b: UInt64
|
|
393
|
-
switch hex.count {
|
|
394
|
-
case 3: (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
|
|
395
|
-
case 6: (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
|
|
396
|
-
case 8: (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
|
|
397
|
-
default: fatalError()
|
|
398
|
-
}
|
|
399
|
-
return AcceptColor(red: Double(r) / 255, green: Double(g) / 255, blue: Double(b) / 255, alpha: Double(a) / 255)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// MARK: - Error mapping
|
|
403
|
-
|
|
404
|
-
private extension AcceptSDKError {
|
|
405
|
-
func toException() -> Exception {
|
|
406
|
-
switch self {
|
|
407
|
-
case .notInitialized:
|
|
408
|
-
return Exception(name: "NotInitialized", description: errorDescription ?? "")
|
|
409
|
-
case .merchantNotAuthenticated:
|
|
410
|
-
return Exception(name: "MerchantNotAuthenticated", description: errorDescription ?? "")
|
|
411
|
-
case .locationPermissionsNotGranted:
|
|
412
|
-
return Exception(name: "LocationPermissionsNotGranted", description: errorDescription ?? "")
|
|
413
|
-
case .companionAppNotInstalled:
|
|
414
|
-
return Exception(name: "CompanionAppNotInstalled", description: errorDescription ?? "")
|
|
415
|
-
case .failedToAuthenticateMerchant:
|
|
416
|
-
return Exception(name: "FailedToAuthenticateMerchant", description: errorDescription ?? "")
|
|
417
|
-
case .failedToPresent:
|
|
418
|
-
return Exception(name: "FailedToPresent", description: errorDescription ?? "")
|
|
419
|
-
case .kybAlreadyInProgress:
|
|
420
|
-
return Exception(name: "KybAlreadyInProgress", description: errorDescription ?? "")
|
|
421
|
-
case .kybAlreadySubmitted:
|
|
422
|
-
return Exception(name: "KybAlreadySubmitted", description: errorDescription ?? "")
|
|
423
|
-
case .paymentAlreadyInProgress:
|
|
424
|
-
return Exception(name: "PaymentAlreadyInProgress", description: errorDescription ?? "")
|
|
425
|
-
case .unexpectedPaymentResult:
|
|
426
|
-
return Exception(name: "UnexpectedPaymentResult", description: errorDescription ?? "")
|
|
427
|
-
case .paymentNotFound:
|
|
428
|
-
return Exception(name: "PaymentNotFound", description: errorDescription ?? "")
|
|
429
|
-
case .refundConflict:
|
|
430
|
-
return Exception(name: "RefundConflict", description: errorDescription ?? "")
|
|
431
|
-
case .merchantOperationFailed:
|
|
432
|
-
return Exception(name: "MerchantOperationFailed", description: errorDescription ?? "")
|
|
433
|
-
case let .amountBelowMinimum(currency, minimum):
|
|
434
|
-
return Exception(name: "AmountBelowMinimum", description: "currency=\(currency) minimum=\(minimum)")
|
|
435
|
-
case let .amountAboveMaximum(currency, maximum):
|
|
436
|
-
return Exception(name: "AmountAboveMaximum", description: "currency=\(currency) maximum=\(maximum)")
|
|
437
|
-
case let .unknownCurrency(code):
|
|
438
|
-
return Exception(name: "UnknownCurrency", description: "code=\(code)")
|
|
439
|
-
case .noActivePayment:
|
|
440
|
-
return Exception(name: "NoActivePayment", description: errorDescription ?? "")
|
|
441
|
-
@unknown default:
|
|
442
|
-
return Exception(name: "AcceptSDKError", description: errorDescription ?? "")
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// MARK: - Info result serialization
|
|
448
|
-
|
|
449
|
-
private struct CardInfoResult: Encodable {
|
|
450
|
-
let status: String
|
|
451
|
-
let readerStatus: String
|
|
452
|
-
let last4: String
|
|
453
|
-
let companyName: String
|
|
454
|
-
let companyAddress1: String
|
|
455
|
-
let companyAddress2: String
|
|
456
|
-
let companyCity: String
|
|
457
|
-
let companyCountry: String
|
|
458
|
-
let terminalId: String
|
|
459
|
-
let authorizationCode: String
|
|
460
|
-
let brand: String
|
|
461
|
-
let reason: String
|
|
462
|
-
let receiptUrl: String?
|
|
463
|
-
let refundToken: String?
|
|
464
|
-
let type: String
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
private struct BankTransferInfoResult: Encodable {
|
|
468
|
-
let status: String
|
|
469
|
-
let postponed: Bool
|
|
470
|
-
let receivedAt: String
|
|
471
|
-
let receivedFromIban: String
|
|
472
|
-
let receiptUrl: String?
|
|
473
|
-
let type: String
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
private enum InfoResultSerializer {
|
|
477
|
-
static func serialize(_ status: any PaymentStatus) throws -> String {
|
|
478
|
-
let encoder = JSONEncoder()
|
|
479
|
-
let data: Data
|
|
480
|
-
|
|
481
|
-
switch status.paymentMethod {
|
|
482
|
-
case .card:
|
|
483
|
-
guard let cardStatus = status as? CardPaymentStatus else {
|
|
484
|
-
throw Exception(name: "SerializationError", description: "Unexpected card status type")
|
|
485
|
-
}
|
|
486
|
-
data = try encoder.encode(CardInfoResult(
|
|
487
|
-
status: cardStatus.status.rnString,
|
|
488
|
-
readerStatus: "",
|
|
489
|
-
last4: cardStatus.details?.last4 ?? "",
|
|
490
|
-
companyName: cardStatus.merchantDetails.legalName,
|
|
491
|
-
companyAddress1: cardStatus.merchantDetails.addressLine1,
|
|
492
|
-
companyAddress2: cardStatus.merchantDetails.addressLine2 ?? "",
|
|
493
|
-
companyCity: cardStatus.merchantDetails.city,
|
|
494
|
-
companyCountry: cardStatus.merchantDetails.country,
|
|
495
|
-
terminalId: cardStatus.terminalId,
|
|
496
|
-
authorizationCode: cardStatus.details?.authorizationCode ?? "",
|
|
497
|
-
brand: cardStatus.details?.brand.rawValue.uppercased() ?? "",
|
|
498
|
-
reason: cardStatus.details?.issuerDeclineReason?.rawValue ?? "",
|
|
499
|
-
receiptUrl: cardStatus.receiptUrl?.absoluteString,
|
|
500
|
-
refundToken: cardStatus.refund?.refundToken,
|
|
501
|
-
type: "card"
|
|
502
|
-
))
|
|
503
|
-
|
|
504
|
-
case .sepaIct:
|
|
505
|
-
guard let bankStatus = status as? BankTransferPaymentStatus else {
|
|
506
|
-
throw Exception(name: "SerializationError", description: "Unexpected bank transfer status type")
|
|
507
|
-
}
|
|
508
|
-
data = try encoder.encode(BankTransferInfoResult(
|
|
509
|
-
status: bankStatus.status.rnString,
|
|
510
|
-
postponed: bankStatus.details?.postponed ?? false,
|
|
511
|
-
receivedAt: bankStatus.processedAt.map { ISO8601DateFormatter().string(from: $0) } ?? "",
|
|
512
|
-
receivedFromIban: bankStatus.details?.bankAccountNumber ?? "",
|
|
513
|
-
receiptUrl: bankStatus.receiptUrl?.absoluteString,
|
|
514
|
-
type: "sepa"
|
|
515
|
-
))
|
|
516
|
-
|
|
517
|
-
case .certisCz:
|
|
518
|
-
guard let bankStatus = status as? BankTransferPaymentStatus else {
|
|
519
|
-
throw Exception(name: "SerializationError", description: "Unexpected bank transfer status type")
|
|
520
|
-
}
|
|
521
|
-
data = try encoder.encode(BankTransferInfoResult(
|
|
522
|
-
status: bankStatus.status.rnString,
|
|
523
|
-
postponed: bankStatus.details?.postponed ?? false,
|
|
524
|
-
receivedAt: bankStatus.processedAt.map { ISO8601DateFormatter().string(from: $0) } ?? "",
|
|
525
|
-
receivedFromIban: bankStatus.details?.bankAccountNumber ?? "",
|
|
526
|
-
receiptUrl: bankStatus.receiptUrl?.absoluteString,
|
|
527
|
-
type: "certis"
|
|
528
|
-
))
|
|
529
|
-
|
|
530
|
-
default:
|
|
531
|
-
throw Exception(name: "UnsupportedPaymentMethod", description: "Payment method not supported by info()")
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
return String(data: data, encoding: .utf8) ?? "{}"
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
private extension AcceptTransactionStatus {
|
|
539
|
-
var rnString: String {
|
|
540
|
-
switch self {
|
|
541
|
-
case .pending: "PENDING"
|
|
542
|
-
case .success: "APPROVED"
|
|
543
|
-
case .cancelled: "ABORTED"
|
|
544
|
-
case .refunded: "REFUNDED"
|
|
545
|
-
case .failed: "DECLINED"
|
|
546
|
-
case .actionNeeded: "PENDING"
|
|
547
|
-
@unknown default: "PENDING"
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
var cardPaymentStatus: String {
|
|
552
|
-
switch self {
|
|
553
|
-
case .pending: "pending"
|
|
554
|
-
case .success: "approved"
|
|
555
|
-
case .cancelled: "aborted"
|
|
556
|
-
case .refunded: "refunded"
|
|
557
|
-
case .failed: "declined"
|
|
558
|
-
case .actionNeeded: "pending"
|
|
559
|
-
@unknown default: "pending"
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
var bankTransferStatus: String {
|
|
564
|
-
switch self {
|
|
565
|
-
case .pending: "pending"
|
|
566
|
-
case .success: "verified"
|
|
567
|
-
case .cancelled: "aborted"
|
|
568
|
-
case .refunded: "refunded"
|
|
569
|
-
case .failed: "declined"
|
|
570
|
-
case .actionNeeded: "pending"
|
|
571
|
-
@unknown default: "pending"
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// MARK: - Payment intent conversion
|
|
577
|
-
|
|
578
|
-
private extension CardPaymentIntentRecord {
|
|
579
|
-
func toPaymentIntent() -> AcceptCardPaymentIntent {
|
|
580
|
-
AcceptCardPaymentIntent(
|
|
581
|
-
id: paymentIntentId,
|
|
582
|
-
amount: amount,
|
|
583
|
-
requestedCurrency: requestedCurrency,
|
|
584
|
-
settlementCurrency: settlementCurrency ?? requestedCurrency
|
|
585
|
-
)
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
private extension SepaPaymentIntentRecord {
|
|
590
|
-
func toPaymentIntent() -> AcceptSepaPaymentIntent {
|
|
591
|
-
AcceptSepaPaymentIntent(
|
|
592
|
-
id: paymentIntentId,
|
|
593
|
-
amount: amount,
|
|
594
|
-
requestedCurrency: requestedCurrency,
|
|
595
|
-
settlementCurrency: settlementCurrency ?? requestedCurrency
|
|
596
|
-
)
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
private extension CertisPaymentIntentRecord {
|
|
601
|
-
func toPaymentIntent() -> AcceptCertisPaymentIntent {
|
|
602
|
-
AcceptCertisPaymentIntent(
|
|
603
|
-
id: paymentIntentId,
|
|
604
|
-
amount: amount,
|
|
605
|
-
requestedCurrency: requestedCurrency,
|
|
606
|
-
settlementCurrency: settlementCurrency ?? requestedCurrency
|
|
607
|
-
)
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// MARK: - Payment outcome conversion
|
|
612
|
-
|
|
613
|
-
private extension AcceptPaymentOutcome where Result == CardPaymentStatus {
|
|
614
|
-
func toCardResult() -> CardPaymentResultRecord {
|
|
615
|
-
let record = CardPaymentResultRecord()
|
|
616
|
-
switch self {
|
|
617
|
-
case .canceled:
|
|
618
|
-
record.status = "aborted"
|
|
619
|
-
case .completed(let status):
|
|
620
|
-
record.status = status.status.cardPaymentStatus
|
|
621
|
-
record.last4 = status.details?.last4
|
|
622
|
-
record.companyName = status.merchantDetails.legalName
|
|
623
|
-
record.companyAddress1 = status.merchantDetails.addressLine1
|
|
624
|
-
record.companyAddress2 = status.merchantDetails.addressLine2
|
|
625
|
-
record.companyCity = status.merchantDetails.city
|
|
626
|
-
record.companyCountry = status.merchantDetails.country
|
|
627
|
-
record.terminalId = status.terminalId
|
|
628
|
-
record.authorizationCode = status.details?.authorizationCode
|
|
629
|
-
record.brand = status.details?.brand.rawValue.uppercased()
|
|
630
|
-
record.reason = status.details?.issuerDeclineReason?.rawValue
|
|
631
|
-
record.receiptUrl = status.receiptUrl?.absoluteString
|
|
632
|
-
record.refundToken = status.refund?.refundToken
|
|
633
|
-
}
|
|
634
|
-
return record
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
private extension AcceptPaymentOutcome where Result == BankTransferPaymentStatus {
|
|
639
|
-
func toBankTransferResult() -> BankTransferPaymentResultRecord {
|
|
640
|
-
let record = BankTransferPaymentResultRecord()
|
|
641
|
-
switch self {
|
|
642
|
-
case .canceled:
|
|
643
|
-
record.status = "aborted"
|
|
644
|
-
case .completed(let status):
|
|
645
|
-
record.status = status.status.bankTransferStatus
|
|
646
|
-
record.postponed = status.details?.postponed ?? false
|
|
647
|
-
record.receivedAt = status.processedAt.map { ISO8601DateFormatter().string(from: $0) }
|
|
648
|
-
record.receivedFromIban = status.details?.bankAccountNumber
|
|
649
|
-
record.receiptUrl = status.receiptUrl?.absoluteString
|
|
650
|
-
}
|
|
651
|
-
return record
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// MARK: - Onboarding status conversion
|
|
656
|
-
|
|
657
|
-
private extension AcceptPaymentMethod {
|
|
658
|
-
static func fromJsString(_ value: String) throws -> AcceptPaymentMethod {
|
|
659
|
-
switch value {
|
|
660
|
-
case "CARD": return .card
|
|
661
|
-
case "SEPA": return .sepaIct
|
|
662
|
-
case "CERTIS": return .certisCz
|
|
663
|
-
case "CRYPTO": return .crypto
|
|
664
|
-
default:
|
|
665
|
-
throw Exception(name: "InvalidPaymentMethod", description: "Unknown payment method: \(value)")
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
func toJsString() -> String {
|
|
670
|
-
switch self {
|
|
671
|
-
case .card: return "CARD"
|
|
672
|
-
case .sepaIct: return "SEPA"
|
|
673
|
-
case .certisCz: return "CERTIS"
|
|
674
|
-
case .crypto: return "CRYPTO"
|
|
675
|
-
@unknown default: return "UNKNOWN"
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
private extension AcceptPaymentMethodStatus.Status {
|
|
681
|
-
func toJsString() -> String {
|
|
682
|
-
switch self {
|
|
683
|
-
case .notStarted: return "NOT_STARTED"
|
|
684
|
-
case .pending: return "PENDING"
|
|
685
|
-
case .active: return "ACTIVE"
|
|
686
|
-
case .attentionNeeded: return "ATTENTION_NEEDED"
|
|
687
|
-
case .actionRequired: return "ACTION_REQUIRED"
|
|
688
|
-
case .blocked: return "BLOCKED"
|
|
689
|
-
@unknown default: return "UNKNOWN"
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
// MARK: - Refund conversion
|
|
695
|
-
|
|
696
|
-
private extension AcceptRefundReason {
|
|
697
|
-
static func fromJsString(_ value: String) throws -> AcceptRefundReason {
|
|
698
|
-
switch value {
|
|
699
|
-
case "customerRequest": return .customerRequest
|
|
700
|
-
case "duplicate": return .duplicate
|
|
701
|
-
case "fraudulent": return .fraudulent
|
|
702
|
-
case "expiredCharge": return .expiredCharge
|
|
703
|
-
default:
|
|
704
|
-
throw Exception(name: "InvalidRefundReason", description: "Unknown refund reason: \(value)")
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
func toJsString() -> String {
|
|
709
|
-
switch self {
|
|
710
|
-
case .customerRequest: return "customerRequest"
|
|
711
|
-
case .duplicate: return "duplicate"
|
|
712
|
-
case .fraudulent: return "fraudulent"
|
|
713
|
-
case .expiredCharge: return "expiredCharge"
|
|
714
|
-
@unknown default: return "customerRequest"
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
private extension AcceptTransactionStatus {
|
|
720
|
-
func toJsString() -> String {
|
|
721
|
-
switch self {
|
|
722
|
-
case .pending: return "pending"
|
|
723
|
-
case .success: return "success"
|
|
724
|
-
case .cancelled: return "cancelled"
|
|
725
|
-
case .refunded: return "refunded"
|
|
726
|
-
case .failed: return "failed"
|
|
727
|
-
case .actionNeeded: return "actionNeeded"
|
|
728
|
-
@unknown default: return "pending"
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
private extension AcceptRefund {
|
|
734
|
-
func toRecord() -> RefundResultRecord {
|
|
735
|
-
let record = RefundResultRecord()
|
|
736
|
-
record.refundToken = refundToken
|
|
737
|
-
record.status = status.toJsString()
|
|
738
|
-
record.paymentMethod = paymentMethod.toJsString()
|
|
739
|
-
record.requestedAmount = requestedAmount
|
|
740
|
-
record.requestedCurrency = requestedCurrency
|
|
741
|
-
record.settlementAmount = settlementAmount
|
|
742
|
-
record.settlementCurrency = settlementCurrency
|
|
743
|
-
record.fxRate = fxRate
|
|
744
|
-
record.refundReason = refundReason.toJsString()
|
|
745
|
-
record.createdAt = ISO8601DateFormatter().string(from: createdAt)
|
|
746
|
-
record.processedAt = processedAt.map { ISO8601DateFormatter().string(from: $0) }
|
|
747
|
-
return record
|
|
748
|
-
}
|
|
749
|
-
}
|