@primer-io/react-native 2.3.0 → 2.6.0

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.
Files changed (53) hide show
  1. package/android/.project +11 -0
  2. package/android/.settings/org.eclipse.buildship.core.prefs +2 -2
  3. package/android/build.gradle +1 -1
  4. package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +1 -20
  5. package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckout.kt +2 -21
  6. package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt +5 -6
  7. package/android/src/main/java/com/primerioreactnative/ReactNativePackage.kt +3 -1
  8. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerPaymentMethodDataRN.kt +1 -3
  9. package/android/src/main/java/com/primerioreactnative/huc/datamodels/manager/raw/card/PrimerRNPRawCardData.kt +22 -0
  10. package/android/src/main/java/com/primerioreactnative/huc/datamodels/manager/raw/phoneNumber/PrimerRNRawPhoneNumberData.kt +14 -0
  11. package/android/src/main/java/com/primerioreactnative/huc/events/PrimerHeadlessUniversalCheckoutRawDataManagerEvent.kt +7 -0
  12. package/android/src/main/java/com/primerioreactnative/huc/manager/raw/PrimerRNHeadlessUniversalCheckoutRawManager.kt +162 -0
  13. package/android/src/main/java/com/primerioreactnative/huc/manager/raw/PrimerRNHeadlessUniversalCheckoutRawManagerListener.kt +49 -0
  14. package/ios/DataModels/PrimerErrorRN.swift +2 -0
  15. package/ios/DataModels/RNTPrimerCardData.swift +46 -0
  16. package/ios/DataModels/RNTPrimerPhoneNumberData.swift +38 -0
  17. package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckout.swift +70 -107
  18. package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckoutRawDataManager.m +21 -0
  19. package/ios/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckoutRawDataManager.swift +158 -0
  20. package/ios/RNTPrimer.m +1 -1
  21. package/ios/RNTPrimer.swift +2 -9
  22. package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckout.js +5 -4
  23. package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckout.js.map +1 -1
  24. package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js +110 -0
  25. package/lib/commonjs/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
  26. package/lib/commonjs/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js +95 -0
  27. package/lib/commonjs/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
  28. package/lib/commonjs/index.js +28 -6
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/commonjs/models/PrimerRawData.js +2 -0
  31. package/lib/commonjs/models/PrimerRawData.js.map +1 -0
  32. package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckout.js +3 -3
  33. package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckout.js.map +1 -1
  34. package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js +92 -0
  35. package/lib/module/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
  36. package/lib/module/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js +86 -0
  37. package/lib/module/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.js.map +1 -0
  38. package/lib/module/index.js +3 -1
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/models/PrimerRawData.js +2 -0
  41. package/lib/module/models/PrimerRawData.js.map +1 -0
  42. package/lib/typescript/src/headless_checkout/PrimerHeadlessUniversalCheckout.d.ts +1 -0
  43. package/lib/typescript/src/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.d.ts +17 -0
  44. package/lib/typescript/src/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.d.ts +13 -0
  45. package/lib/typescript/src/index.d.ts +3 -1
  46. package/lib/typescript/src/models/PrimerRawData.d.ts +12 -0
  47. package/package.json +1 -1
  48. package/primer-io-react-native.podspec +1 -1
  49. package/src/headless_checkout/PrimerHeadlessUniversalCheckout.ts +3 -3
  50. package/src/headless_checkout/PrimerHeadlessUniversalCheckoutRawDataManager.ts +108 -0
  51. package/src/headless_checkout/RNPrimerHeadlessUniversalCheckoutRawDataManager.ts +102 -0
  52. package/src/index.tsx +8 -1
  53. package/src/models/PrimerRawData.ts +13 -0
@@ -10,7 +10,7 @@ import PrimerSDK
10
10
 
11
11
  @objc
12
12
  enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
13
-
13
+
14
14
  case onHUCTokenizeStart = 0
15
15
  case onHUCPrepareStart
16
16
  case onHUCAvailablePaymentMethodsLoaded
@@ -22,7 +22,7 @@ enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
22
22
  case onClientSessionUpdate
23
23
  case onCheckoutComplete
24
24
  case onError
