@primer-io/react-native 0.15.8 → 2.0.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 (203) hide show
  1. package/README.md +114 -24
  2. package/android/build.gradle +7 -2
  3. package/android/gradle.properties +3 -3
  4. package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +118 -148
  5. package/android/src/main/java/com/primerioreactnative/PrimerRNEventListener.kt +212 -127
  6. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerCheckoutDataRN.kt +12 -0
  7. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerClientSessionRN.kt +54 -0
  8. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerErrorRN.kt +3 -7
  9. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerEvents.kt +13 -0
  10. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerPaymentInstrumentTokenRN.kt +4 -4
  11. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerPaymentMethodDataRN.kt +8 -0
  12. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerSettingsRN.kt +43 -125
  13. package/android/src/main/java/com/primerioreactnative/extensions/Payment.kt +6 -0
  14. package/android/src/main/java/com/primerioreactnative/extensions/PrimerAddress.kt +15 -0
  15. package/android/src/main/java/com/primerioreactnative/extensions/PrimerCheckoutData.kt +7 -0
  16. package/android/src/main/java/com/primerioreactnative/extensions/PrimerClientSession.kt +15 -0
  17. package/android/src/main/java/com/primerioreactnative/extensions/PrimerCustomer.kt +13 -0
  18. package/android/src/main/java/com/primerioreactnative/extensions/PrimerLineItem.kt +8 -0
  19. package/android/src/main/java/com/primerioreactnative/extensions/PrimerOrder.kt +6 -0
  20. package/android/src/main/java/com/primerioreactnative/extensions/PrimerPaymentMethodData.kt +7 -0
  21. package/android/src/main/java/com/primerioreactnative/utils/ErrorHelper.kt +1 -3
  22. package/android/src/main/java/com/primerioreactnative/utils/JsonConverter.kt +45 -0
  23. package/android/src/main/java/com/primerioreactnative/utils/PrimerImplementedRNCallbacks.kt +16 -6
  24. package/ios/DataModels/ImplementedRNCallbacks.swift +31 -0
  25. package/ios/DataModels/PrimerErrorRN.swift +0 -17
  26. package/ios/DataModels/PrimerSettingsRN.swift +70 -147
  27. package/ios/DataModels/PrimerThemeRN.swift +1 -10
  28. package/ios/{Pods/Manifest.lock → Podfile.lock} +1 -1
  29. package/ios/RNTPrimer.m +26 -12
  30. package/ios/RNTPrimer.swift +295 -249
  31. package/ios/ReactNative.xcodeproj/project.pbxproj +14 -14
  32. package/lib/commonjs/Primer.js +201 -150
  33. package/lib/commonjs/Primer.js.map +1 -1
  34. package/lib/commonjs/RNPrimer.js +102 -41
  35. package/lib/commonjs/RNPrimer.js.map +1 -1
  36. package/lib/commonjs/index.js +117 -4
  37. package/lib/commonjs/index.js.map +1 -1
  38. package/lib/commonjs/models/Primer.js +6 -0
  39. package/lib/commonjs/models/{action-request.js.map → Primer.js.map} +0 -0
  40. package/lib/commonjs/models/PrimerCheckoutData.js +9 -0
  41. package/lib/commonjs/models/PrimerCheckoutData.js.map +1 -0
  42. package/lib/commonjs/models/PrimerCheckoutPaymentMethodData.js +2 -0
  43. package/lib/commonjs/models/{client-session-actions-request.js.map → PrimerCheckoutPaymentMethodData.js.map} +0 -0
  44. package/lib/commonjs/models/PrimerClientSession.js +2 -0
  45. package/lib/commonjs/models/{primer-callbacks.js.map → PrimerClientSession.js.map} +0 -0
  46. package/lib/commonjs/models/{utils/countryCode.js → PrimerCountryCode.js} +1 -1
  47. package/lib/commonjs/models/PrimerCountryCode.js.map +1 -0
  48. package/lib/commonjs/models/{utils/currencyCode.js → PrimerCurrencyCode.js} +1 -1
  49. package/lib/commonjs/models/PrimerCurrencyCode.js.map +1 -0
  50. package/lib/commonjs/models/PrimerError.js +28 -0
  51. package/lib/commonjs/models/PrimerError.js.map +1 -0
  52. package/lib/commonjs/models/PrimerPaymentMethodTokenData.js +14 -0
  53. package/lib/commonjs/models/PrimerPaymentMethodTokenData.js.map +1 -0
  54. package/lib/commonjs/models/PrimerSessionIntent.js +14 -0
  55. package/lib/commonjs/models/PrimerSessionIntent.js.map +1 -0
  56. package/lib/commonjs/models/PrimerSettings.js +6 -0
  57. package/lib/commonjs/models/{primer-config.js.map → PrimerSettings.js.map} +0 -0
  58. package/lib/commonjs/models/PrimerTheme.js +2 -0
  59. package/lib/commonjs/models/{primer-request.js.map → PrimerTheme.js.map} +0 -0
  60. package/lib/commonjs/utils/index.js +1 -1
  61. package/lib/commonjs/utils/index.js.map +1 -1
  62. package/lib/module/Primer.js +201 -137
  63. package/lib/module/Primer.js.map +1 -1
  64. package/lib/module/RNPrimer.js +102 -41
  65. package/lib/module/RNPrimer.js.map +1 -1
  66. package/lib/module/index.js +9 -4
  67. package/lib/module/index.js.map +1 -1
  68. package/lib/module/models/Primer.js +2 -0
  69. package/lib/{commonjs/models/primer-settings.js.map → module/models/Primer.js.map} +0 -0
  70. package/lib/module/models/PrimerCheckoutData.js +7 -0
  71. package/lib/module/models/PrimerCheckoutData.js.map +1 -0
  72. package/lib/module/models/PrimerCheckoutPaymentMethodData.js +2 -0
  73. package/lib/{commonjs/models/primer-theme.js.map → module/models/PrimerCheckoutPaymentMethodData.js.map} +0 -0
  74. package/lib/module/models/PrimerClientSession.js +2 -0
  75. package/lib/{commonjs/models/primer.js.map → module/models/PrimerClientSession.js.map} +0 -0
  76. package/lib/module/models/{utils/countryCode.js → PrimerCountryCode.js} +1 -1
  77. package/lib/module/models/PrimerCountryCode.js.map +1 -0
  78. package/lib/module/models/{utils/currencyCode.js → PrimerCurrencyCode.js} +1 -1
  79. package/lib/module/models/PrimerCurrencyCode.js.map +1 -0
  80. package/lib/module/models/PrimerError.js +19 -0
  81. package/lib/module/models/PrimerError.js.map +1 -0
  82. package/lib/module/models/PrimerPaymentMethodTokenData.js +7 -0
  83. package/lib/module/models/PrimerPaymentMethodTokenData.js.map +1 -0
  84. package/lib/module/models/PrimerSessionIntent.js +7 -0
  85. package/lib/module/models/PrimerSessionIntent.js.map +1 -0
  86. package/lib/module/models/PrimerSettings.js +2 -0
  87. package/lib/module/models/{action-request.js.map → PrimerSettings.js.map} +0 -0
  88. package/lib/module/models/PrimerTheme.js +2 -0
  89. package/lib/module/models/{client-session-actions-request.js.map → PrimerTheme.js.map} +0 -0
  90. package/lib/module/utils/index.js.map +1 -1
  91. package/lib/typescript/Primer.d.ts +2 -15
  92. package/lib/typescript/RNPrimer.d.ts +16 -9
  93. package/lib/typescript/index.d.ts +9 -3
  94. package/lib/typescript/models/Primer.d.ts +26 -0
  95. package/lib/typescript/models/PrimerCheckoutData.d.ts +15 -0
  96. package/lib/typescript/models/PrimerCheckoutPaymentMethodData.d.ts +5 -0
  97. package/lib/typescript/models/PrimerClientSession.d.ts +45 -0
  98. package/lib/typescript/models/{utils/countryCode.d.ts → PrimerCountryCode.d.ts} +1 -1
  99. package/lib/typescript/models/{utils/currencyCode.d.ts → PrimerCurrencyCode.d.ts} +1 -1
  100. package/lib/typescript/models/PrimerError.d.ts +11 -0
  101. package/lib/typescript/models/PrimerPaymentMethodTokenData.d.ts +116 -0
  102. package/lib/typescript/models/PrimerSessionIntent.d.ts +4 -0
  103. package/lib/typescript/models/PrimerSettings.d.ts +73 -0
  104. package/lib/typescript/models/{primer-theme.d.ts → PrimerTheme.d.ts} +1 -1
  105. package/lib/typescript/utils/index.d.ts +1 -1
  106. package/package.json +1 -1
  107. package/primer-io-react-native.podspec +1 -1
  108. package/src/Primer.ts +228 -172
  109. package/src/RNPrimer.ts +135 -51
  110. package/src/index.tsx +33 -6
  111. package/src/models/Primer.ts +35 -0
  112. package/src/models/PrimerCheckoutData.ts +18 -0
  113. package/src/models/PrimerCheckoutPaymentMethodData.ts +5 -0
  114. package/src/models/PrimerClientSession.ts +53 -0
  115. package/src/models/{utils/countryCode.ts → PrimerCountryCode.ts} +1 -1
  116. package/src/models/{utils/currencyCode.ts → PrimerCurrencyCode.ts} +1 -1
  117. package/src/models/PrimerError.ts +20 -0
  118. package/src/models/PrimerPaymentMethodTokenData.ts +130 -0
  119. package/src/models/PrimerSessionIntent.ts +4 -0
  120. package/src/models/PrimerSettings.ts +93 -0
  121. package/src/models/{primer-theme.ts → PrimerTheme.ts} +1 -1
  122. package/src/utils/index.ts +1 -1
  123. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerEventsRN.kt +0 -11
  124. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerIntentRN.kt +0 -80
  125. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerOnClientSessionActionsRequestRN.kt +0 -65
  126. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerRequestRN.kt +0 -9
  127. package/android/src/main/java/com/primerioreactnative/datamodels/PrimerThemeRN.kt +0 -51
  128. package/android/src/main/java/com/primerioreactnative/utils/PrimerEventQueueRN.kt +0 -30
  129. package/ios/DataModels/PrimerIntentRN.swift +0 -10
  130. package/ios/DataModels/PrimerRequestRN.swift +0 -14
  131. package/ios/Pods/Pods.xcodeproj/project.pbxproj +0 -344
  132. package/ios/Pods/Pods.xcodeproj/xcuserdata/aladintaleb.xcuserdatad/xcschemes/Pods-ReactNative.xcscheme +0 -60
  133. package/ios/Pods/Pods.xcodeproj/xcuserdata/aladintaleb.xcuserdatad/xcschemes/xcschememanagement.plist +0 -16
  134. package/ios/Pods/Target Support Files/Pods-ReactNative/Pods-ReactNative-acknowledgements.markdown +0 -3
  135. package/ios/Pods/Target Support Files/Pods-ReactNative/Pods-ReactNative-acknowledgements.plist +0 -29
  136. package/ios/Pods/Target Support Files/Pods-ReactNative/Pods-ReactNative-dummy.m +0 -5
  137. package/ios/Pods/Target Support Files/Pods-ReactNative/Pods-ReactNative.debug.xcconfig +0 -8
  138. package/ios/Pods/Target Support Files/Pods-ReactNative/Pods-ReactNative.release.xcconfig +0 -8
  139. package/ios/ReactNative.xcworkspace/xcuserdata/aladintaleb.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  140. package/lib/commonjs/models/action-request.js +0 -2
  141. package/lib/commonjs/models/client-session-actions-request.js +0 -2
  142. package/lib/commonjs/models/payment-instrument-token.js +0 -30
  143. package/lib/commonjs/models/payment-instrument-token.js.map +0 -1
  144. package/lib/commonjs/models/primer-callbacks.js +0 -2
  145. package/lib/commonjs/models/primer-config.js +0 -2
  146. package/lib/commonjs/models/primer-error.js +0 -4
  147. package/lib/commonjs/models/primer-error.js.map +0 -1
  148. package/lib/commonjs/models/primer-intent.js +0 -4
  149. package/lib/commonjs/models/primer-intent.js.map +0 -1
  150. package/lib/commonjs/models/primer-request.js +0 -2
  151. package/lib/commonjs/models/primer-settings.js +0 -2
  152. package/lib/commonjs/models/primer-theme.js +0 -2
  153. package/lib/commonjs/models/primer.js +0 -2
  154. package/lib/commonjs/models/utils/countryCode.js.map +0 -1
  155. package/lib/commonjs/models/utils/currencyCode.js.map +0 -1
  156. package/lib/commonjs/models/utils/redirectScheme.js +0 -4
  157. package/lib/commonjs/models/utils/redirectScheme.js.map +0 -1
  158. package/lib/module/models/action-request.js +0 -2
  159. package/lib/module/models/client-session-actions-request.js +0 -2
  160. package/lib/module/models/payment-instrument-token.js +0 -28
  161. package/lib/module/models/payment-instrument-token.js.map +0 -1
  162. package/lib/module/models/primer-callbacks.js +0 -2
  163. package/lib/module/models/primer-callbacks.js.map +0 -1
  164. package/lib/module/models/primer-config.js +0 -2
  165. package/lib/module/models/primer-config.js.map +0 -1
  166. package/lib/module/models/primer-error.js +0 -2
  167. package/lib/module/models/primer-error.js.map +0 -1
  168. package/lib/module/models/primer-intent.js +0 -2
  169. package/lib/module/models/primer-intent.js.map +0 -1
  170. package/lib/module/models/primer-request.js +0 -2
  171. package/lib/module/models/primer-request.js.map +0 -1
  172. package/lib/module/models/primer-settings.js +0 -2
  173. package/lib/module/models/primer-settings.js.map +0 -1
  174. package/lib/module/models/primer-theme.js +0 -2
  175. package/lib/module/models/primer-theme.js.map +0 -1
  176. package/lib/module/models/primer.js +0 -2
  177. package/lib/module/models/primer.js.map +0 -1
  178. package/lib/module/models/utils/countryCode.js.map +0 -1
  179. package/lib/module/models/utils/currencyCode.js.map +0 -1
  180. package/lib/module/models/utils/redirectScheme.js +0 -2
  181. package/lib/module/models/utils/redirectScheme.js.map +0 -1
  182. package/lib/typescript/models/action-request.d.ts +0 -10
  183. package/lib/typescript/models/client-session-actions-request.d.ts +0 -15
  184. package/lib/typescript/models/payment-instrument-token.d.ts +0 -76
  185. package/lib/typescript/models/primer-callbacks.d.ts +0 -10
  186. package/lib/typescript/models/primer-config.d.ts +0 -44
  187. package/lib/typescript/models/primer-error.d.ts +0 -8
  188. package/lib/typescript/models/primer-intent.d.ts +0 -13
  189. package/lib/typescript/models/primer-request.d.ts +0 -7
  190. package/lib/typescript/models/primer-settings.d.ts +0 -65
  191. package/lib/typescript/models/primer.d.ts +0 -33
  192. package/lib/typescript/models/utils/redirectScheme.d.ts +0 -3
  193. package/src/models/action-request.ts +0 -12
  194. package/src/models/client-session-actions-request.ts +0 -21
  195. package/src/models/payment-instrument-token.ts +0 -109
  196. package/src/models/primer-callbacks.ts +0 -14
  197. package/src/models/primer-config.ts +0 -55
  198. package/src/models/primer-error.ts +0 -19
  199. package/src/models/primer-intent.ts +0 -49
  200. package/src/models/primer-request.ts +0 -7
  201. package/src/models/primer-settings.ts +0 -73
  202. package/src/models/primer.ts +0 -41
  203. package/src/models/utils/redirectScheme.ts +0 -5
