@primer-io/react-native 2.26.3 → 2.28.0-beta.1
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.
- package/android/.project +6 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +5 -5
- package/android/build.gradle +1 -3
- package/android/src/main/AndroidManifest.xml +1 -4
- package/android/src/main/java/com/primerioreactnative/PrimerRN.kt +3 -3
- package/android/src/main/java/com/primerioreactnative/PrimerRNEventListener.kt +4 -3
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckout.kt +2 -2
- package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt +46 -9
- package/android/src/main/java/com/primerioreactnative/ReactNativePackage.kt +4 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/ach/AchMandateManager.kt +70 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.kt +283 -0
- package/android/src/main/java/com/primerioreactnative/components/manager/banks/PrimerRNHeadlessUniversalCheckoutBanksComponent.kt +7 -37
- package/android/src/main/java/com/primerioreactnative/components/manager/klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.kt +5 -31
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerCheckoutAdditionalInfoRN.kt +17 -4
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerClientSessionRN.kt +9 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/PrimerSettingsRN.kt +53 -36
- package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsCollectableDataRN.kt +22 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/ach/AchUserDetailsStepRN.kt +22 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsCollectableData.kt +11 -0
- package/android/src/main/java/com/primerioreactnative/datamodels/extensions/ach/AchUserDetailsStep.kt +14 -0
- package/android/src/main/java/com/primerioreactnative/extensions/JSONExtensions.kt +41 -0
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerCheckoutAdditionalInfo.kt +4 -0
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerOrder.kt +5 -1
- package/android/src/main/java/com/primerioreactnative/extensions/PrimerPaymentMethodOptionsRN.kt +48 -15
- package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsCollectableData.swift +54 -0
- package/ios/Sources/DataModels/Ach Component/RNTAchUserDetailsStep.swift +40 -0
- package/ios/Sources/DataModels/PrimerCheckoutAdditionalInfoRN.swift +61 -0
- package/ios/Sources/DataModels/PrimerSettings+Extensions.swift +58 -4
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.m +28 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.swift +233 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.m +16 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Ach/RNTAchMandateManager.swift +53 -0
- package/ios/Sources/Headless Universal Checkout/Managers/Klarna/PrimerRNHeadlessUniversalCheckoutKlarnaComponent.swift +2 -2
- package/ios/Sources/Headless Universal Checkout/RNTPrimerHeadlessUniversalCheckout.swift +55 -7
- package/ios/Sources/version.swift +1 -1
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +106 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +38 -0
- package/lib/commonjs/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
- package/lib/commonjs/index.js +70 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/ach/AchCollectableData.js +6 -0
- package/lib/commonjs/models/ach/AchCollectableData.js.map +1 -0
- package/lib/commonjs/models/ach/AchSteps.js +6 -0
- package/lib/commonjs/models/ach/AchSteps.js.map +1 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js +99 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.js.map +1 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js +31 -0
- package/lib/module/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/ach/AchCollectableData.js +2 -0
- package/lib/module/models/ach/AchCollectableData.js.map +1 -0
- package/lib/module/models/ach/AchSteps.js +2 -0
- package/lib/module/models/ach/AchSteps.js.map +1 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts +53 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.d.ts.map +1 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts +12 -0
- package/lib/typescript/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +8 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts +10 -0
- package/lib/typescript/models/PrimerCheckoutAdditionalInfo.d.ts.map +1 -1
- package/lib/typescript/models/PrimerClientSession.d.ts +7 -0
- package/lib/typescript/models/PrimerClientSession.d.ts.map +1 -1
- package/lib/typescript/models/PrimerSettings.d.ts +40 -1
- package/lib/typescript/models/PrimerSettings.d.ts.map +1 -1
- package/lib/typescript/models/ach/AchCollectableData.d.ts +25 -0
- package/lib/typescript/models/ach/AchCollectableData.d.ts.map +1 -0
- package/lib/typescript/models/ach/AchSteps.d.ts +28 -0
- package/lib/typescript/models/ach/AchSteps.d.ts.map +1 -0
- package/package.json +1 -1
- package/primer-io-react-native.podspec +1 -1
- package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchManager.ts +158 -0
- package/src/HeadlessUniversalCheckout/Managers/PaymentMethodManagers/AchMandateManager.ts +32 -0
- package/src/index.tsx +8 -0
- package/src/models/PrimerCheckoutAdditionalInfo.ts +19 -5
- package/src/models/PrimerClientSession.ts +9 -1
- package/src/models/PrimerSettings.ts +46 -1
- package/src/models/ach/AchCollectableData.ts +29 -0
- package/src/models/ach/AchSteps.ts +29 -0
package/android/.project
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
<projects>
|
|
6
6
|
</projects>
|
|
7
7
|
<buildSpec>
|
|
8
|
+
<buildCommand>
|
|
9
|
+
<name>org.eclipse.jdt.core.javabuilder</name>
|
|
10
|
+
<arguments>
|
|
11
|
+
</arguments>
|
|
12
|
+
</buildCommand>
|
|
8
13
|
<buildCommand>
|
|
9
14
|
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
|
10
15
|
<arguments>
|
|
@@ -12,6 +17,7 @@
|
|
|
12
17
|
</buildCommand>
|
|
13
18
|
</buildSpec>
|
|
14
19
|
<natures>
|
|
20
|
+
<nature>org.eclipse.jdt.core.javanature</nature>
|
|
15
21
|
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
|
16
22
|
</natures>
|
|
17
23
|
<filteredResources>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
arguments
|
|
2
|
-
auto.sync=
|
|
1
|
+
arguments=--init-script /var/folders/wt/mqwpc4jx2kjgqf88mzm5qvx40000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/wt/mqwpc4jx2kjgqf88mzm5qvx40000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
|
|
2
|
+
auto.sync=true
|
|
3
3
|
build.scans.enabled=false
|
|
4
|
-
connection.gradle.distribution=GRADLE_DISTRIBUTION(
|
|
5
|
-
connection.project.dir
|
|
4
|
+
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
|
|
5
|
+
connection.project.dir=../../example/android
|
|
6
6
|
eclipse.preferences.version=1
|
|
7
7
|
gradle.user.home=
|
|
8
|
-
java.home=/
|
|
8
|
+
java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home
|
|
9
9
|
jvm.arguments=
|
|
10
10
|
offline.mode=false
|
|
11
11
|
override.workspace.settings=true
|
package/android/build.gradle
CHANGED
|
@@ -40,7 +40,6 @@ android {
|
|
|
40
40
|
group 'io.primer'
|
|
41
41
|
namespace "com.primerioreactnative"
|
|
42
42
|
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
|
|
43
|
-
buildToolsVersion getExtOrDefault('buildToolsVersion')
|
|
44
43
|
defaultConfig {
|
|
45
44
|
minSdkVersion 21
|
|
46
45
|
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
|
@@ -155,8 +154,7 @@ dependencies {
|
|
|
155
154
|
api 'com.facebook.react:react-native:+'
|
|
156
155
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
157
156
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1"
|
|
158
|
-
implementation 'io.primer:android:2.
|
|
159
|
-
|
|
157
|
+
implementation 'io.primer:android:2.32.0-express-checkout.1'
|
|
160
158
|
testImplementation 'io.mockk:mockk:1.13.11'
|
|
161
159
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
|
|
162
160
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
|
|
@@ -14,9 +14,9 @@ import kotlinx.serialization.encodeToString
|
|
|
14
14
|
import kotlinx.serialization.json.Json
|
|
15
15
|
import org.json.JSONObject
|
|
16
16
|
|
|
17
|
-
class PrimerRN(reactContext: ReactApplicationContext, private val json: Json) :
|
|
17
|
+
class PrimerRN(private val reactContext: ReactApplicationContext, private val json: Json) :
|
|
18
18
|
ReactContextBaseJavaModule(reactContext) {
|
|
19
|
-
private
|
|
19
|
+
private val mListener = PrimerRNEventListener()
|
|
20
20
|
|
|
21
21
|
init {
|
|
22
22
|
mListener.sendEvent = { eventName, paramsJson -> sendEvent(eventName, paramsJson) }
|
|
@@ -36,7 +36,7 @@ class PrimerRN(reactContext: ReactApplicationContext, private val json: Json) :
|
|
|
36
36
|
if (settingsStr.isBlank()) PrimerSettingsRN() else json.decodeFromString(
|
|
37
37
|
settingsStr
|
|
38
38
|
)
|
|
39
|
-
startSdk(settings.toPrimerSettings())
|
|
39
|
+
startSdk(settings.toPrimerSettings(reactContext))
|
|
40
40
|
promise.resolve(null)
|
|
41
41
|
} catch (e: Exception) {
|
|
42
42
|
Log.e("PrimerRN", "configure settings error: $e")
|
|
@@ -5,6 +5,7 @@ import com.primerioreactnative.extensions.toCheckoutAdditionalInfoRN
|
|
|
5
5
|
import com.primerioreactnative.extensions.toPrimerCheckoutDataRN
|
|
6
6
|
import com.primerioreactnative.extensions.toPrimerClientSessionRN
|
|
7
7
|
import com.primerioreactnative.extensions.toPrimerPaymentMethodDataRN
|
|
8
|
+
import com.primerioreactnative.extensions.removeType
|
|
8
9
|
import com.primerioreactnative.utils.PrimerImplementedRNCallbacks
|
|
9
10
|
import com.primerioreactnative.utils.errorTo
|
|
10
11
|
import io.primer.android.PrimerCheckoutListener
|
|
@@ -45,7 +46,7 @@ class PrimerRNEventListener : PrimerCheckoutListener {
|
|
|
45
46
|
PrimerEvents.ON_CHECKOUT_COMPLETE.eventName,
|
|
46
47
|
JSONObject(Json.encodeToString(checkoutData.toPrimerCheckoutDataRN())).apply {
|
|
47
48
|
val additionalInfoJson = optJSONObject(Keys.ADDITIONAL_INFO)
|
|
48
|
-
additionalInfoJson?.
|
|
49
|
+
additionalInfoJson?.removeType()
|
|
49
50
|
putOpt(Keys.ADDITIONAL_INFO, additionalInfoJson)
|
|
50
51
|
}
|
|
51
52
|
)
|
|
@@ -158,7 +159,7 @@ class PrimerRNEventListener : PrimerCheckoutListener {
|
|
|
158
159
|
sendEvent?.invoke(
|
|
159
160
|
PrimerEvents.ON_RESUME_PENDING.eventName,
|
|
160
161
|
JSONObject(Json.encodeToString(additionalInfo.toCheckoutAdditionalInfoRN())).apply {
|
|
161
|
-
|
|
162
|
+
removeType()
|
|
162
163
|
}
|
|
163
164
|
)
|
|
164
165
|
}
|
|
@@ -176,7 +177,7 @@ class PrimerRNEventListener : PrimerCheckoutListener {
|
|
|
176
177
|
sendEvent?.invoke(
|
|
177
178
|
PrimerEvents.ON_CHECKOUT_RECEIVED_ADDITIONAL_INFO.eventName,
|
|
178
179
|
JSONObject(Json.encodeToString(additionalInfo.toCheckoutAdditionalInfoRN())).apply {
|
|
179
|
-
|
|
180
|
+
removeType()
|
|
180
181
|
}
|
|
181
182
|
)
|
|
182
183
|
}
|
|
@@ -21,7 +21,7 @@ class PrimerRNHeadlessUniversalCheckout(
|
|
|
21
21
|
private val json: Json,
|
|
22
22
|
) : ReactContextBaseJavaModule(reactContext) {
|
|
23
23
|
|
|
24
|
-
private val listener = PrimerRNHeadlessUniversalCheckoutListener()
|
|
24
|
+
private val listener = PrimerRNHeadlessUniversalCheckoutListener(reactContext)
|
|
25
25
|
|
|
26
26
|
init {
|
|
27
27
|
listener.sendEvent = { eventName, paramsJson -> sendEvent(eventName, paramsJson) }
|
|
@@ -49,7 +49,7 @@ class PrimerRNHeadlessUniversalCheckout(
|
|
|
49
49
|
PrimerHeadlessUniversalCheckout.current.start(
|
|
50
50
|
reactContext,
|
|
51
51
|
clientToken,
|
|
52
|
-
settings.toPrimerSettings(),
|
|
52
|
+
settings.toPrimerSettings(reactContext),
|
|
53
53
|
listener,
|
|
54
54
|
listener
|
|
55
55
|
)
|
package/android/src/main/java/com/primerioreactnative/PrimerRNHeadlessUniversalCheckoutListener.kt
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
package com.primerioreactnative
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.Promise
|
|
4
|
+
import com.facebook.react.bridge.ReactContext
|
|
4
5
|
import com.primerioreactnative.components.datamodels.core.PrimerRNAvailablePaymentMethods
|
|
5
6
|
import com.primerioreactnative.components.datamodels.core.toPrimerRNHeadlessUniversalCheckoutPaymentMethod
|
|
6
7
|
import com.primerioreactnative.components.events.PrimerHeadlessUniversalCheckoutEvent
|
|
8
|
+
import com.primerioreactnative.components.manager.ach.PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent
|
|
9
|
+
import com.primerioreactnative.components.manager.ach.PrimerRNAchMandateManager
|
|
7
10
|
import com.primerioreactnative.datamodels.*
|
|
8
11
|
import com.primerioreactnative.extensions.toCheckoutAdditionalInfoRN
|
|
9
12
|
import com.primerioreactnative.extensions.toPrimerCheckoutDataRN
|
|
10
13
|
import com.primerioreactnative.extensions.toPrimerClientSessionRN
|
|
11
14
|
import com.primerioreactnative.extensions.toPrimerPaymentMethodDataRN
|
|
15
|
+
import com.primerioreactnative.extensions.removeType
|
|
12
16
|
import com.primerioreactnative.utils.PrimerHeadlessUniversalCheckoutImplementedRNCallbacks
|
|
13
17
|
import com.primerioreactnative.utils.errorTo
|
|
14
18
|
import com.primerioreactnative.utils.toWritableMap
|
|
@@ -23,13 +27,18 @@ import io.primer.android.domain.error.models.PrimerError
|
|
|
23
27
|
import io.primer.android.domain.payments.additionalInfo.MultibancoCheckoutAdditionalInfo
|
|
24
28
|
import io.primer.android.domain.payments.additionalInfo.PrimerCheckoutAdditionalInfo
|
|
25
29
|
import io.primer.android.domain.payments.additionalInfo.PromptPayCheckoutAdditionalInfo
|
|
30
|
+
import io.primer.android.domain.payments.additionalInfo.AchAdditionalInfo
|
|
26
31
|
import io.primer.android.domain.tokenization.models.PrimerPaymentMethodData
|
|
27
32
|
import io.primer.android.domain.tokenization.models.PrimerPaymentMethodTokenData
|
|
33
|
+
import io.primer.android.Primer
|
|
28
34
|
import kotlinx.serialization.encodeToString
|
|
29
35
|
import kotlinx.serialization.json.Json
|
|
30
36
|
import org.json.JSONObject
|
|
37
|
+
import androidx.activity.ComponentActivity
|
|
31
38
|
|
|
32
|
-
class PrimerRNHeadlessUniversalCheckoutListener
|
|
39
|
+
class PrimerRNHeadlessUniversalCheckoutListener(
|
|
40
|
+
private val reactContext: ReactContext
|
|
41
|
+
) : PrimerHeadlessUniversalCheckoutListener,
|
|
33
42
|
PrimerHeadlessUniversalCheckoutUiListener {
|
|
34
43
|
private var paymentCreationDecisionHandler: ((errorMessage: String?) -> Unit)? = null
|
|
35
44
|
private var tokenizeSuccessDecisionHandler: ((resumeToken: String?, errorMessage: String?) -> Unit)? =
|
|
@@ -113,7 +122,7 @@ class PrimerRNHeadlessUniversalCheckoutListener : PrimerHeadlessUniversalCheckou
|
|
|
113
122
|
PrimerHeadlessUniversalCheckoutEvent.ON_CHECKOUT_COMPLETE.eventName,
|
|
114
123
|
JSONObject(Json.encodeToString(checkoutData.toPrimerCheckoutDataRN())).apply {
|
|
115
124
|
val additionalInfoJson = optJSONObject(Keys.ADDITIONAL_INFO)
|
|
116
|
-
additionalInfoJson?.
|
|
125
|
+
additionalInfoJson?.removeType()
|
|
117
126
|
putOpt(Keys.ADDITIONAL_INFO, additionalInfoJson)
|
|
118
127
|
}
|
|
119
128
|
)
|
|
@@ -225,7 +234,7 @@ class PrimerRNHeadlessUniversalCheckoutListener : PrimerHeadlessUniversalCheckou
|
|
|
225
234
|
sendEvent?.invoke(
|
|
226
235
|
PrimerHeadlessUniversalCheckoutEvent.ON_CHECKOUT_PENDING.eventName,
|
|
227
236
|
JSONObject(Json.encodeToString(additionalInfo.toCheckoutAdditionalInfoRN())).apply {
|
|
228
|
-
|
|
237
|
+
removeType()
|
|
229
238
|
}
|
|
230
239
|
)
|
|
231
240
|
}
|
|
@@ -240,13 +249,37 @@ class PrimerRNHeadlessUniversalCheckoutListener : PrimerHeadlessUniversalCheckou
|
|
|
240
249
|
|
|
241
250
|
override fun onCheckoutAdditionalInfoReceived(additionalInfo: PrimerCheckoutAdditionalInfo) {
|
|
242
251
|
if (implementedRNCallbacks?.isOnCheckoutAdditionalInfoImplemented == true) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
252
|
+
when (additionalInfo) {
|
|
253
|
+
is PromptPayCheckoutAdditionalInfo -> {
|
|
254
|
+
sendEvent?.invoke(
|
|
255
|
+
PrimerHeadlessUniversalCheckoutEvent.ON_CHECKOUT_ADDITIONAL_INFO.eventName,
|
|
256
|
+
JSONObject(json.encodeToString(additionalInfo.toCheckoutAdditionalInfoRN())).apply {
|
|
257
|
+
removeType()
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
is AchAdditionalInfo.ProvideActivityResultRegistry -> {
|
|
262
|
+
val activityResultRegistry = (reactContext.currentActivity as? ComponentActivity)?.activityResultRegistry
|
|
263
|
+
if (activityResultRegistry == null) {
|
|
264
|
+
sendError?.invoke(
|
|
265
|
+
ErrorTypeRN.NativeBridgeFailed
|
|
266
|
+
errorTo PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent.UNSUPPORTED_ACTIVITY_ERROR
|
|
267
|
+
)
|
|
268
|
+
} else {
|
|
269
|
+
additionalInfo.provide(activityResultRegistry)
|
|
248
270
|
}
|
|
249
|
-
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
is AchAdditionalInfo.DisplayMandate -> {
|
|
274
|
+
PrimerRNAchMandateManager.acceptMandate = additionalInfo.onAcceptMandate
|
|
275
|
+
PrimerRNAchMandateManager.declineMandate = additionalInfo.onDeclineMandate
|
|
276
|
+
sendEvent?.invoke(
|
|
277
|
+
PrimerHeadlessUniversalCheckoutEvent.ON_CHECKOUT_ADDITIONAL_INFO.eventName,
|
|
278
|
+
JSONObject(json.encodeToString(additionalInfo.toCheckoutAdditionalInfoRN())).apply {
|
|
279
|
+
removeType()
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
}
|
|
250
283
|
}
|
|
251
284
|
} else {
|
|
252
285
|
sendError?.invoke(
|
|
@@ -331,4 +364,8 @@ class PrimerRNHeadlessUniversalCheckoutListener : PrimerHeadlessUniversalCheckou
|
|
|
331
364
|
resumeSuccessDecisionHandler = null
|
|
332
365
|
implementedRNCallbacks = null
|
|
333
366
|
}
|
|
367
|
+
|
|
368
|
+
private companion object {
|
|
369
|
+
val json = Json { encodeDefaults = true }
|
|
370
|
+
}
|
|
334
371
|
}
|
|
@@ -11,6 +11,8 @@ import com.primerioreactnative.components.manager.vault.PrimerRNHeadlessUniversa
|
|
|
11
11
|
import com.primerioreactnative.components.manager.redirect.PrimerRNHeadlessUniversalCheckoutBanksComponent
|
|
12
12
|
import com.primerioreactnative.components.manager.klarna.PrimerRNHeadlessUniversalCheckoutKlarnaComponent
|
|
13
13
|
import com.primerioreactnative.components.manager.klarna.PrimerKlarnaPaymentViewManager
|
|
14
|
+
import com.primerioreactnative.components.manager.ach.PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent
|
|
15
|
+
import com.primerioreactnative.components.manager.ach.PrimerRNAchMandateManager
|
|
14
16
|
import kotlinx.serialization.json.Json
|
|
15
17
|
|
|
16
18
|
class ReactNativePackage : ReactPackage {
|
|
@@ -26,6 +28,8 @@ class ReactNativePackage : ReactPackage {
|
|
|
26
28
|
PrimerRNHeadlessUniversalCheckoutAssetManager(reactContext),
|
|
27
29
|
PrimerRNHeadlessUniversalCheckoutVaultManager(reactContext, json),
|
|
28
30
|
PrimerRNHeadlessUniversalCheckoutKlarnaComponent(reactContext),
|
|
31
|
+
PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent(reactContext),
|
|
32
|
+
PrimerRNAchMandateManager(reactContext),
|
|
29
33
|
//region Component with redirect components
|
|
30
34
|
PrimerRNHeadlessUniversalCheckoutBanksComponent(reactContext)
|
|
31
35
|
//endregion
|
package/android/src/main/java/com/primerioreactnative/components/manager/ach/AchMandateManager.kt
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
package com.primerioreactnative.components.manager.ach
|
|
2
|
+
|
|
3
|
+
import androidx.lifecycle.LifecycleOwner
|
|
4
|
+
import androidx.lifecycle.lifecycleScope
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
8
|
+
import com.facebook.react.bridge.ReactMethod
|
|
9
|
+
import com.primerioreactnative.datamodels.ErrorTypeRN
|
|
10
|
+
import com.primerioreactnative.utils.errorTo
|
|
11
|
+
import kotlinx.coroutines.launch
|
|
12
|
+
|
|
13
|
+
class PrimerRNAchMandateManager(
|
|
14
|
+
private val reactContext: ReactApplicationContext,
|
|
15
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
16
|
+
override fun getName() = "RNTAchMandateManager"
|
|
17
|
+
|
|
18
|
+
@ReactMethod
|
|
19
|
+
fun acceptMandate(promise: Promise) {
|
|
20
|
+
executeMandateAction(promise, PrimerRNAchMandateManager.Companion.acceptMandate, UNITIALIZED_ACCEPT_MANDATE)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@ReactMethod
|
|
24
|
+
fun declineMandate(promise: Promise) {
|
|
25
|
+
executeMandateAction(promise, PrimerRNAchMandateManager.Companion.declineMandate, UNITIALIZED_DECLINE_MANDATE)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private fun executeMandateAction(promise: Promise, action: (suspend () -> Unit)?, error: String) {
|
|
29
|
+
val lifecycleScope = getLifecycleScopeOrNull()
|
|
30
|
+
|
|
31
|
+
if (lifecycleScope == null) {
|
|
32
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNSUPPORTED_ACTIVITY_ERROR
|
|
33
|
+
promise.reject(exception.errorId, exception.description)
|
|
34
|
+
} else {
|
|
35
|
+
lifecycleScope.launch {
|
|
36
|
+
if (action == null) {
|
|
37
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo error
|
|
38
|
+
promise.reject(exception.errorId, exception.description)
|
|
39
|
+
} else {
|
|
40
|
+
action()
|
|
41
|
+
promise.resolve(null)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private fun getLifecycleScopeOrNull() =
|
|
48
|
+
(reactContext.currentActivity as? LifecycleOwner)?.lifecycleScope
|
|
49
|
+
|
|
50
|
+
companion object {
|
|
51
|
+
var acceptMandate: (suspend () -> Unit)? = null
|
|
52
|
+
var declineMandate: (suspend () -> Unit)? = null
|
|
53
|
+
|
|
54
|
+
val UNSUPPORTED_ACTIVITY_ERROR =
|
|
55
|
+
"""
|
|
56
|
+
Unsupported activity type.
|
|
57
|
+
Make sure your root activity extends LifecycleOwner.
|
|
58
|
+
""".trimIndent()
|
|
59
|
+
|
|
60
|
+
val UNITIALIZED_ACCEPT_MANDATE =
|
|
61
|
+
"""
|
|
62
|
+
Unitialized 'acceptMandate' property.
|
|
63
|
+
""".trimIndent()
|
|
64
|
+
|
|
65
|
+
val UNITIALIZED_DECLINE_MANDATE =
|
|
66
|
+
"""
|
|
67
|
+
Unitialized 'declineMandate' property.
|
|
68
|
+
""".trimIndent()
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
package com.primerioreactnative.components.manager.ach
|
|
2
|
+
|
|
3
|
+
import androidx.activity.ComponentActivity
|
|
4
|
+
import androidx.lifecycle.LifecycleOwner
|
|
5
|
+
import androidx.lifecycle.ViewModelStoreOwner
|
|
6
|
+
import androidx.lifecycle.lifecycleScope
|
|
7
|
+
import com.facebook.react.bridge.Arguments
|
|
8
|
+
import com.facebook.react.bridge.Promise
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
11
|
+
import com.facebook.react.bridge.ReactMethod
|
|
12
|
+
import com.facebook.react.bridge.WritableArray
|
|
13
|
+
import com.facebook.react.bridge.WritableMap
|
|
14
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
15
|
+
import com.primerioreactnative.PrimerRNViewModelStoreOwner
|
|
16
|
+
import com.primerioreactnative.components.events.PrimerHeadlessUniversalCheckoutComponentEvent
|
|
17
|
+
import com.primerioreactnative.datamodels.ErrorTypeRN
|
|
18
|
+
import com.primerioreactnative.datamodels.PrimerValidationErrorRN
|
|
19
|
+
import com.primerioreactnative.datamodels.extensions.ach.toUserDetailsCollectedRN
|
|
20
|
+
import com.primerioreactnative.datamodels.extensions.ach.toEmailAddressRN
|
|
21
|
+
import com.primerioreactnative.datamodels.extensions.ach.toFirstNameRN
|
|
22
|
+
import com.primerioreactnative.datamodels.extensions.ach.toLastNameRN
|
|
23
|
+
import com.primerioreactnative.datamodels.extensions.ach.toUserDetailsRetrievedRN
|
|
24
|
+
import com.primerioreactnative.utils.convertJsonToArray
|
|
25
|
+
import com.primerioreactnative.utils.convertJsonToMap
|
|
26
|
+
import com.primerioreactnative.utils.errorTo
|
|
27
|
+
import io.primer.android.components.manager.ach.PrimerHeadlessUniversalCheckoutAchManager
|
|
28
|
+
import io.primer.android.components.manager.core.composable.PrimerValidationStatus
|
|
29
|
+
import io.primer.android.components.presentation.paymentMethods.nativeUi.stripe.ach.StripeAchUserDetailsComponent
|
|
30
|
+
import io.primer.android.components.presentation.paymentMethods.nativeUi.stripe.ach.composable.AchUserDetailsCollectableData
|
|
31
|
+
import io.primer.android.components.presentation.paymentMethods.nativeUi.stripe.ach.composable.AchUserDetailsStep
|
|
32
|
+
import io.primer.android.domain.error.models.PrimerError
|
|
33
|
+
import com.primerioreactnative.utils.toWritableArray
|
|
34
|
+
import com.primerioreactnative.utils.toWritableMap
|
|
35
|
+
import com.primerioreactnative.extensions.putErrors
|
|
36
|
+
import com.primerioreactnative.extensions.putValidationErrors
|
|
37
|
+
import kotlinx.coroutines.Job
|
|
38
|
+
import kotlinx.coroutines.coroutineScope
|
|
39
|
+
import kotlinx.coroutines.flow.collectLatest
|
|
40
|
+
import kotlinx.coroutines.launch
|
|
41
|
+
import kotlinx.serialization.encodeToString
|
|
42
|
+
import kotlinx.serialization.json.Json
|
|
43
|
+
import org.json.JSONArray
|
|
44
|
+
import org.json.JSONObject
|
|
45
|
+
import android.util.Log
|
|
46
|
+
|
|
47
|
+
class PrimerRNHeadlessUniversalCheckoutStripeAchUserDetailsComponent(
|
|
48
|
+
private val reactContext: ReactApplicationContext,
|
|
49
|
+
) : ReactContextBaseJavaModule(reactContext) {
|
|
50
|
+
override fun getName() = "RNTPrimerHeadlessUniversalCheckoutStripeAchUserDetailsComponent"
|
|
51
|
+
|
|
52
|
+
private var job: Job? = null
|
|
53
|
+
private var viewModelStoreOwner: ViewModelStoreOwner? = null
|
|
54
|
+
private var component: StripeAchUserDetailsComponent? = null
|
|
55
|
+
|
|
56
|
+
@ReactMethod
|
|
57
|
+
fun configure(promise: Promise) {
|
|
58
|
+
val currentViewModelStoreOwner =
|
|
59
|
+
reactContext.currentActivity as? ViewModelStoreOwner
|
|
60
|
+
?: run { PrimerRNViewModelStoreOwner() }
|
|
61
|
+
|
|
62
|
+
val activity = reactContext.currentActivity as? ComponentActivity
|
|
63
|
+
|
|
64
|
+
if (activity == null) {
|
|
65
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNSUPPORTED_ACTIVITY_ERROR
|
|
66
|
+
promise.reject(exception.errorId, exception.description)
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
viewModelStoreOwner = currentViewModelStoreOwner
|
|
71
|
+
|
|
72
|
+
runCatching {
|
|
73
|
+
PrimerHeadlessUniversalCheckoutAchManager(currentViewModelStoreOwner)
|
|
74
|
+
.provide<StripeAchUserDetailsComponent>("STRIPE_ACH")
|
|
75
|
+
}
|
|
76
|
+
.onSuccess { component = it }
|
|
77
|
+
.onFailure {
|
|
78
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo "$INITIALIZATION_ERROR: ${it.message}"
|
|
79
|
+
promise.reject(exception.errorId, exception.description)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
val lifecycleScope = (activity as LifecycleOwner).lifecycleScope
|
|
84
|
+
|
|
85
|
+
job =
|
|
86
|
+
lifecycleScope.launch {
|
|
87
|
+
coroutineScope {
|
|
88
|
+
launch { configureStepListener() }
|
|
89
|
+
|
|
90
|
+
launch { configureValidationListener() }
|
|
91
|
+
|
|
92
|
+
launch { configureErrorListener() }
|
|
93
|
+
promise.resolve(null)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@ReactMethod
|
|
99
|
+
fun start(promise: Promise) {
|
|
100
|
+
if (component == null) {
|
|
101
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNINITIALIZED_ERROR
|
|
102
|
+
promise.reject(exception.errorId, exception.description)
|
|
103
|
+
} else {
|
|
104
|
+
component?.start()
|
|
105
|
+
promise.resolve(null)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@ReactMethod
|
|
110
|
+
fun submit(promise: Promise) {
|
|
111
|
+
if (component == null) {
|
|
112
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNINITIALIZED_ERROR
|
|
113
|
+
promise.reject(exception.errorId, exception.description)
|
|
114
|
+
} else {
|
|
115
|
+
component?.submit()
|
|
116
|
+
promise.resolve(null)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@ReactMethod
|
|
121
|
+
fun onSetFirstName(firstName: String, promise: Promise) {
|
|
122
|
+
if (component == null) {
|
|
123
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNINITIALIZED_ERROR
|
|
124
|
+
promise.reject(exception.errorId, exception.description)
|
|
125
|
+
} else {
|
|
126
|
+
component?.updateCollectedData(AchUserDetailsCollectableData.FirstName(firstName))
|
|
127
|
+
promise.resolve(null)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@ReactMethod
|
|
132
|
+
fun onSetLastName(lastName: String, promise: Promise) {
|
|
133
|
+
if (component == null) {
|
|
134
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNINITIALIZED_ERROR
|
|
135
|
+
promise.reject(exception.errorId, exception.description)
|
|
136
|
+
} else {
|
|
137
|
+
component?.updateCollectedData(AchUserDetailsCollectableData.LastName(lastName))
|
|
138
|
+
promise.resolve(null)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@ReactMethod
|
|
143
|
+
fun onSetEmailAddress(emailAddress: String, promise: Promise) {
|
|
144
|
+
if (component == null) {
|
|
145
|
+
val exception = ErrorTypeRN.NativeBridgeFailed errorTo UNINITIALIZED_ERROR
|
|
146
|
+
promise.reject(exception.errorId, exception.description)
|
|
147
|
+
} else {
|
|
148
|
+
component?.updateCollectedData(AchUserDetailsCollectableData.EmailAddress(emailAddress))
|
|
149
|
+
promise.resolve(null)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private suspend fun configureErrorListener() {
|
|
154
|
+
component?.componentError?.collectLatest { error ->
|
|
155
|
+
sendEvent(
|
|
156
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_ERROR.eventName,
|
|
157
|
+
JSONObject().apply { putErrors(error) }
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private suspend fun configureStepListener() {
|
|
163
|
+
component?.componentStep?.collectLatest { step ->
|
|
164
|
+
when (step) {
|
|
165
|
+
is AchUserDetailsStep.UserDetailsRetrieved -> {
|
|
166
|
+
sendEvent(
|
|
167
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_STEP.eventName,
|
|
168
|
+
JSONObject(json.encodeToString(step.toUserDetailsRetrievedRN()))
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
is AchUserDetailsStep.UserDetailsCollected -> {
|
|
172
|
+
sendEvent(
|
|
173
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_STEP.eventName,
|
|
174
|
+
JSONObject(json.encodeToString(step.toUserDetailsCollectedRN()))
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private suspend fun configureValidationListener() {
|
|
182
|
+
component?.componentValidationStatus?.collectLatest { validationStatus ->
|
|
183
|
+
when (validationStatus) {
|
|
184
|
+
is PrimerValidationStatus.Validating -> {
|
|
185
|
+
sendEvent(
|
|
186
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_VALIDATING.eventName,
|
|
187
|
+
JSONObject().apply {
|
|
188
|
+
putData(validationStatus.collectableData as AchUserDetailsCollectableData)
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
is PrimerValidationStatus.Invalid -> {
|
|
193
|
+
sendEvent(
|
|
194
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_IN_VALID.eventName,
|
|
195
|
+
JSONObject().apply {
|
|
196
|
+
putData(validationStatus.collectableData as AchUserDetailsCollectableData)
|
|
197
|
+
putValidationErrors(validationStatus.validationErrors)
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
is PrimerValidationStatus.Valid -> {
|
|
202
|
+
sendEvent(
|
|
203
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_VALID.eventName,
|
|
204
|
+
JSONObject().apply {
|
|
205
|
+
putData(validationStatus.collectableData as AchUserDetailsCollectableData)
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
is PrimerValidationStatus.Error -> {
|
|
210
|
+
sendEvent(
|
|
211
|
+
PrimerHeadlessUniversalCheckoutComponentEvent.ON_VALIDATION_ERROR.eventName,
|
|
212
|
+
JSONObject().apply {
|
|
213
|
+
putData(validationStatus.collectableData as AchUserDetailsCollectableData)
|
|
214
|
+
putErrors(validationStatus.error)
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private fun JSONObject.putData(collectableData: AchUserDetailsCollectableData) {
|
|
223
|
+
put(
|
|
224
|
+
"data",
|
|
225
|
+
JSONObject(
|
|
226
|
+
json.encodeToString(
|
|
227
|
+
when (collectableData) {
|
|
228
|
+
is AchUserDetailsCollectableData.FirstName ->
|
|
229
|
+
collectableData.toFirstNameRN()
|
|
230
|
+
is AchUserDetailsCollectableData.LastName -> collectableData.toLastNameRN()
|
|
231
|
+
is AchUserDetailsCollectableData.EmailAddress ->
|
|
232
|
+
collectableData.toEmailAddressRN()
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@ReactMethod fun addListener(eventName: String?) = Unit
|
|
240
|
+
|
|
241
|
+
@ReactMethod fun removeListeners(count: Int?) = Unit
|
|
242
|
+
|
|
243
|
+
private fun sendEvent(name: String, data: JSONObject?) {
|
|
244
|
+
reactApplicationContext
|
|
245
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
246
|
+
.emit(name, data.toWritableMap())
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private fun sendEvent(name: String, data: JSONArray?) {
|
|
250
|
+
reactApplicationContext
|
|
251
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
252
|
+
.emit(name, data.toWritableArray())
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
@ReactMethod
|
|
256
|
+
fun cleanUp(promise: Promise) {
|
|
257
|
+
job?.cancel()
|
|
258
|
+
job = null
|
|
259
|
+
component = null
|
|
260
|
+
viewModelStoreOwner?.viewModelStore?.clear()
|
|
261
|
+
promise.resolve(null)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
companion object {
|
|
265
|
+
const val INITIALIZATION_ERROR = """
|
|
266
|
+
An error occurred during component initialization.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
const val UNINITIALIZED_ERROR =
|
|
270
|
+
"""
|
|
271
|
+
The component has not been initialized.
|
|
272
|
+
Make sure you have initialized the `component` first.
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
const val UNSUPPORTED_ACTIVITY_ERROR =
|
|
276
|
+
"""
|
|
277
|
+
Unsupported activity type.
|
|
278
|
+
Make sure your root activity extends ComponentActivity.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
val json = Json { encodeDefaults = true }
|
|
282
|
+
}
|
|
283
|
+
}
|