25
-
25
+
26
26
  var stringValue: String {
27
27
  switch self {
28
28
  case .onHUCPrepareStart:
@@ -53,28 +53,28 @@ enum PrimerHeadlessUniversalCheckoutEvents: Int, CaseIterable {
53
53
 
54
54
  @objc(PrimerHeadlessUniversalCheckout)
55
55
  class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
56
-
56
+
57
57
  private var primerWillCreatePaymentWithDataDecisionHandler: ((_ errorMessage: String?) -> Void)?
58
58
  private var primerDidTokenizePaymentMethodDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
59
59
  private var primerDidResumeWithDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
60
60
  private var primerDidFailWithErrorDecisionHandler: ((_ errorMessage: String) -> Void)?
61
61
  private var implementedRNCallbacks: ImplementedRNCallbacks?
62
-
62
+
63
63
  override class func requiresMainQueueSetup() -> Bool {
64
64
  return true
65
65
  }
66
-
66
+
67
67
  override init() {
68
68
  super.init()
69
69
  PrimerHeadlessUniversalCheckout.current.delegate = self
70
70
  }
71
-
71
+
72
72
  override func supportedEvents() -> [String]! {
73
73
  return PrimerHeadlessUniversalCheckoutEvents.allCases.compactMap({ $0.stringValue })
74
74
  }
75
-
75
+
76
76
  // MARK: - API
77
-
77
+
78
78
  @objc
79
79
  public func startWithClientToken(_ clientToken: String,
80
80
  settingsStr: String?,
@@ -90,134 +90,97 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
90
90
  return
91
91
  }
92
92
  }
93
-
93
+
94
94
  PrimerHeadlessUniversalCheckout.current.start(withClientToken: clientToken, settings: settings, delegate: self) { paymentMethodTypes, err in
95
95
  if let err = err {
96
96
  errorCallback([err.rnError])
97
97
  } else if let paymentMethodTypes = paymentMethodTypes {
98
- successCallback([paymentMethodTypes.compactMap({$0.rawValue})])
98
+ successCallback([paymentMethodTypes])
99
99
  }
100
100
  }
101
101
  }
102
-
102
+
103
103
  @objc
104
104
  public func getAssetForPaymentMethodType(_ paymentMethodTypeStr: String,
105
105
  assetType assetTypeStr: String,
106
106
  errorCallback: @escaping RCTResponseSenderBlock,
107
107
  successCallback: @escaping RCTResponseSenderBlock)
108
108
  {
109
+ guard let unwrappedAssetType = PrimerAsset.ImageType(rawValue: assetTypeStr), let image = PrimerHeadlessUniversalCheckout.getAsset(for: paymentMethodTypeStr, assetType: unwrappedAssetType) else {
110
+ let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(paymentMethodTypeStr)", recoverySuggestion: nil)
111
+ errorCallback([err.rnError])
112
+ return
113
+ }
114
+
109
115
  do {
110
- try validate(assetStr: paymentMethodTypeStr, assetTypeStr: assetTypeStr)
111
- let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodTypeStr)
112
-
113
- guard let image = PrimerHeadlessUniversalCheckout.getAsset(for: paymentMethodType, assetType: PrimerAsset.ImageType(rawValue: assetTypeStr)!) else {
114
- let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(paymentMethodTypeStr)", recoverySuggestion: nil)
115
- errorCallback([err.rnError])
116
- return
117
- }
118
-
119
-
120
116
  let imageURL = try self.tempStoreImage(image: image, name: paymentMethodTypeStr)
121
117
  successCallback([imageURL.absoluteString])
122
118
  } catch {
123
119
  errorCallback([error.rnError])
124
120
  }
125
121
  }
126
-
122
+
127
123
  @objc
128
124
  public func getAssetForCardNetwork(_ cardNetworkStr: String,
129
125
  assetType assetTypeStr: String,
130
126
  errorCallback: @escaping RCTResponseSenderBlock,
131
127
  successCallback: @escaping RCTResponseSenderBlock)