@@ -11,30 +11,33 @@ import UIKit
11
11
 
12
12
  @objc
13
13
  enum PrimerEvents: Int, CaseIterable {
14
- case onClientTokenCallback = 0
15
- case onClientSessionActions
16
- case onTokenizeSuccessCallback
17
- case onVaultSuccess
14
+
15
+ case onCheckoutComplete = 0
16
+ case onBeforeClientSessionUpdate
17
+ case onClientSessionUpdate
18
+ case onBeforePaymentCreate
19
+ case onDismiss
20
+ case onTokenizeSuccess
18
21
  case onResumeSuccess
19
- case onCheckoutDismissed
20
22
  case onError
21
-
22
23
  case detectImplementedRNCallbacks
23
-
24
+
24
25
  var stringValue: String {
25
26
  switch self {
26
- case .onClientTokenCallback:
27
- return "onClientTokenCallback"
28
- case .onClientSessionActions:
29
- return "onClientSessionActions"
30
- case .onTokenizeSuccessCallback:
31
- return "onTokenizeSuccessCallback"
32
- case .onVaultSuccess:
33
- return "onVaultSuccess"
27
+ case .onCheckoutComplete:
28
+ return "onCheckoutComplete"
29
+ case .onBeforeClientSessionUpdate:
30
+ return "onBeforeClientSessionUpdate"
31
+ case .onClientSessionUpdate:
32
+ return "onClientSessionUpdate"
33
+ case .onBeforePaymentCreate:
34
+ return "onBeforePaymentCreate"
35
+ case .onDismiss:
36
+ return "onDismiss"
37
+ case .onTokenizeSuccess:
38
+ return "onTokenizeSuccess"
34
39
  case .onResumeSuccess:
35
40
  return "onResumeSuccess"
36
- case .onCheckoutDismissed:
37
- return "onCheckoutDismissed"
38
41
  case .onError:
39
42
  return "onError"
40
43
  case .detectImplementedRNCallbacks:
@@ -45,155 +48,213 @@ enum PrimerEvents: Int, CaseIterable {
45
48
 
46
49
  @objc(NativePrimer)
47
50
  class RNTPrimer: RCTEventEmitter {
48
-
49
- private var isClientTokenCallbackImplementedInRN: Bool?
50
- private var clientTokenCallback: ((String?, Error?) -> Void)?
51
- private var isOnClientSessionActionsImplementedInRN: Bool?
52
- private var onClientSessionActions: ((String?, Error?) -> Void)?
53
- private var onTokenizeSuccess: ((String?, Error?) -> Void)?
54
- private var onResumeSuccess: ((String?, Error?) -> Void)?
55
- private var implementedReactNativeCallbacks: ImplementedReactNativeCallbacks?
56
-
51
+
52
+ private var primerWillCreatePaymentWithDataDecisionHandler: ((_ errorMessage: String?) -> Void)?
53
+ private var primerDidTokenizePaymentMethodDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
54
+ private var primerDidResumeWithDecisionHandler: ((_ resumeToken: String?, _ errorMessage: String?) -> Void)?
55
+ private var primerDidFailWithErrorDecisionHandler: ((_ errorMessage: String) -> Void)?
56
+ private var implementedRNCallbacks: ImplementedRNCallbacks?
57
+
57
58
  // MARK: - INITIALIZATION & REACT NATIVE SUPPORT
58
-
59
+
59
60
  override class func requiresMainQueueSetup() -> Bool {
60
61
  return true
61
62
  }
62
-
63
+
63
64
  deinit {
64
65
  print("🧨 deinit: \(self) \(Unmanaged.passUnretained(self).toOpaque())")
65
66
  }
66
-
67
+
67
68
  override init() {
68
69
  super.init()
69
70
  PrimerSDK.Primer.shared.delegate = self
70
71
  }
71
-
72
+
72
73
  override func supportedEvents() -> [String]! {
73
74
  return PrimerEvents.allCases.compactMap({ $0.stringValue })
74
75
  }
75
-
76
- // MARK: - API
77
-
76
+
77
+ // MARK: - SDK API
78
+
78
79
  @objc
79
- public func configureWithSettings(_ settingsStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
80
+ public func configure(_ settingsStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
80
81
  DispatchQueue.main.async {
81
82
  do {
82
- try self.configure(settingsStr: settingsStr)
83
+ try self.configure(settingsStr: settingsStr.isEmpty ? nil : settingsStr)
83
84
  resolver(nil)
84
85
  } catch {
85
- self.checkoutFailed(with: error)
86
86
  rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
87
87
  }
88
88
  }
89
89
  }
90
-
90
+
91
91
  @objc
92
- public func configureWithTheme(_ themeStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
92
+ public func showUniversalCheckoutWithClientToken(_ clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
93
+ DispatchQueue.main.async {
94
+ PrimerSDK.Primer.shared.showUniversalCheckout(clientToken: clientToken) { err in
95
+ DispatchQueue.main.async {
96
+ if let err = err {
97
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
98
+ } else {
99
+ resolver(nil)
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ @objc
107
+ public func showVaultManagerWithClientToken(_ clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
108
+ DispatchQueue.main.async {
109
+ PrimerSDK.Primer.shared.showVaultManager(clientToken: clientToken) { err in
110
+ DispatchQueue.main.async {
111
+ if let err = err {
112
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
113
+ } else {
114
+ resolver(nil)
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ @objc
122
+ public func showPaymentMethod(_ paymentMethodStr: String, intent: String, clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
93
123
  DispatchQueue.main.async {
94
124
  do {
95
- try self.configure(themeStr: themeStr)
96
- resolver(nil)
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
+ guard let primerIntent = PrimerSessionIntent(rawValue: intent.lowercased()) else {
133
+ let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Intent \(intent) is not valid."])
134
+ throw err
135
+ }
136
+
137
+ PrimerSDK.Primer.shared.showPaymentMethod(paymentMethodType, withIntent: primerIntent, andClientToken: clientToken) { err in
138
+ DispatchQueue.main.async {
139
+ if let err = err {
140
+ rejecter(err.rnError["errorId"]!, err.rnError["description"], err)
141
+ } else {
142
+ resolver(nil)
143
+ }
144
+ }
145
+ }
97
146
  } catch {
98
- self.checkoutFailed(with: error)
99
147
  rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
100
148
  }
101
149
  }
102
150
  }
103
-
151
+
152
+ @objc
153
+ public func dismiss() {
154
+ Primer.shared.dismiss()
155
+ }
156
+
157
+ // MARK: - DECISION HANDLERS
158
+
159
+ // MARK: Tokenization
160
+
104
161
  @objc
105
- public func showUniversalCheckout(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
162
+ public func handleTokenizationNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
106
163
  DispatchQueue.main.async {
107
- PrimerSDK.Primer.shared.showUniversalCheckout(on: UIViewController(), clientToken: nil)
164
+ self.primerDidTokenizePaymentMethodDecisionHandler?(newClientToken, nil)
165
+ self.primerDidTokenizePaymentMethodDecisionHandler = nil
108
166
  resolver(nil)
109
167
  }
110
168
  }
111
-
169
+
112
170
  @objc
113
- public func showUniversalCheckoutWithClientToken(_ clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
171
+ public func handleTokenizationSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
114
172
  DispatchQueue.main.async {
115
- PrimerSDK.Primer.shared.showUniversalCheckout(on: UIViewController(), clientToken: clientToken)
173
+ self.primerDidTokenizePaymentMethodDecisionHandler?(nil, nil)
174
+ self.primerDidTokenizePaymentMethodDecisionHandler = nil
116
175
  resolver(nil)
117
176
  }
118
177
  }
119
-
178
+
120
179
  @objc
121
- public func showVaultManager(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
180
+ public func handleTokenizationFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
122
181
  DispatchQueue.main.async {
123
- PrimerSDK.Primer.shared.showVaultManager(on: UIViewController(), clientToken: nil)
182
+ self.primerDidTokenizePaymentMethodDecisionHandler?(nil, errorMessage ?? "")
183
+ self.primerDidTokenizePaymentMethodDecisionHandler = nil
124
184
  resolver(nil)
125
185
  }
126
186
  }
127
-
187
+
188
+ // MARK: Resume Payment
189
+
128
190
  @objc
129
- public func showVaultManager(_ clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
191
+ public func handleResumeWithNewClientToken(_ newClientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
130
192
  DispatchQueue.main.async {
131
- PrimerSDK.Primer.shared.showVaultManager(on: UIViewController(), clientToken: clientToken)
193
+ self.primerDidResumeWithDecisionHandler?(newClientToken, nil)
194
+ self.primerDidResumeWithDecisionHandler = nil
132
195
  resolver(nil)
133
196
  }
134
197
  }
135
-
198
+
136
199
  @objc
137
- public func showPaymentMethod(_ clientToken: String, paymentMethodStr: String, intentStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
200
+ public func handleResumeSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
138
201
  DispatchQueue.main.async {
139
- do {
140
- let paymentMethodConfigType = PaymentMethodConfigType(rawValue: paymentMethodStr)
141
-
142
- guard paymentMethodConfigType != PaymentMethodConfigType.other(rawValue: paymentMethodStr) else {
143
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Payment method type \(paymentMethodStr) is not valid."])
144
- throw err
145
- }
146
-
147
- guard let intent = PrimerSessionIntent(rawValue: intentStr) else {
148
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Intent \(intentStr) is not valid."])
149
- throw err
150
- }
151
-
152
- PrimerSDK.Primer.shared.showPaymentMethod(paymentMethodConfigType, withIntent: intent, on: UIViewController(), with: clientToken)
153
- resolver(nil)
154
- } catch {
155
- self.checkoutFailed(with: error)
156
- rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
157
- }
158
-
202
+ self.primerDidResumeWithDecisionHandler?(nil, nil)
203
+ self.primerDidResumeWithDecisionHandler = nil
204
+ resolver(nil)
159
205
  }
160
206
  }
161
-
207
+
162
208
  @objc
163
- public func handleNewClientToken(_ clientToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
209
+ public func handleResumeFailure(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
164
210
  DispatchQueue.main.async {
165
- self.callCallbackWithClientToken(clientToken)
211
+ self.primerDidResumeWithDecisionHandler?(nil, errorMessage ?? "")
212
+ self.primerDidResumeWithDecisionHandler = nil
166
213
  resolver(nil)
167
214
  }
168
215
  }
169
-
216
+
217
+ // MARK: Payment Creation
218
+
170
219
  @objc
171
- public func handleError(_ errorStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
220
+ public func handlePaymentCreationAbort(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
172
221
  DispatchQueue.main.async {
173
- do {
174
- guard let errorData = errorStr.data(using: .utf8) else {
175
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to convert string to data"])
176
- throw err
177
- }
178
-
179
- let err = try JSONDecoder().decode(NativeError.self, from: errorData)
180
- self.callCallbackWithError(err)
181
- resolver(nil)
182
- } catch {
183
- self.checkoutFailed(with: error)
184
- rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
185
- }
222
+ self.primerWillCreatePaymentWithDataDecisionHandler?(errorMessage ?? "")
223
+ self.primerWillCreatePaymentWithDataDecisionHandler = nil
224
+ resolver(nil)
186
225
  }
187
226
  }
188
-
227
+
228
+ @objc
229
+ public func handlePaymentCreationContinue(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
230
+ DispatchQueue.main.async {
231
+ self.primerWillCreatePaymentWithDataDecisionHandler?(nil)
232
+ self.primerWillCreatePaymentWithDataDecisionHandler = nil
233
+ resolver(nil)
234
+ }
235
+ }
236
+
237
+ // MARK: Error Handler
238
+
189
239
  @objc
190
- public func handleSuccess(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
240
+ public func showErrorMessage(_ errorMessage: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
191
241
  DispatchQueue.main.async {
192
- self.callCallbackToContinueFlow()
242
+ self.primerDidFailWithErrorDecisionHandler?(errorMessage ?? "")
243
+ self.primerDidFailWithErrorDecisionHandler = nil
193
244
  resolver(nil)
194
245
  }
195
246
  }
196
-
247
+
248
+ // MARK: Helpers
249
+
250
+ private func configure(settingsStr: String? = nil) throws {
251
+ try PrimerSDK.Primer.shared.configure(settings: PrimerSettings.initialize(with: settingsStr), delegate: self)
252
+ }
253
+
254
+ private func detectImplemetedCallbacks() {
255
+ sendEvent(withName: PrimerEvents.detectImplementedRNCallbacks.stringValue, body: nil)
256
+ }
257
+
197
258
  @objc
198
259
  public func setImplementedRNCallbacks(_ implementedRNCallbacksStr: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
199
260
  DispatchQueue.main.async {
@@ -202,207 +263,192 @@ class RNTPrimer: RCTEventEmitter {
202
263
  let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to convert string to data"])
203
264
  throw err
204
265
  }
205
- self.implementedReactNativeCallbacks = try JSONDecoder().decode(ImplementedReactNativeCallbacks.self, from: implementedRNCallbacksData)
206
- Primer.shared.setImplementedReactNativeCallbacks(self.implementedReactNativeCallbacks!)
266
+ self.implementedRNCallbacks = try JSONDecoder().decode(ImplementedRNCallbacks.self, from: implementedRNCallbacksData)
207
267
  resolver(nil)
208
268
  } catch {
209
- self.checkoutFailed(with: error)
269
+ self.primerDidFailWithError(error, data: nil) { decisionHandler in
270
+
271
+ }
210
272
  rejecter(error.rnError["errorId"]!, error.rnError["description"], error)
211
273
  }
212
274
  }
213
275
  }
214
-
215
- // MARK: - HELPERS
216
-
217
- private func configure(settingsStr: String? = nil, themeStr: String? = nil) throws {
218
- var settings: PrimerSettings?
219
- if let settingsStr = settingsStr {
220
- guard let settingsData = settingsStr.data(using: .utf8) else {
221
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to convert string to data"])
222
- throw err
276
+
277
+ private func handleRNBridgeError(_ error: Error, checkoutData: PrimerCheckoutData?, stopOnDebug: Bool) {
278
+ DispatchQueue.main.async {
279
+ if stopOnDebug {
280
+ assertionFailure(error.localizedDescription)
223
281
  }
224
- let settingsRN = try JSONDecoder().decode(PrimerSettingsRN.self, from: settingsData)
225
- settings = settingsRN.asPrimerSettings()
226
- }
227
-
228
- var theme: PrimerTheme?
229
- if let themeStr = themeStr {
230
- guard let themeData = themeStr.data(using: .utf8) else {
231
- let err = NSError(domain: "native-bridge", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to convert string to data"])
232
- throw err
282
+
283
+ var body: [String: Any] = ["error": error.rnError]
284
+ if let checkoutData = checkoutData,
285
+ let data = try? JSONEncoder().encode(checkoutData),
286
+ let json = try? JSONSerialization.jsonObject(with: data){
287
+ body["checkoutData"] = json
233
288
  }
234
- let themeRN = try JSONDecoder().decode(PrimerThemeRN.self, from: themeData)
235
- theme = themeRN.asPrimerTheme()
289
+ print(body)
290
+ self.sendEvent(withName: PrimerEvents.onError.stringValue, body: body)
236
291
  }
237
-
238
- PrimerSDK.Primer.shared.configure(settings: settings, theme: theme)
239
- }
240
-
241
- private func detectImplemetedCallbacks() {
242
- sendEvent(withName: PrimerEvents.detectImplementedRNCallbacks.stringValue, body: nil)
243
292
  }
244
-
245
- private func callCallbackWithClientToken(_ clientToken: String) {
246
- self.clientTokenCallback?(clientToken, nil)
247
- self.onClientSessionActions?(clientToken, nil)
248
- self.onTokenizeSuccess?(clientToken, nil)
249
- self.onResumeSuccess?(clientToken, nil)
250
- self.removeCallbacksAndHandlers()
251
- }
252
-
253
- private func callCallbackWithError(_ err: Error) {
254
- self.clientTokenCallback?(nil, err)
255
- self.onClientSessionActions?(nil, err)
256
- self.onTokenizeSuccess?(nil, err)
257
- self.onResumeSuccess?(nil, err)
258
- self.removeCallbacksAndHandlers()
259
- }
260
-
261
- private func callCallbackToContinueFlow() {
262
- self.clientTokenCallback?(nil, nil)
263
- self.onClientSessionActions?(nil, nil)
264
- self.onTokenizeSuccess?(nil, nil)
265
- self.onResumeSuccess?(nil, nil)
266
- self.removeCallbacksAndHandlers()
267
- }
268
-
269
- private func removeCallbacksAndHandlers() {
270
- self.clientTokenCallback = nil
271
- self.onClientSessionActions = nil
272
- self.onTokenizeSuccess = nil
273
- self.onResumeSuccess = nil
274
- }
275
-
276
293
  }
277
294
 
295
+ // MARK: - PRIMER DELEGATE
296
+
278
297
  extension RNTPrimer: PrimerDelegate {
279
-
280
- func clientTokenCallback(_ completion: @escaping (String?, Error?) -> Void) {
298
+
299
+ func primerDidCompleteCheckoutWithData(_ data: PrimerCheckoutData) {
281
300
  DispatchQueue.main.async {
282
- if self.implementedReactNativeCallbacks?.isClientTokenCallbackImplemented == true {
283
- self.clientTokenCallback = { (clientToken, err) in
284
- completion(clientToken, err)
285
- self.removeCallbacksAndHandlers()
301
+ if self.implementedRNCallbacks?.isOnCheckoutCompleteImplemented == true {
302
+ do {
303
+ let checkoutData = try JSONEncoder().encode(data)
304
+ let checkoutJson = try JSONSerialization.jsonObject(with: checkoutData, options: .allowFragments)
305
+ self.sendEvent(withName: PrimerEvents.onCheckoutComplete.stringValue, body: checkoutJson)
306
+ } catch {
307
+ self.handleRNBridgeError(error, checkoutData: data, stopOnDebug: true)
286
308
  }
287
- self.sendEvent(withName: PrimerEvents.onClientTokenCallback.stringValue, body: nil)
288
309
  } else {
289
- let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [clientTokenCallback] should had been implemented."])
290
- completion(nil, err)
310
+ let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [onCheckoutComplete] should be implemented."])
311
+ self.handleRNBridgeError(err, checkoutData: data, stopOnDebug: false)
291
312
  }
292
313
  }
293
314
  }
294
-
295
- func onClientSessionActions(_ actions: [ClientSession.Action], resumeHandler: ResumeHandlerProtocol?) {
296
- DispatchQueue.main.async {
297
- if self.implementedReactNativeCallbacks?.isClientSessionActionsImplemented == true {
298
- self.onClientSessionActions = { (newClientToken, err) in
299
- if let err = err {
300
- resumeHandler?.handle(error: err)
301
- } else if let newClientToken = newClientToken {
302
- resumeHandler?.handle(newClientToken: newClientToken)
315
+
316
+ func primerWillCreatePaymentWithData(_ data: PrimerCheckoutPaymentMethodData, decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void) {
317
+ if self.implementedRNCallbacks?.isOnBeforePaymentCreateImplemented == true {
318
+ self.primerWillCreatePaymentWithDataDecisionHandler = { errorMessage in
319
+ DispatchQueue.main.async {
320
+ if let errorMessage = errorMessage {
321
+ decisionHandler(.abortPaymentCreation(withErrorMessage: errorMessage.isEmpty ? nil : errorMessage))
303
322
  } else {
304
- resumeHandler?.handleSuccess()
323
+ decisionHandler(.continuePaymentCreation())
305
324
  }
306
325
  }
307
-
326
+ }
327
+
328
+ DispatchQueue.main.async {
308
329
  do {
309
- let actionsData = try JSONEncoder().encode(actions)
310
- let actionsJson = try JSONSerialization.jsonObject(with: actionsData, options: .allowFragments)
311
- self.sendEvent(withName: PrimerEvents.onClientSessionActions.stringValue, body: actionsJson)
330
+ let checkoutPaymentmethodData = try JSONEncoder().encode(data)
331
+ let checkoutPaymentmethodJson = try JSONSerialization.jsonObject(with: checkoutPaymentmethodData, options: .allowFragments)
332
+ self.sendEvent(withName: PrimerEvents.onBeforePaymentCreate.stringValue, body: checkoutPaymentmethodJson)
312
333
  } catch {
313
- self.checkoutFailed(with: error)
334
+ self.handleRNBridgeError(error, checkoutData: nil, stopOnDebug: true)
314
335
  }
315
- } else {
316
- let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [onClientSessionActions] should had been implemented."])
317
- resumeHandler?.handle(error: err)
318
336
  }
319
-
337
+ } else {
338
+ // RN Dev hasn't implemented this callback, send a decision to continue the flow.
339
+ DispatchQueue.main.async {
340
+ decisionHandler(.continuePaymentCreation())
341
+ }
320
342
  }
321
343
  }
322
-
323
- func tokenAddedToVault(_ token: PaymentMethodToken) {
324
- DispatchQueue.main.async {
325
- if self.implementedReactNativeCallbacks?.isTokenAddedToVaultImplemented == true {
326
- do {
327
- let paymentMethodTokenData = try JSONEncoder().encode(token)
328
- let paymentMethodTokenJson = try JSONSerialization.jsonObject(with: paymentMethodTokenData, options: .allowFragments)
329
- self.sendEvent(withName: PrimerEvents.onVaultSuccess.stringValue, body: paymentMethodTokenJson)
330
- } catch {
331
- self.checkoutFailed(with: error)
332
- }
344
+
345
+ func primerClientSessionWillUpdate() {
346
+ if self.implementedRNCallbacks?.isOnBeforeClientSessionUpdateImplemented == true {
347
+ DispatchQueue.main.async {
348
+ self.sendEvent(withName: PrimerEvents.onBeforeClientSessionUpdate.stringValue, body: nil)
333
349
  }
350
+ } else {
351
+ // RN Dev hasn't implemented this callback, ignore.
334
352
  }
335
353
  }
336
-
337
- func onTokenizeSuccess(_ paymentMethodToken: PaymentMethodToken, resumeHandler: ResumeHandlerProtocol) {
338
- DispatchQueue.main.async {
339
- self.onTokenizeSuccess = { (newClientToken, err) in
340
- if let err = err {
341
- resumeHandler.handle(error: err)
342
- } else if let newClientToken = newClientToken {
343
- resumeHandler.handle(newClientToken: newClientToken)
344
- } else {
345
- resumeHandler.handleSuccess()
346
- }
347
- }
348
-
354
+
355
+ func primerClientSessionDidUpdate(_ clientSession: PrimerClientSession) {
356
+ if self.implementedRNCallbacks?.isOnClientSessionUpdateImplemented == true {
349
357
  do {
350
- let paymentMethodTokenData = try JSONEncoder().encode(paymentMethodToken)
351
- let paymentMethodTokenJson = try JSONSerialization.jsonObject(with: paymentMethodTokenData, options: .allowFragments)
352
- self.sendEvent(withName: PrimerEvents.onTokenizeSuccessCallback.stringValue, body: paymentMethodTokenJson)
358
+ let data = try JSONEncoder().encode(clientSession)
359
+ let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
360
+ DispatchQueue.main.async {
361
+ self.sendEvent(withName: PrimerEvents.onClientSessionUpdate.stringValue, body: json)
362
+ }
353
363
  } catch {
354
- self.checkoutFailed(with: error)
364
+ self.handleRNBridgeError(error, checkoutData: nil, stopOnDebug: true)
355
365
  }
366
+ } else {
367
+ // RN Dev hasn't implemented this callback, ignore.
356
368
  }
357
369
  }
358
-
359
- func onResumeSuccess(_ clientToken: String, resumeHandler: ResumeHandlerProtocol) {
360
- DispatchQueue.main.async {
361
- if self.implementedReactNativeCallbacks?.isOnResumeSuccessImplemented == true {
362
- self.onResumeSuccess = { (newClientToken, err) in
363
- if let err = err {
364
- resumeHandler.handle(error: err)
370
+
371
+ func primerDidTokenizePaymentMethod(_ paymentMethodTokenData: PrimerPaymentMethodTokenData, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
372
+ if self.implementedRNCallbacks?.isOnTokenizeSuccessImplemented == true {
373
+ self.primerDidTokenizePaymentMethodDecisionHandler = { (newClientToken, errorMessage) in
374
+ DispatchQueue.main.async {
375
+ if let errorMessage = errorMessage {
376
+ decisionHandler(.fail(withErrorMessage: errorMessage.isEmpty ? nil : errorMessage))
365
377
  } else if let newClientToken = newClientToken {
366
- resumeHandler.handle(newClientToken: newClientToken)
378
+ decisionHandler(.continueWithNewClientToken(newClientToken))
367
379
  } else {
368
- resumeHandler.handleSuccess()
380
+ decisionHandler(.succeed())
369
381
  }
370
382
  }
371
-
372
- self.sendEvent(withName: PrimerEvents.onResumeSuccess.stringValue, body: ["resumeToken": clientToken])
373
- } else {
374
- let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [onResumeSuccess] should had been implemented."])
375
- resumeHandler.handle(error: err)
376
383
  }
384
+
385
+ do {
386
+ let data = try JSONEncoder().encode(paymentMethodTokenData)
387
+ let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
388
+ DispatchQueue.main.async {
389
+ self.sendEvent(withName: PrimerEvents.onTokenizeSuccess.stringValue, body: json)
390
+ }
391
+ } catch {
392
+ self.handleRNBridgeError(error, checkoutData: nil, stopOnDebug: true)
393
+ }
394
+ } else {
395
+ // RN dev hasn't opted in on listening the tokenization callback.
396
+ // Throw an error if it's the manual flow, ignore if it's the
397
+ // auto flow.
377
398
  }
378
399
  }
379
-
380
- func onResumeError(_ error: Error) {
381
- DispatchQueue.main.async {
382
- if self.implementedReactNativeCallbacks?.isOnResumeErrorImplemented == true {
383
- self.checkoutFailed(with: error)
384
- } else {
385
- let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [onResumeError] should had been implemented."])
386
- self.checkoutFailed(with: err)
400
+
401
+ func primerDidResumeWith(_ resumeToken: String, decisionHandler: @escaping (PrimerResumeDecision) -> Void) {
402
+ if self.implementedRNCallbacks?.isOnResumeSuccessImplemented == true {
403
+ self.primerDidResumeWithDecisionHandler = { (resumeToken, errorMessage) in
404
+ DispatchQueue.main.async {
405
+ if let errorMessage = errorMessage {
406
+ decisionHandler(.fail(withErrorMessage: errorMessage.isEmpty ? nil : errorMessage))
407
+ } else if let resumeToken = resumeToken {
408
+ decisionHandler(.continueWithNewClientToken(resumeToken))
409
+ } else {
410
+ decisionHandler(.succeed())
411
+ }
412
+ }
413
+ }
414
+
415
+ DispatchQueue.main.async {
416
+ self.sendEvent(withName: PrimerEvents.onResumeSuccess.stringValue, body: ["resumeToken": resumeToken])
387
417
  }
418
+ } else {
419
+ // RN dev hasn't opted in on listening the tokenization callback.
420
+ // Throw an error if it's the manual flow.
388
421
  }
389
422
  }
390
-
391
- func onCheckoutDismissed() {
392
- DispatchQueue.main.async {
393
- if self.implementedReactNativeCallbacks?.isOnCheckoutDismissedImplemented == true {
394
- self.sendEvent(withName: PrimerEvents.onCheckoutDismissed.stringValue, body: nil)
395
- } else {
396
- let err = NSError(domain: "native-bridge", code: 1, userInfo: [NSLocalizedDescriptionKey: "Callback [onCheckoutDismissed] should had been implemented."])
397
- self.checkoutFailed(with: err)
423
+
424
+ func primerDidDismiss() {
425
+ if self.implementedRNCallbacks?.isOnDismissImplemented == true {
426
+ DispatchQueue.main.async {
427
+ self.sendEvent(withName: PrimerEvents.onDismiss.stringValue, body: nil)
398
428
  }
429
+ } else {
430
+ // RN dev hasn't opted in on listening SDK dismiss.
431
+ // Ignore!
399
432
  }
400
433
  }
401
-
402
- func checkoutFailed(with error: Error) {
403
- DispatchQueue.main.async {
404
- self.sendEvent(withName: PrimerEvents.onError.stringValue, body: ["error": error.rnError])
434
+
435
+ func primerDidFailWithError(_ error: Error, data: PrimerCheckoutData?, decisionHandler: @escaping ((PrimerErrorDecision) -> Void)) {
436
+ if self.implementedRNCallbacks?.isOnErrorImplemented == true {
437
+ // Set up the callback that will be called by **handleErrorMessage** when the RN
438
+ // bridge invokes it.
439
+ self.primerDidFailWithErrorDecisionHandler = { errorMessage in
440
+ // Callback was called by **handleErrorMessage**.
441
+ DispatchQueue.main.async {
442
+ decisionHandler(.fail(withErrorMessage: errorMessage.isEmpty ? nil : errorMessage))
443
+ }
444
+ }
445
+
446
+ // Send the error message to the RN bridge.
447
+ self.handleRNBridgeError(error, checkoutData: nil, stopOnDebug: false)
448
+
449
+ } else {
450
+ // RN dev hasn't opted in on listening SDK dismiss.
451
+ // Ignore!
405
452
  }
406
453
  }
407
-
408
454
  }