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