132
128
  {
129
+ guard let cardNetwork = CardNetwork(rawValue: cardNetworkStr) else {
130
+ let err = NativeError(errorId: "invalid-card-network", errorDescription: "Card network for \(cardNetworkStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
131
+ errorCallback([err.rnError])
132
+ return
133
+ }
134
+
135
+ guard let unwrappedAssetType = PrimerAsset.ImageType(rawValue: assetTypeStr), let image = PrimerHeadlessUniversalCheckout.getAsset(for: cardNetwork, assetType: unwrappedAssetType) else {
136
+ let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(cardNetworkStr)", recoverySuggestion: nil)
137
+ errorCallback([err.rnError])
138
+ return
139
+ }
140
+
133
141
  do {
134
- try validate(assetStr: cardNetworkStr, assetTypeStr: assetTypeStr)
135
- guard let cardNetwork = CardNetwork(rawValue: cardNetworkStr) else {
136
- let err = NativeError(errorId: "invalid-card-network", errorDescription: "Card network for \(cardNetworkStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
137
- errorCallback([err.rnError])
138
- return
139
- }
140
-
141
- guard let image = PrimerHeadlessUniversalCheckout.getAsset(for: cardNetwork, assetType: PrimerAsset.ImageType(rawValue: assetTypeStr)!) else {
142
- let err = NativeError(errorId: "missing-asset", errorDescription: "Failed to find \(assetTypeStr) for \(cardNetworkStr)", recoverySuggestion: nil)
143
- errorCallback([err.rnError])
144
- return
145
- }
146
-
147
-
148
142
  let imageURL = try self.tempStoreImage(image: image, name: cardNetworkStr)
149
143
  successCallback([imageURL.absoluteString])
150
144
  } catch {
151
145
  errorCallback([error.rnError])
152
146
  }
153
147
  }
154
-
148
+
155
149
  @objc
156
150
  public func showPaymentMethod(_ paymentMethodTypeStr: String,
157
151
  resolver: RCTPromiseResolveBlock,
158
152
  rejecter: RCTPromiseRejectBlock)
159
153
  {
160
- let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodTypeStr)
161
- PrimerHeadlessUniversalCheckout.current.showPaymentMethod(paymentMethodType)
154
+ PrimerHeadlessUniversalCheckout.current.showPaymentMethod(paymentMethodTypeStr)
162
155
  resolver(nil)
163
156
  }
164
-
157
+
165
158
  @objc
166
159
  public func disposePrimerHeadlessUniversalCheckout() {
167
-
160
+
168
161
  }
169
-
162
+
170
163
  // MARK: - HELPERS
171
-
172
- private func validate(assetStr: String, assetTypeStr: String) throws {
173
- var errors: [NativeError] = []
174
-
175
- if PrimerPaymentMethodType(rawValue: assetStr) != .other(rawValue: assetStr) {
176
- // ...
177
- } else if CardNetwork(rawValue: assetStr) != nil {
178
- // ...
179
- } else {
180
- let err = NativeError(errorId: "invalid-payment-method-type", errorDescription: "Asset for \(assetStr) does not exist, make sure you don't have any typos.", recoverySuggestion: nil)
181
- errors.append(err)
182
- }
183
-
184
-
185
- if PrimerAsset.ImageType(rawValue: assetTypeStr) == nil {
186
- let err = NativeError(errorId: "mismatch", errorDescription: "You have provided assetType=\(assetTypeStr), which is not valid", recoverySuggestion: "Use one of the following values: \(PrimerAsset.ImageType.allCases.compactMap({ $0.rawValue }))")
187
- errors.append(err)
188
- }
189
-
190
- if errors.isEmpty {
191
- return
192
- } else if errors.count == 1 {
193
- throw errors.first!
194
- } else {
195
- let errorDescription: String = errors.compactMap({ $0.errorDescription }).joined(separator: "/n")
196
- let recoverySuggestion = errors.compactMap({ $0.recoverySuggestion }).joined(separator: "/n")
197
- let err = NativeError(errorId: "underlying-errors", errorDescription: errorDescription, recoverySuggestion: recoverySuggestion)
198
- throw err
199
- }
200
- }
201
-
164
+
202
165
  private func tempStoreImage(image: UIImage, name: String) throws -> URL {
203
166
  guard let imageURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(name).png") else {
204
167
  let err = NativeError(errorId: "error", errorDescription: "Failed to create URL for asset", recoverySuggestion: nil)
205
168
  throw err
206
169
  }
207
-
170
+
208
171
  guard let pngData = image.pngData() else {
209
172
  let err = NativeError(errorId: "error", errorDescription: "Failed to get image's PNG data", recoverySuggestion: nil)
210
173
  throw err
211
174
  }
212
-
175
+
213
176
  try pngData.write(to: imageURL)
214
177
  return imageURL
215
178
  }
216
-
179
+
217
180
  // MARK: - DECISION HANDLERS
218
-
181
+
219
182
  // MARK: Tokenization
220
-
183
+
221
184
  @objc
