@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
@@ -1,170 +1,254 @@
1
1
  package com.primerioreactnative
2
2
 
3
- import android.util.Log
4
3
  import com.primerioreactnative.datamodels.*
5
- import com.primerioreactnative.utils.Keys
4
+ import com.primerioreactnative.extensions.toPrimerCheckoutDataRN
5
+ import com.primerioreactnative.extensions.toPrimerClientSessionRN
6
+ import com.primerioreactnative.extensions.toPrimerPaymentMethodDataRN
6
7
  import com.primerioreactnative.utils.PrimerImplementedRNCallbacks
7
- import com.primerioreactnative.utils.asError
8
8
  import com.primerioreactnative.utils.errorTo
9
- import io.primer.android.CheckoutEventListener
10
- import io.primer.android.completion.ResumeHandler
11
- import io.primer.android.events.CheckoutEvent
9
+ import io.primer.android.PrimerCheckoutListener
10
+ import io.primer.android.completion.PrimerErrorDecisionHandler
11
+ import io.primer.android.completion.PrimerPaymentCreationDecisionHandler
12
+ import io.primer.android.completion.PrimerResumeDecisionHandler
13
+ import io.primer.android.domain.PrimerCheckoutData
14
+ import io.primer.android.domain.action.models.PrimerClientSession
15
+ import io.primer.android.domain.error.models.PrimerError
16
+ import io.primer.android.domain.tokenization.models.PrimerPaymentMethodData
17
+ import io.primer.android.domain.tokenization.models.PrimerPaymentMethodTokenData
12
18
  import kotlinx.serialization.encodeToString
13
19
  import kotlinx.serialization.json.Json
14
20
  import org.json.JSONObject
15
21
 
