@primer-io/react-native 0.15.4 → 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 +122 -143
  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 +69 -150
  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 +297 -237
  31. package/ios/ReactNative.xcodeproj/project.pbxproj +14 -14
  32. package/lib/commonjs/Primer.js +187 -176
  33. package/lib/commonjs/Primer.js.map +1 -1
  34. package/lib/commonjs/RNPrimer.js +102 -40
  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 +187 -162
  63. package/lib/module/Primer.js.map +1 -1
  64. package/lib/module/RNPrimer.js +102 -40
  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 +214 -196
  109. package/src/RNPrimer.ts +135 -50
  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 -40
  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 -63
  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 -50
  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 -70
  202. package/src/models/primer.ts +0 -41
  203. package/src/models/utils/redirectScheme.ts +0 -5
package/README.md CHANGED
@@ -10,49 +10,139 @@ Official React Native SDK plugin for [Primer](https://primer.io)
10
10
  <img src="https://img.shields.io/npm/v/@primer-io/react-native" />
11
11
  </p>
12
12
 
13
- ---
13
+ **Note:** This quick start guide addresses the platform-specific integration points only. As everything prior to that (e.g. creating a client token) is the same for all the guidelines.
14
14
 
15
- The simplest payments integration, ever. Integrate payments once with just a few lines of code, and empower ops teams to automate complex business logic with Primer.
15
+ # Set up the Universal Checkout
16
16
 
17
- ### Features of the React Native SDK
17
+ ## Step 1. Install the SDK
18
18
 
19
- - 💳 Create great payment experiences with our Universal Checkout
19
+ Add the SDK package.
20
20
 
21
- - 🧩 Connect and configure new payment methods with only a few lines of code
21
+ ```sh
22
+ \# With yarn
23
+ yarn add @primer-io/react-native
24
+
25
+ \# With npm
26
+ npm i @primer-io/react-native --save
27
+ ```
28
+
29
+ Once you are done, navigate to the \/ios folder and run pod install.
22
30
 
23
- - Dynamically handle 3DS 2.0 across processors and be SCA ready
31
+ ## Step 2. Initialize the SDK
24
32
 
25
- - ♻️ Store payment methods for one-click checkout, recurring and repeat payments
33
+ Import the Primer SDK, construct your settings and call the SDK’s configure function.
26
34
 
27
- - 🔒 Always PCI compliant without redirecting customers
35
+ ```js
36
+ import * as React from 'react';
37
+ import {
38
+ Primer,
39
+ PrimerSettings,
40
+ PrimerCheckoutData
41
+ } from '@primer-io/react-native';
42
+
43
+ const CheckoutScreen = (props: any) => {
44
+
45
+ const onCheckoutComplete = (checkoutData: PrimerCheckoutData) => {
46
+ // Perform an action based on the payment creation response
47
+ // ex. show success screen, redirect to order confirmation view, etc.
48
+ };
49
+
50
+ React.useEffect(() => {
51
+ const settings: PrimerSettings = {
52
+ onCheckoutComplete: onCheckoutComplete
53
+ };
54
+
55
+ Primer.configure(settings)
56
+ .then(() => {
57
+ // SDK is initialized sucessfully
58
+ })
59
+ .catch (err => {
60
+ // SDK failed to initialize
61
+ })
62
+ }, []);
63
+ }
64
+ ```
28
65
 
29
- ---
66
+ ## Step 3. Generate a client token
30
67
 
31
- ## 💾 Installation
68
+ **Note:** Check our guide on how to set up the client session [here](https://primer.io/docs/accept-payments/manage-client-sessions).
32
69
 
33
- ```sh
34
- npm i @primer-io/react-native
70
+ Make an API call to your backend to fetch a Client Token. Here is a simple example of how it can be done from your component. Once successful store your Client Token for future use.
71
+
72
+ ```js
73
+ const CheckoutScreen = (props: any) => {
74
+
75
+ // ...
76
+
77
+ const onUniversalCheckoutButtonTapped = async () => {
78
+ try {
79
+ // Make an API request to your backend to create a client session
80
+ // and fetch a client token.
81
+ const clientToken = await createClientSession(clientSessionRequestParams);
82
+ } catch (err) {
83
+ // ...
84
+ }
85
+ };
86
+ }
35
87
  ```
36
88
 
37
- ## 🔧 Usage
89
+ ## Step 4. Show Universal Checkout
90
+
91
+ At this step, you should have a Client Token available. Call the `showUniversalCheckout(clientToken)` function, with the Client Token (as shown below) to present Universal Checkout.
38
92
 
39
93
  ```js
40
- import { Primer } from '@primer-io/react-native';
94
+ const CheckoutScreen = (props: any) => {
41
95
 
42
- // fetch Primer client token from backend.
43
- const token: string = await fetchClientToken();
96
+ // ...
44
97
 
45
- // configure listeners and settings.
46
- const onTokenizeSuccess = async (t, handler) => {
47
- const payment = await createPayment(t);
48
- handler.handleSuccess(); // resume the checkout flow with success message.
49
- };
98
+ const onUniversalCheckoutButtonTapped = async () => {
99
+ try {
100
+ // ...
50
101
 
51
- // show Universal Checkout with client token and config.
52
- Primer.showUniversalCheckout(token, { onTokenizeSuccess });
102
+ // Present Universal Checkout
103
+ await Primer.showUniversalCheckout(clientToken);
104
+ } catch (err) {
105
+ // ...
106
+ }
107
+ };
108
+ }
53
109
  ```
54
110
 
55
- For more info & help troubleshooting, check out our 🔥 [docs](https://www.notion.so/primerio/Quick-Start-6c5eb61e5bbe426ca66244259e06048e)
111
+ ## Full Code Snippet
112
+
113
+ ```js
114
+ import * as React from 'react';
115
+ import {
116
+ Primer,
117
+ PrimerSettings,
118
+ PrimerCheckoutData
119
+ } from '@primer-io/react-native';
120
+
121
+ const CheckoutScreen = async (props: any) => {
122
+ const onCheckoutComplete = (checkoutData: PrimerCheckoutData) => {
123
+ // Show a success screen
124
+ };
125
+
126
+ const onUniversalCheckoutButtonTapped = async () => {
127
+ const settings: PrimerSettings = {
128
+ onCheckoutComplete: onCheckoutComplete
129
+ };
130
+
131
+ // Configure the SDK
132
+ await Primer.configure(settings);
133
+
134
+ // Ask your backend to create a client session
135
+ const clientToken = await createClientSession(clientSessionRequestParams);
136
+
137
+ // Present Universal Checkout
138
+ await Primer.showUniversalCheckout(clientToken);
139
+ };
140
+ }
141
+ ```
142
+
143
+ You should now be able to see Universal Checkout! The user can now interact with Universal Checkout, and the SDK will create the payment. The payment’s data will be returned in the onCheckoutComplete callback configured in Step 2.
144
+
145
+ **Note:** For more info & help troubleshooting, check out our [docs](http://primer.io/docs).
56
146
 
57
147
  ## 📚 License
58
148
 
@@ -4,6 +4,7 @@ buildscript {
4
4
 
5
5
  repositories {
6
6
  google()
7
+ mavenLocal()
7
8
  jcenter()
8
9
  }
9
10
 
@@ -52,9 +53,13 @@ android {
52
53
  sourceCompatibility JavaVersion.VERSION_1_8
53
54
  targetCompatibility JavaVersion.VERSION_1_8
54
55
  }
56
+ kotlinOptions {
57
+ freeCompilerArgs += '-Xjvm-default=all'
58
+ }
55
59
  }
56
60
 
57
61
  repositories {
62
+ mavenLocal()
58
63
  mavenCentral()
59
64
  jcenter()
60
65
  google()
@@ -131,6 +136,6 @@ dependencies {
131
136
  // noinspection GradleDynamicVersion
132
137
  api 'com.facebook.react:react-native:+'
133
138
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
134
- implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1"
135
- implementation 'io.primer:android:1.13.0'
139
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3"
140
+ implementation 'io.primer:android:2.0.0'
136
141
  }
@@ -1,4 +1,4 @@
1
- ReactNative_kotlinVersion=1.5.0
2
- ReactNative_compileSdkVersion=29
1
+ ReactNative_kotlinVersion=1.6.21
2
+ ReactNative_compileSdkVersion=31
3
3
  ReactNative_buildToolsVersion=29.0.2
4
- ReactNative_targetSdkVersion=29
4
+ ReactNative_targetSdkVersion=31
@@ -5,77 +5,48 @@ import com.facebook.react.bridge.*
5
5
  import com.facebook.react.modules.core.DeviceEventManagerModule
6
6
  import com.primerioreactnative.datamodels.*
7
7
  import com.primerioreactnative.utils.PrimerImplementedRNCallbacks
8
+ import com.primerioreactnative.utils.convertJsonToMap
8
9
  import com.primerioreactnative.utils.errorTo
9
- import io.primer.android.PaymentMethodIntent
10
10
  import io.primer.android.Primer
11
- import io.primer.android.model.dto.PrimerConfig
12
- import io.primer.android.model.dto.PrimerPaymentMethod
11
+ import io.primer.android.PrimerSessionIntent
12
+ import io.primer.android.data.configuration.models.PrimerPaymentMethodType
13
+ import io.primer.android.data.settings.PrimerSettings
13
14
  import kotlinx.serialization.decodeFromString
14
15
  import kotlinx.serialization.encodeToString
15
16
  import kotlinx.serialization.json.Json
16
17
  import org.json.JSONObject
17
18
 
18
-
19
19
  class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
20
-
21
- private var settings: PrimerSettingsRN = PrimerSettingsRN()
22
- private var theme: PrimerThemeRN = PrimerThemeRN()
23
- private var intent: PaymentMethodIntent? = null
24
- private var paymentMethod: PrimerPaymentMethod? = null
25
-
26
20
  private var mListener = PrimerRNEventListener()
27
-
28
- private var sdkWasInitialised = false
29
-
30
21
  private val json = Json { ignoreUnknownKeys = true }
31
22
 
32
23
  init {
33
24
  mListener.sendEvent = { eventName, paramsJson -> sendEvent(eventName, paramsJson) }
34
- mListener.sendError = { paramsJson -> checkoutFailed(paramsJson) }
25
+ mListener.sendError = { paramsJson -> onError(paramsJson) }
26
+ mListener.sendErrorWithCheckoutData =
27
+ { paramsJson, checkoutData -> onError(paramsJson, checkoutData) }
35
28
  }
36
29
 
37
30
  override fun getName(): String = "NativePrimer"
38
31
 
39
32
  @ReactMethod
40
- fun configureWithSettings(settingsStr: String, promise: Promise) {
33
+ fun configure(settingsStr: String, promise: Promise) {
41
34
  try {
42
35
  Log.d("PrimerRN", "settings: $settingsStr")
43
- val settings = json.decodeFromString<PrimerSettingsRN>(settingsStr)
44
- this.settings = settings
45
- startSdk()
36
+ val settings =
37
+ if (settingsStr.isBlank()) PrimerSettingsRN() else json.decodeFromString(
38
+ settingsStr
39
+ )
40
+ startSdk(settings.toPrimerSettings())
46
41
  promise.resolve(null)
47
42
  } catch (e: Exception) {
48
43
  Log.e("PrimerRN", "configure settings error: $e")
49
- val exception = ErrorTypeRN.ParseJsonFailed errorTo "failed to parse settings."
50
- checkoutFailed(exception)
51
- promise.reject(exception.errorId, exception.errorDescription, e)
52
- }
53
- }
54
-
55
- @ReactMethod
56
- fun configureWithTheme(themeStr: String, promise: Promise) {
57
- try {
58
- Log.d("PrimerRN", "theme: $themeStr")
59
- val theme = json.decodeFromString<PrimerThemeRN>(themeStr)
60
- this.theme = theme
61
- startSdk()
62
- promise.resolve(null)
63
- } catch (e: Exception) {
64
- Log.e("PrimerRN", "configure theme error: $e")
65
- val exception = ErrorTypeRN.ParseJsonFailed errorTo "failed to parse theme."
66
- checkoutFailed(exception)
67
- promise.reject(exception.errorId, exception.errorDescription, e)
44
+ val exception = ErrorTypeRN.NativeBridgeFailed errorTo "failed to parse settings."
45
+ onError(exception)
46
+ promise.reject(exception.errorId, exception.description, e)
68
47
  }
69
48
  }
70
49
 
71
- @ReactMethod
72
- fun showUniversalCheckout(promise: Promise) {
73
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
74
- "This method is deprecated. Use the new showUniversalCheckoutWithClientToken method"
75
- checkoutFailed(exception)
76
- promise.reject(exception.errorId, exception.errorDescription)
77
- }
78
-
79
50
  @ReactMethod
80
51
  fun showUniversalCheckoutWithClientToken(
81
52
  clientToken: String,
@@ -85,62 +56,54 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
85
56
  Primer.instance.showUniversalCheckout(reactApplicationContext.applicationContext, clientToken)
86
57
  promise.resolve(null)
87
58
  } catch (e: Exception) {
88
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
59
+ val exception = ErrorTypeRN.NativeBridgeFailed errorTo
89
60
  "Primer SDK failed: ${e.message}"
90
- checkoutFailed(exception)
91
- promise.reject(exception.errorId, exception.errorDescription, e)
61
+ onError(exception)
62
+ promise.reject(exception.errorId, exception.description, e)
92
63
  }
93
64
  }
94
65
 
95
66
  @ReactMethod
96
- fun showVaultManager(promise: Promise) {
97
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
98
- "This method is deprecated. Use the new showUniversalCheckoutWithClientToken method"
99
- checkoutFailed(exception)
100
- promise.reject(exception.errorId, exception.errorDescription)
101
- }
102
-
103
- @ReactMethod
104
- fun showVaultManager(clientToken: String, promise: Promise) {
67
+ fun showVaultManagerWithClientToken(clientToken: String, promise: Promise) {
105
68
  try {
106
69
  Primer.instance.showVaultManager(reactApplicationContext.applicationContext, clientToken)
107
70
  promise.resolve(null)
108
71
  } catch (e: Exception) {
109
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
72
+ val exception = ErrorTypeRN.NativeBridgeFailed errorTo
110
73
  "Primer SDK failed: ${e.message}"
111
- checkoutFailed(exception)
112
- promise.reject(exception.errorId, exception.errorDescription, e)
74
+ onError(exception)
75
+ promise.reject(exception.errorId, exception.description, e)
113
76
  }
114
77
  }
115
78
 
116
79
  @ReactMethod
117
80
  fun showPaymentMethod(
118
- clientToken: String,
119
81
  paymentMethodTypeStr: String,
120
82
  intentStr: String,
83
+ clientToken: String,
121
84
  promise: Promise
122
85
  ) {
86
+ val intent: PrimerSessionIntent
123
87
  try {
124
- this.intent = PaymentMethodIntent.valueOf(intentStr)
88
+ intent = PrimerSessionIntent.valueOf(intentStr.uppercase())
125
89
  } catch (e: Exception) {
126
- val exception = ErrorTypeRN.ParseJsonFailed errorTo "failed to parse intent."
127
- checkoutFailed(exception)
128
- promise.reject(exception.errorId, exception.errorDescription, e)
90
+ val exception = ErrorTypeRN.NativeBridgeFailed errorTo "Intent $intentStr is not valid."
91
+ onError(exception)
92
+ promise.reject(exception.errorId, exception.description, e)
129
93
  return
130
94
  }
95
+ val paymentMethod: PrimerPaymentMethodType
131
96
  try {
132
- val paymentMethod = PrimerPaymentMethod.valueOf(paymentMethodTypeStr)
133
- this.paymentMethod = paymentMethod
97
+ paymentMethod = getPrimerPaymentMethod(paymentMethodTypeStr)
134
98
  } catch (e: Exception) {
135
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo "failed to parse payment method type."
136
- checkoutFailed(exception)
137
- promise.reject(exception.errorId, exception.errorDescription, e)
99
+ val exception =
100
+ ErrorTypeRN.NativeBridgeFailed errorTo "Payment method type $paymentMethodTypeStr is not valid."
101
+ onError(exception)
102
+ promise.reject(exception.errorId, exception.description, e)
138
103
  return
139
104
  }
140
105
 
141
106
  try {
142
- val paymentMethod = this.paymentMethod ?: return
143
- val intent = this.intent ?: return
144
107
  Primer.instance.showPaymentMethod(
145
108
  reactApplicationContext.applicationContext,
146
109
  clientToken,
@@ -149,60 +112,81 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
149
112
  )
150
113
  promise.resolve(null)
151
114
  } catch (e: Exception) {
152
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
115
+ val exception = ErrorTypeRN.NativeBridgeFailed errorTo
153
116
  "Primer SDK failed: ${e.message}"
154
- checkoutFailed(exception)
155
- promise.reject(exception.errorId, exception.errorDescription, e)
117
+ onError(exception)
118
+ promise.reject(exception.errorId, exception.description, e)
156
119
  }
157
120
  }
158
121
 
159
122
  @ReactMethod
160
- fun handleNewClientToken(clientToken: String, promise: Promise) {
161
- mListener.onClientTokenCallback(clientToken, null)
162
- mListener.onClientSessionActions(clientToken, null)
163
- mListener.onTokenizeSuccess(clientToken, null)
164
- mListener.onResumeSuccess(clientToken, null)
165
- removeCallbacksAndHandlers()
123
+ fun dismiss(promise: Promise) {
124
+ Primer.instance.dismiss()
166
125
  promise.resolve(null)
167
126
  }
168
127
 
128
+ // region tokenization handlers
169
129
  @ReactMethod
170
- fun handleError(errorStr: String, promise: Promise) {
171
- try {
172
- val err = json.decodeFromString<PrimerErrorRN>(errorStr)
173
- mListener.onClientTokenCallback(null, err)
174
- mListener.onClientSessionActions(null, err)
175
- mListener.onTokenizeSuccess(null, err)
176
- mListener.onResumeSuccess(null, err)
177
- removeCallbacksAndHandlers()
178
- promise.resolve(null)
179
- } catch (e: Exception) {
180
- val exception = PrimerErrorRN(
181
- ErrorTypeRN.CheckoutFlowFailed.name,
182
- "Primer SDK failed: ${e.message}"
183
- )
184
- checkoutFailed(exception)
185
- promise.reject(exception.errorId, exception.errorDescription, e)
186
- }
130
+ fun handleTokenizationNewClientToken(newClientToken: String, promise: Promise) {
131
+ mListener.handleTokenizationNewClientToken(newClientToken)
132
+ promise.resolve(null)
187
133
  }
188
134
 
189
135
  @ReactMethod
190
- fun handleSuccess(promise: Promise) {
191
- try {
192
- mListener.onClientTokenCallback(null, null)
193
- mListener.onClientSessionActions(null, null)
194
- mListener.onTokenizeSuccess(null, null)
195
- mListener.onResumeSuccess(null, null)
196
- removeCallbacksAndHandlers()
197
- promise.resolve(null)
198
- } catch (e: Exception) {
199
- val exception = ErrorTypeRN.CheckoutFlowFailed errorTo
200
- "Primer SDK failed: ${e.message}"
201
- checkoutFailed(exception)
202
- promise.reject(exception.errorId, exception.errorDescription, e)
203
- }
136
+ fun handleTokenizationSuccess(promise: Promise) {
137
+ mListener.handleTokenizationSuccess()
138
+ promise.resolve(null)
204
139
  }
205
140
 
141
+ @ReactMethod
142
+ fun handleTokenizationFailure(errorMessage: String?, promise: Promise) {
143
+ mListener.handleTokenizationFailure(errorMessage.orEmpty())
144
+ promise.resolve(null)
145
+ }
146
+ // endregion
147
+
148
+ // region resume handlers
149
+ @ReactMethod
150
+ fun handleResumeNewClientToken(newClientToken: String, promise: Promise) {
151
+ mListener.handleResumeNewClientToken(newClientToken)
152
+ promise.resolve(null)
153
+ }
154
+
155
+ @ReactMethod
156
+ fun handleResumeSuccess(promise: Promise) {
157
+ mListener.handleResumeSuccess()
158
+ promise.resolve(null)
159
+ }
160
+
161
+ @ReactMethod
162
+ fun handleResumeFailure(errorMessage: String?, promise: Promise) {
163
+ mListener.handleResumeFailure(errorMessage.orEmpty())
164
+ promise.resolve(null)
165
+ }
166
+ // endregion
167
+
168
+ // region payment handlers
169
+ @ReactMethod
170
+ fun handlePaymentCreationContinue(promise: Promise) {
171
+ mListener.handlePaymentCreationContinue()
172
+ promise.resolve(null)
173
+ }
174
+
175
+ @ReactMethod
176
+ fun handlePaymentCreationAbort(errorMessage: String?, promise: Promise) {
177
+ mListener.handlePaymentCreationAbort(errorMessage.orEmpty())
178
+ promise.resolve(null)
179
+ }
180
+ // endregion
181
+
182
+ // region error handlers
183
+ @ReactMethod
184
+ fun showErrorMessage(errorMessage: String?, promise: Promise) {
185
+ mListener.handleErrorMessage(errorMessage.orEmpty())
186
+ promise.resolve(null)
187
+ }
188
+ // endregion
189
+
206
190
  @ReactMethod
207
191
  fun setImplementedRNCallbacks(implementedRNCallbacksStr: String, promise: Promise) {
208
192
  try {
@@ -212,32 +196,28 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
212
196
  this.mListener.setImplementedCallbacks(implementedRNCallbacks)
213
197
  promise.resolve(null)
214
198
  } catch (e: Exception) {
215
- val exception = ErrorTypeRN.ParseJsonFailed errorTo "Failed to parse implemented callbacks"
216
- checkoutFailed(exception)
217
- promise.reject(exception.errorId, exception.errorDescription, e)
199
+ val exception =
200
+ ErrorTypeRN.NativeBridgeFailed errorTo "Implemented callbacks $implementedRNCallbacksStr is not valid."
201
+ onError(exception)
202
+ promise.reject(exception.errorId, exception.description, e)
218
203
  }
219
204
  }
220
205
 
221
- private fun removeCallbacksAndHandlers() {
222
- mListener.removeCallbacksAndHandlers()
206
+ private fun startSdk(settings: PrimerSettings) {
207
+ Primer.instance.configure(settings, mListener)
223
208
  }
224
209
 
225
- private fun startSdk() {
226
- val theme = theme.format()
227
- val settings = settings.format()
228
- val config = PrimerConfig(theme, settings)
229
-
230
- Primer.instance.configure(config, mListener)
231
- sdkWasInitialised = true
232
- }
233
-
234
- private fun checkoutFailed(exception: PrimerErrorRN) {
210
+ private fun onError(exception: PrimerErrorRN, checkoutDataRN: PrimerCheckoutDataRN? = null) {
235
211
  val params = Arguments.createMap()
236
212
  val errorJson = JSONObject(Json.encodeToString(exception))
237
- val data = Arguments.createMap()
238
- prepareData(data, errorJson)
239
- params.putMap(Keys.ERROR, data)
240
- sendEvent(PrimerEventsRN.OnError.string, params)
213
+ val errorData = prepareData(errorJson)
214
+ params.putMap(Keys.ERROR, errorData)
215
+ checkoutDataRN?.let {
216
+ val checkoutDataJson = JSONObject(Json.encodeToString(it))
217
+ val checkoutData = prepareData(checkoutDataJson)
218
+ params.putMap(Keys.CHECKOUT_DATA, checkoutData)
219
+ }
220
+ sendEvent(PrimerEvents.ON_ERROR.eventName, params)
241
221
  }
242
222
 
243
223
  private fun sendEvent(name: String, params: WritableMap) {
@@ -247,28 +227,27 @@ class PrimerRN(reactContext: ReactApplicationContext) : ReactContextBaseJavaModu
247
227
  }
248
228
 
249
229
  private fun sendEvent(name: String, data: JSONObject?) {
250
- val params = Arguments.createMap()
251
- prepareData(params, data)
230
+ val params = prepareData(data)
252
231
  reactApplicationContext.getJSModule(
253
232
  DeviceEventManagerModule.RCTDeviceEventEmitter::class.java
254
233
  ).emit(name, params)
255
234
  }
256
235
 
257
- private fun prepareData(params: WritableMap, data: JSONObject?) {
258
- data?.keys()?.forEach { key ->
259
- when (val dataValue = data.opt(key)) {
260
- is String -> params.putString(key, dataValue)
261
- is Boolean -> params.putBoolean(key, dataValue)
262
- is Double -> params.putDouble(key, dataValue)
263
- is Int -> params.putInt(key, dataValue)
264
- is JSONObject -> prepareData(params, dataValue)
265
- else -> params.putNull(key)
266
- }
236
+ private fun prepareData(data: JSONObject?): WritableMap {
237
+ return data?.let { convertJsonToMap(data) } ?: Arguments.createMap()
238
+ }
239
+
240
+ private fun getPrimerPaymentMethod(paymentMethodTypeStr: String): PrimerPaymentMethodType {
241
+ if (PrimerPaymentMethodType.PAYMENT_CARD.name == paymentMethodTypeStr) {
242
+ return PrimerPaymentMethodType.PAYMENT_CARD
267
243
  }
244
+
245
+ return PrimerPaymentMethodType.valueOf(paymentMethodTypeStr)
268
246
  }
269
247
  }
270
248
 
271
249
  internal object Keys {
272
250
  const val ERROR = "error"
273
251
  const val RESUME_TOKEN = "resumeToken"
252
+ const val CHECKOUT_DATA = "checkoutData"
274
253
  }