222
185
  public func handleTokenizationNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
223
186
  DispatchQueue.main.async {
@@ -226,7 +189,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
226
189
  resolver(nil)
227
190
  }
228
191
  }
229
-
192
+
230
193
  @objc
231
194
  public func handleTokenizationSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
232
195
  DispatchQueue.main.async {
@@ -236,7 +199,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
236
199
  rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
237
200
  }
238
201
  }
239
-
202
+
240
203
  @objc
241
204
  public func handleTokenizationFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
242
205
  DispatchQueue.main.async {
@@ -246,9 +209,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
246
209
  rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
247
210
  }
248
211
  }
249
-
212
+
250
213
  // MARK: Resume Payment
251
-
214
+
252
215
  @objc
253
216
  public func handleResumeWithNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
254
217
  DispatchQueue.main.async {
@@ -257,7 +220,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
257
220
  resolver(nil)
258
221
  }
259
222
  }
260
-
223
+
261
224
  @objc
262
225
  public func handleResumeSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
263
226
  DispatchQueue.main.async {
@@ -265,7 +228,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
265
228
  rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
266
229
  }
267
230
  }
268
-
231
+
269
232
  @objc
270
233
  public func handleResumeFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
271
234
  DispatchQueue.main.async {
@@ -273,9 +236,9 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
273
236
  rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
274
237
  }
275
238
  }
276
-
239
+
277
240
  // MARK: Payment Creation
278
-
241
+
279
242
  @objc
280
243
  public func handlePaymentCreationAbort(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
281
244
  DispatchQueue.main.async {
@@ -284,7 +247,7 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
284
247
  resolver(nil)
285
248
  }
286
249
  }
287
-
250
+
288
251
  @objc
289
252
  public func handlePaymentCreationContinue(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
290
253
  DispatchQueue.main.async {
@@ -293,13 +256,13 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
293
256
  resolver(nil)
294
257
  }
295
258
  }
296
-
259
+
297
260
  // MARK: Helpers
298
-
261
+
299
262
  private func detectImplemetedCallbacks() {
300
263
  sendEvent(withName: PrimerEvents.detectImplementedRNCallbacks.stringValue, body: nil)
301
264
  }
302
-
265
+
303
266
  @objc
304
267
  public func setImplementedRNCallbacks(_ implementedRNCallbacksStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
305
268
  DispatchQueue.main.async {
@@ -316,13 +279,13 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
316
279
  }
317
280
  }
318
281
  }
319
-
282
+
320
283
  private func handleRNBridgeError(_ error: Error, checkoutData: PrimerCheckoutData?, stopOnDebug: Bool) {
321
284
  DispatchQueue.main.async {
322
285
  if stopOnDebug {
323
286
  assertionFailure(error.localizedDescription)
324
287
  }
325
-
288
+
326
289
  var body: [String: Any] = ["error": error.rnError]
327
290
  if let checkoutData = checkoutData,
328
291
  let data = try? JSONEncoder().encode(checkoutData),
@@ -338,23 +301,23 @@ class RNTPrimerHeadlessUniversalCheckout: RCTEventEmitter {
338
301
  // MARK: - EVENTS
339
302
 
340
303
  extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDelegate {
341
-
304
+
342
305
  func primerHeadlessUniversalCheckoutPreparationDidStart(for paymentMethodType: String) {
343
306
  sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCPrepareStart.stringValue, body: ["paymentMethodType": paymentMethodType])
344
307
  }
345
-
308
+
346
309
  func primerHeadlessUniversalCheckoutTokenizationDidStart(for paymentMethodType: String) {
347
310
  sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCTokenizeStart.stringValue, body: ["paymentMethodType": paymentMethodType])
348
311
  }
349
-
312
+
350
313
  func primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods(_ paymentMethodTypes: [String]) {
351
314
  sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCAvailablePaymentMethodsLoaded.stringValue, body: ["paymentMethodTypes": paymentMethodTypes])
352
315
  }
353
-
316
+
354
317
  func primerHeadlessUniversalCheckoutPaymentMethodDidShow(for paymentMethodType: String) {
355
318
  sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onHUCPaymentMethodShow.stringValue, body: ["paymentMethodType": paymentMethodType])
356
319
  }