16
- class PrimerRNEventListener : CheckoutEventListener {
22
+ class PrimerRNEventListener : PrimerCheckoutListener {
17
23
 
18
- private var clientTokenCallback: ((String?, PrimerErrorRN?) -> Unit)? = null
19
- private var onClientSessionActions: ((String?, PrimerErrorRN?) -> Unit)? = null
20
- private var onTokenizeSuccess: ((String?, PrimerErrorRN?) -> Unit)? = null
21
- private var onResumeSuccess: ((String?, PrimerErrorRN?) -> Unit)? = null
24
+ private var paymentCreationDecisionHandler: ((errorMessage: String?) -> Unit)? = null
25
+ private var primerErrorDecisionHandler: ((errorMessage: String?) -> Unit)? = null
26
+ private var tokenizeSuccessDecisionHandler: ((resumeToken: String?, errorMessage: String?) -> Unit)? =
27
+ null
28
+ private var resumeSuccessDecisionHandler: ((resumeToken: String?, errorMessage: String?) -> Unit)? =
29
+ null
22
30
  private var implementedRNCallbacks: PrimerImplementedRNCallbacks? = null
23
31
 
24
- private var resumeHandler: ResumeHandler? = null
25
-
26
32
  var sendEvent: ((eventName: String, paramsJson: JSONObject?) -> Unit)? = null
27
33
  var sendError: ((error: PrimerErrorRN) -> Unit)? = null
34
+ var sendErrorWithCheckoutData: ((error: PrimerErrorRN, checkoutData: PrimerCheckoutDataRN?) -> Unit)? =
35
+ null
36
+
37
+ override fun onCheckoutCompleted(checkoutData: PrimerCheckoutData) {
38
+ if (implementedRNCallbacks?.isOnCheckoutCompleteImplemented == true) {
39
+ sendEvent?.invoke(
40
+ PrimerEvents.ON_CHECKOUT_COMPLETE.eventName,
41
+ JSONObject(Json.encodeToString(checkoutData.toPrimerCheckoutDataRN()))
42
+ )
43
+ } else {
44
+ sendError?.invoke(
45
+ ErrorTypeRN.NativeBridgeFailed
46
+ errorTo "Callback [onCheckoutComplete] should be implemented."
47
+ )
48
+ }
49
+ }
28
50
 
29
- override fun onClientSessionActions(event: CheckoutEvent.OnClientSessionActions) {
30
- val token = PrimerOnClientSessionActionsRequestRN.build(event.data)
31
- val request = JSONObject(Json.encodeToString(token))
32
-
33
- onClientSessionActions = { newClientToken, err ->
34
- when {
35
- err != null -> resumeHandler?.handleError(err.asError())
36
- newClientToken != null -> resumeHandler?.handleNewClientToken(newClientToken)
37
- else -> resumeHandler?.handleSuccess()
51
+ override fun onBeforePaymentCreated(
52
+ paymentMethodData: PrimerPaymentMethodData,
53
+ decisionHandler: PrimerPaymentCreationDecisionHandler
54
+ ) {
55
+ if (implementedRNCallbacks?.isOnBeforePaymentCreateImplemented == true) {
56
+ paymentCreationDecisionHandler = { errorMessage ->
57
+ when {
58
+ errorMessage != null -> decisionHandler.abortPaymentCreation(errorMessage.ifBlank { null })
59
+ else -> decisionHandler.continuePaymentCreation()
60
+ }
38
61
  }
62
+ sendEvent?.invoke(
63
+ PrimerEvents.ON_BEFORE_PAYMENT_CREATE.eventName,
64
+ JSONObject(Json.encodeToString(paymentMethodData.toPrimerPaymentMethodDataRN()))
65
+ )
66
+ } else {
67
+ super.onBeforePaymentCreated(paymentMethodData, decisionHandler)
39
68
  }
69
+ }
40
70
 
41
- event.resumeHandler.handleClientToken(null)
42
- sendEvent?.invoke(PrimerEventsRN.OnClientSessionActions.string, request)
43
- }
44
-
45
- override fun onCheckoutEvent(e: CheckoutEvent) {
46
- when (e) {
47
- is CheckoutEvent.TokenizationSuccess -> {
48
- val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(e.data)
49
- val request = JSONObject(Json.encodeToString(token))
50
- onTokenizeSuccess = { newClientToken, err ->
51
- when {
52
- err != null -> resumeHandler?.handleError(err.asError())
53
- newClientToken != null -> resumeHandler?.handleNewClientToken(newClientToken)
54
- else -> resumeHandler?.handleSuccess()
55
- }
56
- }
71
+ override fun onBeforeClientSessionUpdated() {
72
+ if (implementedRNCallbacks?.isOnBeforeClientSessionUpdateImplemented == true) {
73
+ sendEvent?.invoke(
74
+ PrimerEvents.ON_BEFORE_CLIENT_SESSION_UPDATE.eventName,
75
+ null
76
+ )
77
+ } else {
78
+ super.onBeforeClientSessionUpdated()
79
+ }
80
+ }
57
81
 
58
- resumeHandler = e.resumeHandler
59
- sendEvent?.invoke(PrimerEventsRN.OnTokenizeSuccessCallback.string, request)
60
- }
61
- is CheckoutEvent.ResumeSuccess -> {
62
- val token = e.resumeToken
63
- if (implementedRNCallbacks?.isOnResumeSuccessImplemented == true) {
64
- onResumeSuccess = { newClientToken, err ->
65
- when {
66
- err != null -> resumeHandler?.handleError(err.asError())
67
- newClientToken != null -> resumeHandler?.handleNewClientToken(newClientToken)
68
- else -> resumeHandler?.handleSuccess()
69
- }
70
- }
71
-
72
- resumeHandler = e.resumeHandler
73
- val resumeToken = mapOf(Keys.RESUME_TOKEN to token)
74
- sendEvent?.invoke(
75
- PrimerEventsRN.OnResumeSuccess.string,
76
- JSONObject(Json.encodeToString(resumeToken))
77
- )
78
- } else {
79
- sendError?.invoke(ErrorTypeRN.InitFailed
80
- errorTo "Callback [onResumeSuccess] should had been implemented.")
81
- }
82
- }
83
- is CheckoutEvent.ApiError -> {
84
- Log.e("PrimerRN", "ApiError: ${e.data}")
85
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo e.data.description
86
- sendError?.invoke(exception)
87
- }
88
- is CheckoutEvent.TokenAddedToVault -> {
89
- val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(e.data)
90
- val request = JSONObject(Json.encodeToString(token))
91
- sendEvent?.invoke(
92
- PrimerEventsRN.OnVaultSuccess.string,
93
- request
94
- )
95
- }
96
- is CheckoutEvent.TokenSelected -> {
97
- val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(e.data)
98
- val request = JSONObject(Json.encodeToString(token))
99
- onTokenizeSuccess = { newClientToken, err ->
100
- when {
101
- err != null -> resumeHandler?.handleError(err.asError())
102
- newClientToken != null -> resumeHandler?.handleNewClientToken(newClientToken)
103
- else -> resumeHandler?.handleSuccess()
104
- }
105
- }
82
+ override fun onClientSessionUpdated(clientSession: PrimerClientSession) {
83
+ if (implementedRNCallbacks?.isOnClientSessionUpdateImplemented == true) {
84
+ sendEvent?.invoke(
85
+ PrimerEvents.ON_CLIENT_SESSION_UPDATE.eventName,
86
+ JSONObject(Json.encodeToString(clientSession.toPrimerClientSessionRN()))
87
+ )
88
+ } else {
89
+ super.onClientSessionUpdated(clientSession)
90
+ }
91
+ }
106
92
 
107
- resumeHandler = e.resumeHandler
108
- sendEvent?.invoke(PrimerEventsRN.OnTokenizeSuccessCallback.string, request)
109
- }
110
- is CheckoutEvent.Exit -> {
111
- removeCallbacksAndHandlers()
112
- if (implementedRNCallbacks?.isOnCheckoutDismissedImplemented == true) {
113
- sendEvent?.invoke(
114
- PrimerEventsRN.OnCheckoutDismissed.string,
115
- null
116
- )
117
- } else {
118
- sendError?.invoke(ErrorTypeRN.InitFailed
119
- errorTo "Callback [onCheckoutDismissed] should had been implemented.")
120
- }
121
- }
122
- is CheckoutEvent.TokenizationError -> {
123
- if (implementedRNCallbacks?.isCheckoutFailedImplemented == true) {
124
- Log.e("PrimerRN", "TokenizationError: ${e.data}")
125
- val exception = ErrorTypeRN.TokenizationFailed errorTo e.data.description
126
- sendError?.invoke(exception)
127
- } else {
128
- sendError?.invoke(ErrorTypeRN.InitFailed
129
- errorTo "Callback [onError] should had been implemented.")
93
+ override fun onTokenizeSuccess(
94
+ paymentMethodTokenData: PrimerPaymentMethodTokenData,
95
+ decisionHandler: PrimerResumeDecisionHandler
96
+ ) {
97
+ if (implementedRNCallbacks?.isOnTokenizeSuccessImplemented == true) {
98
+ val token = PrimerPaymentInstrumentTokenRN.fromPaymentMethodToken(paymentMethodTokenData)
99
+ val request = JSONObject(Json.encodeToString(token))
100
+ tokenizeSuccessDecisionHandler = { newClientToken, err ->
101
+ when {
102
+ err != null -> decisionHandler.handleFailure(err.ifBlank { null })
103
+ newClientToken != null -> decisionHandler.continueWithNewClientToken(newClientToken)
104
+ else -> decisionHandler.handleSuccess()
130
105
  }
131
106
  }
132
- else -> Unit
107
+ sendEvent?.invoke(PrimerEvents.ON_TOKENIZE_SUCCESS.eventName, request)
108
+ } else {
109
+ sendError?.invoke(
110
+ ErrorTypeRN.NativeBridgeFailed
111
+ errorTo "Callback [onTokenizeSuccess] should be implemented."
112
+ )
133
113
  }
134
114
  }
135
115
 
136
- fun onClientTokenCallback(clientToken: String?, error: PrimerErrorRN?) {
137
- this.clientTokenCallback?.invoke(clientToken, error)
138
- sendEvent?.invoke(PrimerEventsRN.OnClientTokenCallback.string, null)
116
+ override fun onResumeSuccess(
117
+ resumeToken: String,
118
+ decisionHandler: PrimerResumeDecisionHandler
119
+ ) {
120
+ if (implementedRNCallbacks?.isOnResumeSuccessImplemented == true) {
121
+ resumeSuccessDecisionHandler = { newClientToken, err ->
122
+ when {
123
+ err != null -> decisionHandler.handleFailure(err.ifBlank { null })
124
+ newClientToken != null -> decisionHandler.continueWithNewClientToken(newClientToken)
125
+ else -> decisionHandler.handleSuccess()
126
+ }
127
+ }
128
+
129
+ val resumeToken = mapOf(Keys.RESUME_TOKEN to resumeToken)
130
+ sendEvent?.invoke(
131
+ PrimerEvents.ON_RESUME_SUCCESS.eventName,
132
+ JSONObject(Json.encodeToString(resumeToken))
133
+ )
134
+ } else {
135
+ sendError?.invoke(
136
+ ErrorTypeRN.NativeBridgeFailed
137
+ errorTo "Callback [onResumeSuccess] should be implemented."
138
+ )
139
+ }
139
140
  }
140
141
 
141
- fun onClientSessionActions(clientToken: String?, error: PrimerErrorRN?) {
142
- if (implementedRNCallbacks?.isClientSessionActionsImplemented == true) {
143
- this.onClientSessionActions?.invoke(clientToken, error)
142
+ override fun onDismissed() {
143
+ if (implementedRNCallbacks?.isOnDismissImplemented == true) {
144
+ sendEvent?.invoke(
145
+ PrimerEvents.ON_DISMISS.eventName,
146
+ null
147
+ )
144
148
  }
149
+ removeCallbacksAndHandlers()
145
150
  }
146
151
 
147
- fun onTokenizeSuccess(clientToken: String?, error: PrimerErrorRN?) {
148
- this.onTokenizeSuccess?.invoke(clientToken, error)
152
+ override fun onFailed(
153
+ error: PrimerError,
154
+ checkoutData: PrimerCheckoutData?,
155
+ errorHandler: PrimerErrorDecisionHandler?
156
+ ) {
157
+ if (implementedRNCallbacks?.isOnErrorImplemented == true) {
158
+ primerErrorDecisionHandler = { errorMessage: String? ->
159
+ errorHandler?.showErrorMessage(errorMessage?.ifBlank { null })
160
+ }
161
+ sendErrorWithCheckoutData?.invoke(
162
+ PrimerErrorRN(
163
+ error.errorId,
164
+ error.description,
165
+ error.recoverySuggestion
166
+ ), checkoutData?.toPrimerCheckoutDataRN()
167
+ )
168
+ } else {
169
+ super.onFailed(error, checkoutData, errorHandler)
170
+ }
149
171
  }
150
172
 
151
- fun onResumeSuccess(clientToken: String?, error: PrimerErrorRN?) {
152
- if (implementedRNCallbacks?.isOnResumeSuccessImplemented == true) {
153
- this.onResumeSuccess?.invoke(clientToken, error)
173
+ override fun onFailed(error: PrimerError, errorHandler: PrimerErrorDecisionHandler?) {
174
+ if (implementedRNCallbacks?.isOnErrorImplemented == true) {
175
+ primerErrorDecisionHandler = { errorMessage: String? ->
176
+ errorHandler?.showErrorMessage(errorMessage)
177
+ }
178
+ sendError?.invoke(PrimerErrorRN(error.errorId, error.description, error.recoverySuggestion))
154
179
  } else {
155
- sendError?.invoke(ErrorTypeRN.CheckoutFlowFailed
156
- errorTo "Callback [onResumeSuccess] should had been implemented.")
180
+ super.onFailed(error, errorHandler)
157
181
  }
158
182
  }
159
183
 
160
- fun removeCallbacksAndHandlers() {
161
- clientTokenCallback = null
162
- onClientSessionActions = null
163
- onTokenizeSuccess = null
164
- onResumeSuccess = null
184
+ // region tokenization handlers
185
+ fun handleTokenizationNewClientToken(newClientToken: String) {
186
+ tokenizeSuccessDecisionHandler?.invoke(newClientToken, null)
187
+ tokenizeSuccessDecisionHandler = null
188
+ }
189
+
190
+ fun handleTokenizationSuccess() {
191
+ tokenizeSuccessDecisionHandler?.invoke(null, null)
192
+ tokenizeSuccessDecisionHandler = null
165
193
  }
166
194
 
195
+ fun handleTokenizationFailure(errorMessage: String) {
196
+ tokenizeSuccessDecisionHandler?.invoke(
197
+ null,
198
+ errorMessage.ifBlank { null }
199
+ )
200
+ tokenizeSuccessDecisionHandler = null
201
+ }
202
+ // endregion
203
+
204
+ // region resume handlers
205
+ fun handleResumeNewClientToken(newClientToken: String) {
206
+ resumeSuccessDecisionHandler?.invoke(newClientToken, null)
207
+ resumeSuccessDecisionHandler = null
208
+ }
209
+
210
+ fun handleResumeSuccess() {
211
+ resumeSuccessDecisionHandler?.invoke(null, null)
212
+ resumeSuccessDecisionHandler = null
213
+ }
214
+
215
+ fun handleResumeFailure(errorMessage: String) {
216
+ resumeSuccessDecisionHandler?.invoke(
217
+ null,
218
+ errorMessage.ifBlank { null }
219
+ )
220
+ resumeSuccessDecisionHandler = null
221
+ }
222
+ // endregion
223
+
224
+ // region payment create handlers
225
+ fun handlePaymentCreationContinue() {
226
+ paymentCreationDecisionHandler?.invoke(null)
227
+ paymentCreationDecisionHandler = null
228
+ }
229
+
230
+ fun handlePaymentCreationAbort(errorMessage: String) {
231
+ paymentCreationDecisionHandler?.invoke(errorMessage)
232
+ paymentCreationDecisionHandler = null
233
+ }
234
+ // endregion
235
+
236
+ // region error handlers
237
+ fun handleErrorMessage(errorMessage: String) {
238
+ primerErrorDecisionHandler?.invoke(errorMessage)
239
+ primerErrorDecisionHandler = null
240
+ }
241
+ // endregion
242
+
167
243
  fun setImplementedCallbacks(implementedRNCallbacks: PrimerImplementedRNCallbacks) {
168
244
  this.implementedRNCallbacks = implementedRNCallbacks
169
245
  }
246
+
247
+ private fun removeCallbacksAndHandlers() {
248
+ paymentCreationDecisionHandler = null
249
+ primerErrorDecisionHandler = null
250
+ tokenizeSuccessDecisionHandler = null
251
+ resumeSuccessDecisionHandler = null
252
+ implementedRNCallbacks = null
253
+ }
170
254
  }
@@ -0,0 +1,244 @@
1
+ package com.primerioreactnative
2
+
3
+ import android.util.Log
4
+ import androidx.core.content.ContextCompat
5
+ import com.facebook.react.bridge.*
6
+ import com.facebook.react.modules.core.DeviceEventManagerModule
7
+ import com.primerioreactnative.datamodels.*
8
+ import com.primerioreactnative.huc.assets.AssetsManager
9
+ import com.primerioreactnative.huc.assets.AssetsManager.drawableToBitmap
10
+ import com.primerioreactnative.huc.assets.AssetsManager.getFile
11
+ import com.primerioreactnative.huc.events.PrimerHeadlessUniversalCheckoutEvent
12
+ import com.primerioreactnative.utils.PrimerHeadlessUniversalCheckoutImplementedRNCallbacks
13
+ import com.primerioreactnative.utils.convertJsonToMap
14
+ import com.primerioreactnative.utils.errorTo
15
+ import io.primer.android.ExperimentalPrimerApi
16
+ import io.primer.android.components.PrimerHeadlessUniversalCheckout
17
+ import io.primer.android.components.ui.assets.ImageType
18
+ import io.primer.android.data.configuration.models.PaymentMethodType
19
+ import io.primer.android.data.configuration.models.PrimerPaymentMethodType
20
+ import kotlinx.serialization.decodeFromString
21
+ import kotlinx.serialization.encodeToString
22
+ import kotlinx.serialization.json.Json
23
+ import org.json.JSONObject
24
+
25
+ @ExperimentalPrimerApi
26
+ class PrimerRNHeadlessUniversalCheckout(
27
+ private val reactContext: ReactApplicationContext,
28
+ private val json: Json,
29
+ ) : ReactContextBaseJavaModule(reactContext) {
30
+
31
+ private val listener = PrimerRNHeadlessUniversalCheckoutListener()
32
+
33
+ init {
34
+ listener.sendEvent = { eventName, paramsJson -> sendEvent(eventName, paramsJson) }
35
+ listener.sendError = { paramsJson -> onError(paramsJson) }
36
+ listener.sendErrorWithCheckoutData =
37
+ { paramsJson, checkoutData -> onError(paramsJson, checkoutData) }
38
+ }
39
+
40
+ override fun getName(): String {
41
+ return "PrimerHeadlessUniversalCheckout"
42
+ }
43
+
44
+ @ReactMethod
45
+ fun startWithClientToken(
46
+ clientToken: String,
47
+ settingsStr: String?,
48
+ errorCallback: Callback,
49
+ successCallback: Callback
50
+ ) {
51
+ listener.successCallback = successCallback
52
+ try {
53
+ val settings =
54
+ if (settingsStr.isNullOrBlank()) PrimerSettingsRN() else json.decodeFromString(
55
+ settingsStr
56
+ )
57
+ PrimerHeadlessUniversalCheckout.current.start(
58
+ reactContext,
59
+ clientToken,
60
+ settings.toPrimerSettings(),
61
+ listener
62
+ )
63
+ } catch (e: Exception) {
64
+ errorCallback.invoke(
65
+ json.encodeToString(
66
+ ErrorTypeRN.NativeBridgeFailed errorTo
67
+ "failed to initialise PrimerHeadlessUniversalCheckout SDK, error: $e",
68
+ )
69
+ )
70
+ }
71
+ }
72
+
73
+ @ReactMethod
74
+ fun showPaymentMethod(paymentMethodTypeStr: String, promise: Promise) {
75
+ val primerPaymentMethodType = PrimerPaymentMethodType.safeValueOf(paymentMethodTypeStr)
76
+ if (primerPaymentMethodType == PaymentMethodType.UNKNOWN) {
77
+ val exception =
78
+ ErrorTypeRN.NativeBridgeFailed errorTo "Payment method type $paymentMethodTypeStr is not valid."
79
+ onError(exception)
80
+ promise.reject(exception.errorId, exception.description)
81
+ } else {
82
+ PrimerHeadlessUniversalCheckout.current.showPaymentMethod(
83
+ reactContext,
84
+ primerPaymentMethodType
85
+ )
86
+ promise.resolve(null)
87
+ }
88
+ }
89
+
90
+ @ReactMethod
91
+ fun disposePrimerHeadlessUniversalCheckout() {
92
+ PrimerHeadlessUniversalCheckout.current.cleanup()
93
+ listener.removeCallbacksAndHandlers()
94
+ }
95
+
96
+ @ReactMethod
97
+ fun getAssetForPaymentMethodType(
98
+ paymentMethodType: String,
99
+ assetType: String,
100
+ errorCallback: Callback,
101
+ successCallback: Callback
102
+ ) {
103
+
104
+ val primerPaymentMethodType = PrimerPaymentMethodType.safeValueOf(paymentMethodType)
105
+ val type = ImageType.values().find { it.name.equals(assetType, ignoreCase = true) }
106
+ when {
107
+ primerPaymentMethodType == PaymentMethodType.UNKNOWN -> {
108
+ errorCallback.invoke(
109
+ json.encodeToString(
110
+ ErrorTypeRN.InvalidPaymentMethodType errorTo
111
+ "Asset for $paymentMethodType does not exist, make sure you don't have any typos."
112
+ )
113
+ )
114
+ }
115
+ type == null -> {
116
+ errorCallback.invoke(
117
+ json.encodeToString(
118
+ ErrorTypeRN.AssetMismatch errorTo
119
+ "You have provided assetType=$assetType, but variable assetType can be 'LOGO' or 'ICON'."
120
+ )
121
+ )
122
+ }
123
+ else -> {
124
+ PrimerHeadlessUniversalCheckout.getAsset(primerPaymentMethodType, type)?.let { resourceId ->
125
+ val file = getFile(reactContext, paymentMethodType)
126
+ AssetsManager.saveBitmapToFile(
127
+ file,
128
+ drawableToBitmap(ContextCompat.getDrawable(reactContext, resourceId)!!),
129
+ )
130
+ successCallback.invoke("file://${file.absolutePath}")
131
+ } ?: run {
132
+ errorCallback.invoke(
133
+ json.encodeToString(
134
+ ErrorTypeRN.AssetMissing errorTo
135
+ "Failed to find $assetType for $paymentMethodType"
136
+ )
137
+ )
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ // region tokenization handlers
144
+ @ReactMethod
145
+ fun handleTokenizationNewClientToken(newClientToken: String, promise: Promise) {
146
+ listener.handleTokenizationNewClientToken(newClientToken)
147
+ promise.resolve(null)
148
+ }
149
+
150
+ @ReactMethod
151
+ fun handleTokenizationSuccess(promise: Promise) {
152
+ listener.handleTokenizationSuccess(promise)
153
+ }
154
+
155
+ @ReactMethod
156
+ fun handleTokenizationFailure(errorMessage: String?, promise: Promise) {
157
+ listener.handleTokenizationFailure(errorMessage.orEmpty(), promise)
158
+ }
159
+ // endregion
160
+
161
+ // region resume handlers
162
+ @ReactMethod
163
+ fun handleResumeNewClientToken(newClientToken: String, promise: Promise) {
164
+ listener.handleResumeNewClientToken(newClientToken)
165
+ promise.resolve(null)
166
+ }
167
+
168
+ @ReactMethod
169
+ fun handleResumeSuccess(promise: Promise) {
170
+ listener.handleResumeSuccess(promise)
171
+ }
172
+
173
+ @ReactMethod
174
+ fun handleResumeFailure(errorMessage: String?, promise: Promise) {
175
+ listener.handleResumeFailure(errorMessage.orEmpty(), promise)
176
+ }
177
+ // endregion
178
+
179
+ // region payment handlers
180
+ @ReactMethod
181
+ fun handlePaymentCreationContinue(promise: Promise) {
182
+ listener.handlePaymentCreationContinue()
183
+ promise.resolve(null)
184
+ }
185
+
186
+ @ReactMethod
187
+ fun handlePaymentCreationAbort(errorMessage: String?, promise: Promise) {
188
+ listener.handlePaymentCreationAbort(errorMessage.orEmpty())
189
+ promise.resolve(null)
190
+ }
191
+ // endregion
192
+
193
+ @ReactMethod
194
+ fun setImplementedRNCallbacks(implementedRNCallbacksStr: String, promise: Promise) {
195
+ try {
196
+ Log.d(TAG, "implementedRNCallbacks: $implementedRNCallbacksStr")
197
+ val implementedRNCallbacks =
198
+ json.decodeFromString<PrimerHeadlessUniversalCheckoutImplementedRNCallbacks>(
199
+ implementedRNCallbacksStr
200
+ )
201
+ listener.setImplementedCallbacks(implementedRNCallbacks)
202
+ promise.resolve(null)
203
+ } catch (e: Exception) {
204
+ val exception =
205
+ ErrorTypeRN.NativeBridgeFailed errorTo "Implemented callbacks $implementedRNCallbacksStr is not valid."
206
+ onError(exception)
207
+ promise.reject(exception.errorId, exception.description, e)
208
+ }
209
+ }
210
+
211
+ private fun onError(exception: PrimerErrorRN, checkoutDataRN: PrimerCheckoutDataRN? = null) {
212
+ val params = Arguments.createMap()
213
+ val errorJson = JSONObject(Json.encodeToString(exception))
214
+ val errorData = prepareData(errorJson)
215
+ params.putMap(Keys.ERROR, errorData)
216
+ checkoutDataRN?.let {
217
+ val checkoutDataJson = JSONObject(Json.encodeToString(it))
218
+ val checkoutData = prepareData(checkoutDataJson)
219
+ params.putMap(Keys.CHECKOUT_DATA, checkoutData)
220
+ }
221
+ sendEvent(PrimerHeadlessUniversalCheckoutEvent.ON_ERROR.eventName, params)
222
+ }
223
+
224
+ private fun sendEvent(name: String, params: WritableMap) {
225
+ reactApplicationContext.getJSModule(
226
+ DeviceEventManagerModule.RCTDeviceEventEmitter::class.java
227
+ ).emit(name, params)
228
+ }
229
+
230
+ private fun sendEvent(name: String, data: JSONObject?) {
231
+ val params = prepareData(data)
232
+ reactApplicationContext.getJSModule(
233
+ DeviceEventManagerModule.RCTDeviceEventEmitter::class.java
234
+ ).emit(name, params)
235
+ }
236
+
237
+ private fun prepareData(data: JSONObject?): WritableMap {
238
+ return data?.let { convertJsonToMap(data) } ?: Arguments.createMap()
239
+ }
240
+
241
+ private companion object {
242
+ const val TAG = "PrimerHUC"
243
+ }
244
+ }