357
-
320
+
358
321
  func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod(_ paymentMethodTokenData: PrimerPaymentMethodTokenData, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
359
322
  if self.implementedRNCallbacks?.isOnTokenizeSuccessImplemented == true {
360
323
  self.primerDidTokenizePaymentMethodDecisionHandler = { (newClientToken, errorMessage) in
@@ -368,7 +331,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
368
331
  }
369
332
  }
370
333
  }
371
-
334
+
372
335
  do {
373
336
  let data = try JSONEncoder().encode(paymentMethodTokenData)
374
337
  let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
@@ -384,7 +347,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
384
347
  // auto flow.
385
348
  }
386
349
  }
387
-
350
+
388
351
  func primerHeadlessUniversalCheckoutDidResumeWith(_ resumeToken: String, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
389
352
  if self.implementedRNCallbacks?.isOnResumeSuccessImplemented == true {
390
353
  self.primerDidResumeWithDecisionHandler = { (resumeToken, errorMessage) in
@@ -398,7 +361,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
398
361
  }
399
362
  }
400
363
  }
401
-
364
+
402
365
  DispatchQueue.main.async {
403
366
  self.sendEvent(withName: PrimerHeadlessUniversalCheckoutEvents.onResumeSuccess.stringValue, body: ["resumeToken": resumeToken])
404
367
  }
@@ -407,18 +370,18 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
407
370
  // Throw an error if it's the manual flow.
408
371
  }
409
372
  }
410
-
373
+
411
374
  func primerHeadlessUniversalCheckoutDidFail(withError err: Error) {
412
375
  if self.implementedRNCallbacks?.isOnErrorImplemented == true {
413
376
  // Send the error message to the RN bridge.
414
377
  self.handleRNBridgeError(err, checkoutData: nil, stopOnDebug: false)
415
-
378
+
416
379
  } else {
417
380
  // RN dev hasn't opted in on listening SDK dismiss.
418
381
  // Ignore!
419
382
  }
420
383
  }
421
-
384
+
422
385
  func primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData(_ data: PrimerCheckoutData) {
423
386
  DispatchQueue.main.async {
424
387
  if self.implementedRNCallbacks?.isOnCheckoutCompleteImplemented == true {
@@ -435,7 +398,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
435
398
  }
436
399
  }
437
400
  }
438
-
401
+
439
402
  func primerHeadlessUniversalCheckoutClientSessionWillUpdate() {
440
403
  if self.implementedRNCallbacks?.isOnBeforeClientSessionUpdateImplemented == true {
441
404
  DispatchQueue.main.async {
@@ -445,7 +408,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
445
408
  // RN Dev hasn't implemented this callback, ignore.
446
409
  }
447
410
  }
448
-
411
+
449
412
  func primerHeadlessUniversalCheckoutClientSessionDidUpdate(_ clientSession: PrimerClientSession) {
450
413
  if self.implementedRNCallbacks?.isOnClientSessionUpdateImplemented == true {
451
414
  do {
@@ -461,7 +424,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
461
424
  // RN Dev hasn't implemented this callback, ignore.
462
425
  }
463
426
  }
464
-
427
+
465
428
  func primerHeadlessUniversalCheckoutWillCreatePaymentWithData(_ data: PrimerCheckoutPaymentMethodData, decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void) {
466
429
  if self.implementedRNCallbacks?.isOnBeforePaymentCreateImplemented == true {
467
430
  self.primerWillCreatePaymentWithDataDecisionHandler = { errorMessage in
@@ -473,7 +436,7 @@ extension RNTPrimerHeadlessUniversalCheckout: PrimerHeadlessUniversalCheckoutDel
473
436
  }
474
437
  }
475
438
  }
476
-
439
+
477
440
  DispatchQueue.main.async {
478
441
  do {
479
442
  let checkoutPaymentmethodData = try JSONEncoder().encode(data)
@@ -0,0 +1,21 @@
1
+ //
2
+ // RNTPrimerHeadlessUniversalCheckoutRawDataManager.m
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Evangelos on 3/8/22.
6
+ //
7
+
8
+ #import <React/RCTBridgeModule.h>
9
+ #import <React/RCTEventEmitter.h>
10
+
11
+ @interface RCT_EXTERN_MODULE(PrimerHeadlessUniversalCheckoutRawDataManager, RCTEventEmitter)
12
+
13
+ RCT_EXTERN_METHOD(initialize:(NSString *)paymentMethodTypeStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
14
+
15
+ RCT_EXTERN_METHOD(listRequiredInputElementTypesForPaymentMethodType:(NSString *)paymentMethodTypeStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
16
+
17
+ RCT_EXTERN_METHOD(setRawData:(NSString *)rawDataStr resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
18
+
19
+ RCT_EXTERN_METHOD(submit:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
20
+
21
+ @end
@@ -0,0 +1,158 @@
1
+ //
2
+ // RNTPrimerHeadlessUniversalCheckoutRawDataManager.swift
3
+ // primer-io-react-native
4
+ //
5
+ // Created by Evangelos on 3/8/22.
6
+ //
7
+
8
+ import Foundation
9
+ import PrimerSDK
10
+
11
+ @objc
12
+ enum PrimerHeadlessUniversalCheckoutRawDataManagerEvents: Int, CaseIterable {
13
+
14
+ case onMetadataChange = 0
15
+ case onValidation
16
+ case onNativeError
17
+
18
+ var stringValue: String {
19
+ switch self {
20
+ case .onMetadataChange:
21
+ return "onMetadataChange"
22
+ case .onValidation:
23
+ return "onValidation"
24
+ case .onNativeError:
25
+ return "onNativeError"
26
+ }
27
+ }
28
+ }
29
+
30
+ @objc(PrimerHeadlessUniversalCheckoutRawDataManager)
31
+ class RNTPrimerHeadlessUniversalCheckoutRawDataManager: RCTEventEmitter {
32
+
33
+ private var rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager!
34
+ private var paymentMethodType: String?
35
+
36
+ override class func requiresMainQueueSetup() -> Bool {
37
+ return true
38
+ }
39
+
40
+ override func supportedEvents() -> [String]! {
41
+ return PrimerHeadlessUniversalCheckoutRawDataManagerEvents.allCases.compactMap({ $0.stringValue })
42
+ }
43
+
44
+ // MARK: - API
45
+
46
+ @objc
47
+ public func initialize(
48
+ _ paymentMethodTypeStr: String,
49
+ resolver: RCTPromiseResolveBlock,
50
+ rejecter: RCTPromiseRejectBlock
51
+ ) {
52
+ self.paymentMethodType = paymentMethodTypeStr
53
+
54
+ do {
55
+ self.rawDataManager = try PrimerHeadlessUniversalCheckout.RawDataManager(paymentMethodType: self.paymentMethodType!)
56
+ self.rawDataManager.delegate = self
57
+ resolver(nil)
58
+ } catch {
59
+ rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
60
+ }
61
+ }
62
+
63
+ @objc
64
+ public func listRequiredInputElementTypesForPaymentMethodType(
65
+ _ paymentMethodTypeStr: String,
66
+ resolver: RCTPromiseResolveBlock,
67
+ rejecter: RCTPromiseRejectBlock
68
+ ) {
69
+ guard let rawDataManager = rawDataManager else {
70
+ let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
71
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
72
+ return
73
+ }
74
+
75
+ let inputElementTypes = rawDataManager.listRequiredInputElementTypes(for: rawDataManager.paymentMethodType).compactMap({ $0.stringValue })
76
+ resolver(["inputElementTypes": inputElementTypes])
77
+ }
78
+
79
+ @objc
80
+ public func setRawData(
81
+ _ rawDataStr: String,
82
+ resolver: RCTPromiseResolveBlock,
83
+ rejecter: RCTPromiseRejectBlock
84
+ ) {
85
+ guard let rawDataManager = rawDataManager else {
86
+ let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
87
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
88
+ return
89
+ }
90
+
91
+ if let rawCardData = PrimerCardData(cardDataStr: rawDataStr) {
92
+ rawDataManager.rawData = rawCardData
93
+ resolver(nil)
94
+ return
95
+ }
96
+
97
+ if let rawPhoneNumberData = PrimerPhoneNumberData(phoneNumbeDatarStr: rawDataStr) {
98
+ rawDataManager.rawData = rawPhoneNumberData
99
+ resolver(nil)
100
+ return
101
+ }
102
+
103
+ let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to decode RawData on iOS. Make sure you're providing a valid 'PrimerRawData' (or any inherited) object"])
104
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
105
+ }
106
+
107
+ @objc
108
+ public func submit(
109
+ _ resolver: RCTPromiseResolveBlock,
110
+ rejecter: RCTPromiseRejectBlock
111
+ ) {
112
+ guard let rawDataManager = rawDataManager else {
113
+ let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "The PrimerHeadlessUniversalCheckoutRawDataManager has not been initialized. Make sure you have called the PrimerHeadlessUniversalCheckoutRawDataManager.configure function first."])
114
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
115
+ return
116
+ }
117
+
118
+ rawDataManager.submit()
119
+ resolver(nil)
120
+ }
121
+ }
122
+
123
+ extension RNTPrimerHeadlessUniversalCheckoutRawDataManager: PrimerRawDataManagerDelegate {
124
+
125
+ func primerRawDataManager(_ rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager, metadataDidChange metadata: [String : Any]?) {
126
+ DispatchQueue.main.async {
127
+ self.sendEvent(withName: PrimerHeadlessUniversalCheckoutRawDataManagerEvents.onMetadataChange.stringValue, body: metadata)
128
+ }
129
+ }
130
+
131
+ func primerRawDataManager(_ rawDataManager: PrimerHeadlessUniversalCheckout.RawDataManager, dataIsValid isValid: Bool, errors: [Error]?) {
132
+ DispatchQueue.main.async {
133
+ var body: [String: Any] = ["isValid": isValid]
134
+ if let errors = errors {
135
+ let rnErrors = errors.compactMap({ $0.rnError })
136
+ body["errors"] = rnErrors
137
+ }
138
+ self.sendEvent(withName: PrimerHeadlessUniversalCheckoutRawDataManagerEvents.onValidation.stringValue, body: body)
139
+ }
140
+ }
141
+
142
+ private func handleRNBridgeError(_ error: Error, checkoutData: PrimerCheckoutData?, stopOnDebug: Bool) {
143
+ DispatchQueue.main.async {
144
+ if stopOnDebug {
145
+ assertionFailure(error.localizedDescription)
146
+ }
147
+
148
+ var body: [String: Any] = ["error": error.rnError]
149
+ if let checkoutData = checkoutData,
150
+ let data = try? JSONEncoder().encode(checkoutData),
151
+ let json = try? JSONSerialization.jsonObject(with: data){
152
+ body["checkoutData"] = json
153
+ }
154
+ print(body)
155
+ self.sendEvent(withName: PrimerEvents.onError.stringValue, body: body)
156
+ }
157
+ }
158
+ }
package/ios/RNTPrimer.m CHANGED
@@ -18,7 +18,7 @@ RCT_EXTERN_METHOD(showUniversalCheckoutWithClientToken:(NSString *)clientToken r
18
18
 
19
19
  RCT_EXTERN_METHOD(showVaultManagerWithClientToken: (NSString *)clientToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
20
20
 
21
- RCT_EXTERN_METHOD(showPaymentMethod:(NSString *)paymentMethodStr intent:(NSString *)intentStr clientToken:(NSString *)clientToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
21
+ RCT_EXTERN_METHOD(showPaymentMethod:(NSString *)paymentMethodTypeStr intent:(NSString *)intentStr clientToken:(NSString *)clientToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
22
22
 
23
23
  RCT_EXTERN_METHOD(dismiss)
24
24
 
@@ -119,22 +119,15 @@ class RNTPrimer: RCTEventEmitter {
119
119
  }
120
120
 
121
121
  @objc
122
- public func showPaymentMethod(_ paymentMethodStr: String, intent: String, clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
122
+ public func showPaymentMethod(_ paymentMethodTypeStr: String, intent: String, clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
123
123
  DispatchQueue.main.async {
124
124
  do {
125
- let paymentMethodType = PrimerPaymentMethodType(rawValue: paymentMethodStr)
126
-
127
- guard paymentMethodType != PrimerPaymentMethodType.other(rawValue: paymentMethodStr) else {
128
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Payment method type \(paymentMethodStr) is not valid."])
129
- throw err
130
- }
131
-
132
125
  guard let primerIntent = PrimerSessionIntent(rawValue: intent) else {
133
126
  let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Intent \(intent) is not valid."])
134
127
  throw err
135
128
  }
136
129
 
137
- PrimerSDK.Primer.shared.showPaymentMethod(paymentMethodType, withIntent: primerIntent, andClientToken: clientToken) { err in
130
+ PrimerSDK.Primer.shared.showPaymentMethod(paymentMethodTypeStr, withIntent: primerIntent, andClientToken: clientToken) { err in
138
131
  DispatchQueue.main.async {
139
132
  if let err = err {
140
133
  rejecter(err.rnError["errorId"]!, err.rnError["description"], err)