@stripe/stripe-react-native 0.65.1 → 0.66.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.
- package/android/detekt/detekt-baseline.xml +0 -10
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +51 -57
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementEvent.kt +26 -0
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +129 -16
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +17 -0
- package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +4 -0
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +8 -19
- package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +1 -0
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +95 -26
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +1 -0
- package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +2 -16
- package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +59 -33
- package/android/src/main/java/com/reactnativestripesdk/utils/DefaultActivityLifecycleCallbacks.kt +41 -0
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +17 -3
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +5 -1
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +116 -0
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +109 -1
- package/android/src/test/java/com/reactnativestripesdk/DrawableLoadingTest.kt +6 -2
- package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +107 -0
- package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +39 -30
- package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +8 -0
- package/ios/CurrencySelectorElementManager.m +7 -0
- package/ios/CurrencySelectorElementView.swift +142 -7
- package/ios/EmbeddedPaymentElementView.swift +1 -1
- package/ios/Mappers+Checkout.swift +251 -107
- package/ios/Mappers.swift +90 -2
- package/ios/NewArch/StripeCurrencySelectorElementComponentView.mm +14 -0
- package/ios/OldArch/StripeSdkEventEmitterCompat.h +1 -0
- package/ios/OldArch/StripeSdkEventEmitterCompat.m +6 -0
- package/ios/PaymentOptionDisplayData+ReactNative.swift +1 -1
- package/ios/PaymentSheetAppearance.swift +1 -1
- package/ios/StripeOnrampSdk.mm +19 -0
- package/ios/StripeSdk.mm +17 -4
- package/ios/StripeSdkEmitter.swift +1 -0
- package/ios/StripeSdkImpl+Checkout.swift +75 -23
- package/ios/StripeSdkImpl+CustomerSheet.swift +1 -1
- package/ios/StripeSdkImpl+Embedded.swift +1 -1
- package/ios/StripeSdkImpl+PaymentSheet.swift +1 -1
- package/ios/StripeSdkImpl.swift +88 -8
- package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
- package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
- package/lib/commonjs/hooks/useCheckout.js +1 -1
- package/lib/commonjs/hooks/useCheckout.js.map +1 -1
- package/lib/commonjs/hooks/useOnramp.js +1 -1
- package/lib/commonjs/hooks/useOnramp.js.map +1 -1
- package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
- package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
- package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
- package/lib/module/hooks/useCheckout.js +1 -1
- package/lib/module/hooks/useCheckout.js.map +1 -1
- package/lib/module/hooks/useOnramp.js +1 -1
- package/lib/module/hooks/useOnramp.js.map +1 -1
- package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
- package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts +1 -1
- package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useCheckout.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useOnramp.d.ts +22 -0
- package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +3 -0
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +2 -1
- package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
- package/lib/typescript/src/types/Checkout.d.ts +266 -84
- package/lib/typescript/src/types/Checkout.d.ts.map +1 -1
- package/lib/typescript/src/types/Onramp.d.ts +94 -0
- package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/components/PaymentMethodMessagingElement.tsx +54 -52
- package/src/hooks/useCheckout.tsx +20 -4
- package/src/hooks/useOnramp.tsx +44 -0
- package/src/specs/NativeOnrampSdkModule.ts +5 -0
- package/src/specs/NativeStripeSdkModule.ts +8 -1
- package/src/types/Checkout.ts +289 -84
- package/src/types/Onramp.ts +109 -0
- package/stripe-react-native.podspec +1 -1
- package/ios/CurrencySelectorElementManager.swift +0 -12
|
@@ -62,6 +62,7 @@ class StripeSdkPackage : BaseReactPackage() {
|
|
|
62
62
|
EmbeddedPaymentElementViewManager(),
|
|
63
63
|
NavigationBarManager(),
|
|
64
64
|
PaymentMethodMessagingElementViewManager(),
|
|
65
|
+
CurrencySelectorElementViewManager(),
|
|
65
66
|
)
|
|
66
67
|
|
|
67
68
|
private fun getOnrampModuleClass(): Class<out NativeModule?>? {
|
package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
package com.reactnativestripesdk.customersheet
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
|
-
import android.app.Application
|
|
5
4
|
import android.graphics.drawable.Drawable
|
|
6
5
|
import android.os.Bundle
|
|
7
6
|
import android.os.Handler
|
|
@@ -20,6 +19,7 @@ import com.reactnativestripesdk.buildPaymentSheetAppearance
|
|
|
20
19
|
import com.reactnativestripesdk.convertDrawableToBase64
|
|
21
20
|
import com.reactnativestripesdk.mapToCardBrandAcceptance
|
|
22
21
|
import com.reactnativestripesdk.utils.CreateTokenErrorType
|
|
22
|
+
import com.reactnativestripesdk.utils.DefaultActivityLifecycleCallbacks
|
|
23
23
|
import com.reactnativestripesdk.utils.ErrorType
|
|
24
24
|
import com.reactnativestripesdk.utils.KeepJsAwakeTask
|
|
25
25
|
import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
|
|
@@ -224,7 +224,7 @@ class CustomerSheetManager(
|
|
|
224
224
|
private fun presentWithTimeout(timeout: Long) {
|
|
225
225
|
var activities: MutableList<Activity> = mutableListOf()
|
|
226
226
|
val activityLifecycleCallbacks =
|
|
227
|
-
object :
|
|
227
|
+
object : DefaultActivityLifecycleCallbacks() {
|
|
228
228
|
override fun onActivityCreated(
|
|
229
229
|
activity: Activity,
|
|
230
230
|
savedInstanceState: Bundle?,
|
|
@@ -232,20 +232,6 @@ class CustomerSheetManager(
|
|
|
232
232
|
activities.add(activity)
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
override fun onActivityStarted(activity: Activity) {}
|
|
236
|
-
|
|
237
|
-
override fun onActivityResumed(activity: Activity) {}
|
|
238
|
-
|
|
239
|
-
override fun onActivityPaused(activity: Activity) {}
|
|
240
|
-
|
|
241
|
-
override fun onActivityStopped(activity: Activity) {}
|
|
242
|
-
|
|
243
|
-
override fun onActivitySaveInstanceState(
|
|
244
|
-
activity: Activity,
|
|
245
|
-
outState: Bundle,
|
|
246
|
-
) {
|
|
247
|
-
}
|
|
248
|
-
|
|
249
235
|
override fun onActivityDestroyed(activity: Activity) {
|
|
250
236
|
activities = mutableListOf()
|
|
251
237
|
context.currentActivity?.application?.unregisterActivityLifecycleCallbacks(this)
|
|
@@ -25,51 +25,70 @@ internal fun mapFromCheckoutState(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
@OptIn(CheckoutSessionPreview::class)
|
|
28
|
-
private fun mapFromCheckoutSession(
|
|
29
|
-
session: CheckoutSession,
|
|
30
|
-
): WritableMap =
|
|
28
|
+
private fun mapFromCheckoutSession(session: CheckoutSession): WritableMap =
|
|
31
29
|
Arguments.createMap().apply {
|
|
32
30
|
putString("id", session.id)
|
|
33
|
-
// TODO(CheckoutSessionsPreview): Populate from public Android checkout fields once
|
|
34
|
-
// stripe-android exposes status, paymentStatus, and livemode on CheckoutSession.
|
|
35
|
-
putString("status", "unknown")
|
|
36
|
-
putString("paymentStatus", "unknown")
|
|
37
31
|
putBoolean("livemode", false)
|
|
38
32
|
|
|
39
33
|
if (session.currency.isNotBlank()) {
|
|
40
34
|
putString("currency", session.currency)
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
putMap("status", mapFromStatus(session.status))
|
|
38
|
+
putMap("tax", mapFromTax(session.tax))
|
|
39
|
+
session.totalSummary?.let { putMap("total", mapFromTotal(it)) }
|
|
40
|
+
|
|
41
|
+
putArray("lineItems", mapFromLineItems(session))
|
|
42
|
+
putArray("shippingOptions", mapFromShippingOptions(session))
|
|
43
|
+
putArray("discountAmounts", Arguments.createArray())
|
|
44
|
+
putArray("currencyOptions", Arguments.createArray())
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
@OptIn(CheckoutSessionPreview::class)
|
|
48
|
+
private fun mapFromStatus(status: CheckoutSession.Status): WritableMap =
|
|
49
|
+
Arguments.createMap().apply {
|
|
50
|
+
putString(
|
|
51
|
+
"type",
|
|
52
|
+
when (status) {
|
|
53
|
+
CheckoutSession.Status.Open -> "open"
|
|
54
|
+
CheckoutSession.Status.Complete -> "complete"
|
|
55
|
+
CheckoutSession.Status.Expired -> "expired"
|
|
56
|
+
else -> "unknown"
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
}
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
@OptIn(CheckoutSessionPreview::class)
|
|
62
|
+
private fun mapFromTax(tax: CheckoutSession.Tax): WritableMap =
|
|
63
|
+
Arguments.createMap().apply {
|
|
64
|
+
putString(
|
|
65
|
+
"status",
|
|
66
|
+
when (tax.status) {
|
|
67
|
+
CheckoutSession.Tax.Status.Ready -> "ready"
|
|
68
|
+
CheckoutSession.Tax.Status.RequiresShippingAddress -> "requiresShippingAddress"
|
|
69
|
+
CheckoutSession.Tax.Status.RequiresBillingAddress -> "requiresBillingAddress"
|
|
70
|
+
else -> "unknown"
|
|
71
|
+
}
|
|
72
|
+
)
|
|
53
73
|
}
|
|
54
74
|
|
|
55
75
|
@OptIn(CheckoutSessionPreview::class)
|
|
56
|
-
private fun
|
|
57
|
-
|
|
76
|
+
private fun mapFromTotal(totals: CheckoutSession.TotalSummary): WritableMap =
|
|
77
|
+
Arguments.createMap().apply {
|
|
78
|
+
val taxTotal = totals.taxAmounts.sumOf { it.amount }
|
|
58
79
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
putDouble("tax", taxTotal.toDouble())
|
|
80
|
+
putMap("subtotal", makeAmount(totals.subtotal))
|
|
81
|
+
putMap("taxExclusive", makeAmount(taxTotal))
|
|
82
|
+
putMap("taxInclusive", makeAmount(0L))
|
|
83
|
+
putMap("shippingRate", makeAmount(totals.shippingRate?.amount ?: 0L))
|
|
84
|
+
putMap("discount", makeAmount(0L))
|
|
85
|
+
putMap("total", makeAmount(totals.totalAmountDue))
|
|
86
|
+
putMap("appliedBalance", makeAmount(0L))
|
|
87
|
+
putBoolean("balanceAppliedToNextInvoice", false)
|
|
68
88
|
}
|
|
69
|
-
}
|
|
70
89
|
|
|
71
90
|
@OptIn(CheckoutSessionPreview::class)
|
|
72
|
-
private fun
|
|
91
|
+
private fun mapFromLineItems(session: CheckoutSession): WritableArray =
|
|
73
92
|
Arguments.createArray().apply {
|
|
74
93
|
session.lineItems.forEach { item ->
|
|
75
94
|
pushMap(
|
|
@@ -77,25 +96,32 @@ private fun mapFromCheckoutLineItems(session: CheckoutSession): WritableArray =
|
|
|
77
96
|
putString("id", item.id)
|
|
78
97
|
putString("name", item.name)
|
|
79
98
|
putInt("quantity", item.quantity)
|
|
80
|
-
|
|
81
|
-
|
|
99
|
+
putArray("images", Arguments.createArray())
|
|
100
|
+
putArray("discountAmounts", Arguments.createArray())
|
|
101
|
+
putArray("taxAmounts", Arguments.createArray())
|
|
102
|
+
item.unitAmount?.let { putMap("unitAmount", makeAmount(it)) }
|
|
82
103
|
},
|
|
83
104
|
)
|
|
84
105
|
}
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
@OptIn(CheckoutSessionPreview::class)
|
|
88
|
-
private fun
|
|
109
|
+
private fun mapFromShippingOptions(session: CheckoutSession): WritableArray =
|
|
89
110
|
Arguments.createArray().apply {
|
|
90
111
|
session.shippingOptions.forEach { option ->
|
|
91
112
|
pushMap(
|
|
92
113
|
Arguments.createMap().apply {
|
|
93
114
|
putString("id", option.id)
|
|
94
115
|
putString("displayName", option.displayName)
|
|
95
|
-
|
|
116
|
+
putMap("amount", makeAmount(option.amount))
|
|
96
117
|
putString("currency", session.currency)
|
|
97
|
-
option.deliveryEstimate?.let { putString("deliveryEstimate", it) }
|
|
98
118
|
},
|
|
99
119
|
)
|
|
100
120
|
}
|
|
101
121
|
}
|
|
122
|
+
|
|
123
|
+
private fun makeAmount(minorUnits: Long): WritableMap =
|
|
124
|
+
Arguments.createMap().apply {
|
|
125
|
+
putString("amount", "")
|
|
126
|
+
putDouble("minorUnitsAmount", minorUnits.toDouble())
|
|
127
|
+
}
|
package/android/src/main/java/com/reactnativestripesdk/utils/DefaultActivityLifecycleCallbacks.kt
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.reactnativestripesdk.utils
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.app.Application
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
|
|
7
|
+
internal open class DefaultActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
|
|
8
|
+
override fun onActivityCreated(
|
|
9
|
+
activity: Activity,
|
|
10
|
+
savedInstanceState: Bundle?,
|
|
11
|
+
) {
|
|
12
|
+
// NO-OP
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override fun onActivityStarted(activity: Activity) {
|
|
16
|
+
// NO-OP
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun onActivityResumed(activity: Activity) {
|
|
20
|
+
// NO-OP
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override fun onActivityPaused(activity: Activity) {
|
|
24
|
+
// NO-OP
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override fun onActivityStopped(activity: Activity) {
|
|
28
|
+
// NO-OP
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun onActivitySaveInstanceState(
|
|
32
|
+
activity: Activity,
|
|
33
|
+
outState: Bundle,
|
|
34
|
+
) {
|
|
35
|
+
// NO-OP
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override fun onActivityDestroyed(activity: Activity) {
|
|
39
|
+
// NO-OP
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -17,9 +17,11 @@ import com.facebook.react.bridge.Promise;
|
|
|
17
17
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
18
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
19
19
|
import com.facebook.react.bridge.ReactMethod;
|
|
20
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
20
21
|
import com.facebook.react.bridge.ReadableMap;
|
|
21
22
|
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
|
22
23
|
import javax.annotation.Nonnull;
|
|
24
|
+
import javax.annotation.Nullable;
|
|
23
25
|
|
|
24
26
|
public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
|
|
25
27
|
public static final String NAME = "OnrampSdk";
|
|
@@ -57,6 +59,18 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
57
59
|
@DoNotStrip
|
|
58
60
|
public abstract void attachKycInfo(ReadableMap kycInfo, Promise promise);
|
|
59
61
|
|
|
62
|
+
@ReactMethod
|
|
63
|
+
@DoNotStrip
|
|
64
|
+
public abstract void retrieveMissingIdentifiers(Promise promise);
|
|
65
|
+
|
|
66
|
+
@ReactMethod
|
|
67
|
+
@DoNotStrip
|
|
68
|
+
public abstract void submitIdentifiers(ReadableArray identifiers, Promise promise);
|
|
69
|
+
|
|
70
|
+
@ReactMethod
|
|
71
|
+
@DoNotStrip
|
|
72
|
+
public abstract void presentCRSCARFDeclaration(Promise promise);
|
|
73
|
+
|
|
60
74
|
@ReactMethod
|
|
61
75
|
@DoNotStrip
|
|
62
76
|
public abstract void updatePhoneNumber(String phone, Promise promise);
|
|
@@ -71,7 +85,7 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
71
85
|
|
|
72
86
|
@ReactMethod
|
|
73
87
|
@DoNotStrip
|
|
74
|
-
public abstract void provideCheckoutClientSecret(String clientSecret);
|
|
88
|
+
public abstract void provideCheckoutClientSecret(@Nullable String clientSecret);
|
|
75
89
|
|
|
76
90
|
@ReactMethod
|
|
77
91
|
@DoNotStrip
|
|
@@ -91,11 +105,11 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
91
105
|
|
|
92
106
|
@ReactMethod
|
|
93
107
|
@DoNotStrip
|
|
94
|
-
public abstract void authenticateUserWithToken(String
|
|
108
|
+
public abstract void authenticateUserWithToken(String linkAuthTokenClientSecret, Promise promise);
|
|
95
109
|
|
|
96
110
|
@ReactMethod
|
|
97
111
|
@DoNotStrip
|
|
98
|
-
public abstract void presentKycInfoVerification(ReadableMap updatedAddress, Promise promise);
|
|
112
|
+
public abstract void presentKycInfoVerification(@Nullable ReadableMap updatedAddress, Promise promise);
|
|
99
113
|
|
|
100
114
|
@ReactMethod
|
|
101
115
|
@DoNotStrip
|
|
@@ -335,7 +335,11 @@ public abstract class NativeStripeSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
335
335
|
|
|
336
336
|
@ReactMethod
|
|
337
337
|
@DoNotStrip
|
|
338
|
-
public abstract void
|
|
338
|
+
public abstract void checkoutRunServerUpdateStart(String sessionKey, Promise promise);
|
|
339
|
+
|
|
340
|
+
@ReactMethod
|
|
341
|
+
@DoNotStrip
|
|
342
|
+
public abstract void checkoutRunServerUpdateComplete(String sessionKey, @Nullable String error, Promise promise);
|
|
339
343
|
|
|
340
344
|
@ReactMethod
|
|
341
345
|
@DoNotStrip
|
|
@@ -5,11 +5,20 @@ package com.reactnativestripesdk
|
|
|
5
5
|
import android.annotation.SuppressLint
|
|
6
6
|
import androidx.compose.ui.graphics.Color
|
|
7
7
|
import com.facebook.react.bridge.Arguments
|
|
8
|
+
import com.facebook.react.bridge.ReadableArray
|
|
8
9
|
import com.facebook.react.bridge.ReadableMap
|
|
10
|
+
import com.facebook.react.bridge.WritableArray
|
|
11
|
+
import com.stripe.android.core.model.CountryCode
|
|
9
12
|
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
10
13
|
import com.stripe.android.crypto.onramp.model.KycInfo
|
|
11
14
|
import com.stripe.android.crypto.onramp.model.OnrampConfiguration
|
|
12
15
|
import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
|
|
16
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifier
|
|
17
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierAlternativeGroup
|
|
18
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierRequirement
|
|
19
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierRequirements
|
|
20
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierType
|
|
21
|
+
import com.stripe.android.crypto.onramp.model.compliance.SubmitIdentifiersResult
|
|
13
22
|
import com.stripe.android.googlepaylauncher.GooglePayEnvironment
|
|
14
23
|
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
|
|
15
24
|
import com.stripe.android.link.LinkAppearance
|
|
@@ -178,10 +187,110 @@ internal fun mapFromKycInfo(kycInfo: KycInfo): ReadableMap {
|
|
|
178
187
|
kycInfo.idNumber?.let { result.putString("idNumber", it) }
|
|
179
188
|
kycInfo.address?.let { result.putMap("address", mapFromKycAddress(it)) }
|
|
180
189
|
kycInfo.dateOfBirth?.let { result.putMap("dateOfBirth", mapFromDateOfBirth(it)) }
|
|
190
|
+
kycInfo.birthCountry?.let { result.putString("birthCountry", it.value) }
|
|
191
|
+
kycInfo.birthCity?.let { result.putString("birthCity", it) }
|
|
192
|
+
kycInfo.nationalities?.let {
|
|
193
|
+
result.putArray("nationalities", mapFromCountryCodes(it))
|
|
194
|
+
}
|
|
181
195
|
|
|
182
196
|
return result
|
|
183
197
|
}
|
|
184
198
|
|
|
199
|
+
internal fun mapToComplianceIdentifiers(identifiers: ReadableArray): List<ComplianceIdentifier> {
|
|
200
|
+
val complianceIdentifiers = mutableListOf<ComplianceIdentifier>()
|
|
201
|
+
|
|
202
|
+
for (index in 0 until identifiers.size()) {
|
|
203
|
+
val identifierMap =
|
|
204
|
+
runCatching { identifiers.getMap(index) }
|
|
205
|
+
.getOrNull()
|
|
206
|
+
?: throw InvalidIdentifiersArrayException()
|
|
207
|
+
val type = identifierMap.getRequiredNormalizedString("type")
|
|
208
|
+
val value = identifierMap.getRequiredNormalizedString("value")
|
|
209
|
+
|
|
210
|
+
complianceIdentifiers.add(
|
|
211
|
+
ComplianceIdentifier()
|
|
212
|
+
.type(ComplianceIdentifierType(type))
|
|
213
|
+
.value(value),
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return complianceIdentifiers
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
internal fun mapFromComplianceIdentifierRequirements(
|
|
221
|
+
requirements: ComplianceIdentifierRequirements,
|
|
222
|
+
) = Arguments.createMap().apply {
|
|
223
|
+
putArray("identifiers", mapFromComplianceIdentifierRequirementsList(requirements.identifiers))
|
|
224
|
+
putArray("alternatives", mapFromComplianceIdentifierAlternativeGroups(requirements.alternatives))
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
internal fun mapFromSubmitIdentifiersResult(
|
|
228
|
+
result: SubmitIdentifiersResult,
|
|
229
|
+
) = Arguments.createMap().apply {
|
|
230
|
+
putBoolean("valid", result.valid)
|
|
231
|
+
putArray("identifiers", mapFromComplianceIdentifierRequirementsList(result.identifiers))
|
|
232
|
+
putArray("alternatives", mapFromComplianceIdentifierAlternativeGroups(result.alternatives))
|
|
233
|
+
putArray("invalidIdentifiers", mapFromComplianceIdentifierTypes(result.invalidIdentifiers))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private fun mapFromComplianceIdentifierRequirementsList(
|
|
237
|
+
requirements: List<ComplianceIdentifierRequirement>,
|
|
238
|
+
): WritableArray =
|
|
239
|
+
Arguments.createArray().apply {
|
|
240
|
+
requirements.forEach { requirement ->
|
|
241
|
+
pushMap(
|
|
242
|
+
Arguments.createMap().apply {
|
|
243
|
+
putString("type", requirement.type.value)
|
|
244
|
+
putString("regulation", requirement.regulation.value)
|
|
245
|
+
},
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private fun mapFromComplianceIdentifierAlternativeGroups(
|
|
251
|
+
groups: List<ComplianceIdentifierAlternativeGroup>,
|
|
252
|
+
): WritableArray =
|
|
253
|
+
Arguments.createArray().apply {
|
|
254
|
+
groups.forEach { group ->
|
|
255
|
+
pushMap(
|
|
256
|
+
Arguments.createMap().apply {
|
|
257
|
+
putArray(
|
|
258
|
+
"originalMissingIdentifiers",
|
|
259
|
+
mapFromComplianceIdentifierTypes(group.originalMissingIdentifiers),
|
|
260
|
+
)
|
|
261
|
+
putArray(
|
|
262
|
+
"alternativeMissingIdentifiers",
|
|
263
|
+
mapFromComplianceIdentifierTypes(group.alternativeMissingIdentifiers),
|
|
264
|
+
)
|
|
265
|
+
},
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private fun mapFromComplianceIdentifierTypes(
|
|
271
|
+
identifierTypes: List<ComplianceIdentifierType>,
|
|
272
|
+
): WritableArray =
|
|
273
|
+
Arguments.createArray().apply {
|
|
274
|
+
identifierTypes.forEach { identifierType ->
|
|
275
|
+
pushString(identifierType.value)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private fun mapFromCountryCodes(
|
|
280
|
+
countryCodes: List<CountryCode>,
|
|
281
|
+
): WritableArray =
|
|
282
|
+
Arguments.createArray().apply {
|
|
283
|
+
countryCodes.forEach { countryCode ->
|
|
284
|
+
pushString(countryCode.value)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private fun ReadableMap.getRequiredNormalizedString(key: String): String =
|
|
289
|
+
getString(key)
|
|
290
|
+
?.trim()
|
|
291
|
+
?.takeIf { it.isNotEmpty() }
|
|
292
|
+
?: throw ComplianceIdentifierFieldException(key)
|
|
293
|
+
|
|
185
294
|
private fun mapFromKycAddress(address: PaymentSheet.Address): ReadableMap {
|
|
186
295
|
val result = Arguments.createMap()
|
|
187
296
|
|
|
@@ -202,3 +311,10 @@ private fun mapFromDateOfBirth(dateOfBirth: DateOfBirth): ReadableMap {
|
|
|
202
311
|
result.putInt("year", dateOfBirth.year)
|
|
203
312
|
return result
|
|
204
313
|
}
|
|
314
|
+
|
|
315
|
+
internal class ComplianceIdentifierFieldException(
|
|
316
|
+
field: String,
|
|
317
|
+
) : IllegalArgumentException("Invalid format for field: $field")
|
|
318
|
+
|
|
319
|
+
internal class InvalidIdentifiersArrayException :
|
|
320
|
+
IllegalArgumentException("Unexpected format of identifiers array. Expected dictionaries with String keys.")
|
|
@@ -7,10 +7,12 @@ import android.app.Application
|
|
|
7
7
|
import androidx.activity.ComponentActivity
|
|
8
8
|
import androidx.fragment.app.FragmentActivity
|
|
9
9
|
import androidx.lifecycle.SavedStateHandle
|
|
10
|
+
import com.stripe.android.core.model.CountryCode
|
|
10
11
|
import com.facebook.react.bridge.Arguments
|
|
11
12
|
import com.facebook.react.bridge.Promise
|
|
12
13
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
13
14
|
import com.facebook.react.bridge.ReactMethod
|
|
15
|
+
import com.facebook.react.bridge.ReadableArray
|
|
14
16
|
import com.facebook.react.bridge.ReadableMap
|
|
15
17
|
import com.facebook.react.bridge.WritableNativeMap
|
|
16
18
|
import com.facebook.react.module.annotations.ReactModule
|
|
@@ -23,6 +25,7 @@ import com.reactnativestripesdk.utils.createMissingActivityError
|
|
|
23
25
|
import com.reactnativestripesdk.utils.createMissingInitError
|
|
24
26
|
import com.reactnativestripesdk.utils.createOnrampNotConfiguredError
|
|
25
27
|
import com.reactnativestripesdk.utils.createResult
|
|
28
|
+
import com.reactnativestripesdk.utils.getStringList
|
|
26
29
|
import com.reactnativestripesdk.utils.getValOr
|
|
27
30
|
import com.reactnativestripesdk.utils.mapToPaymentSheetAddress
|
|
28
31
|
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
@@ -37,10 +40,13 @@ import com.stripe.android.crypto.onramp.model.OnrampCheckoutResult
|
|
|
37
40
|
import com.stripe.android.crypto.onramp.model.OnrampCollectPaymentMethodResult
|
|
38
41
|
import com.stripe.android.crypto.onramp.model.OnrampConfigurationResult
|
|
39
42
|
import com.stripe.android.crypto.onramp.model.OnrampCreateCryptoPaymentTokenResult
|
|
43
|
+
import com.stripe.android.crypto.onramp.model.OnrampCrsCarfDeclarationResult
|
|
40
44
|
import com.stripe.android.crypto.onramp.model.OnrampHasLinkAccountResult
|
|
41
45
|
import com.stripe.android.crypto.onramp.model.OnrampLogOutResult
|
|
42
46
|
import com.stripe.android.crypto.onramp.model.OnrampRegisterLinkUserResult
|
|
43
47
|
import com.stripe.android.crypto.onramp.model.OnrampRegisterWalletAddressResult
|
|
48
|
+
import com.stripe.android.crypto.onramp.model.OnrampRetrieveMissingIdentifiersResult
|
|
49
|
+
import com.stripe.android.crypto.onramp.model.OnrampSubmitIdentifiersResult
|
|
44
50
|
import com.stripe.android.crypto.onramp.model.OnrampTokenAuthenticationResult
|
|
45
51
|
import com.stripe.android.crypto.onramp.model.OnrampUpdatePhoneNumberResult
|
|
46
52
|
import com.stripe.android.crypto.onramp.model.OnrampVerifyIdentityResult
|
|
@@ -78,6 +84,7 @@ class OnrampSdkModule(
|
|
|
78
84
|
private var authorizePromise: Promise? = null
|
|
79
85
|
private var checkoutPromise: Promise? = null
|
|
80
86
|
private var verifyKycPromise: Promise? = null
|
|
87
|
+
private var crsCarfDeclarationPromise: Promise? = null
|
|
81
88
|
|
|
82
89
|
private var checkoutClientSecretDeferred: CompletableDeferred<String>? = null
|
|
83
90
|
private val rnScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
@@ -141,6 +148,10 @@ class OnrampSdkModule(
|
|
|
141
148
|
handleOnrampCheckoutResult(result, checkoutPromise!!)
|
|
142
149
|
}.verifyKycCallback { result ->
|
|
143
150
|
handleOnrampKycVerificationResult(result, verifyKycPromise!!)
|
|
151
|
+
}.crsCarfDeclarationCallback { result ->
|
|
152
|
+
crsCarfDeclarationPromise?.let {
|
|
153
|
+
handleOnrampCrsCarfDeclarationResult(result, it)
|
|
154
|
+
}
|
|
144
155
|
}.onrampSessionClientSecretProvider { sessionId ->
|
|
145
156
|
checkoutClientSecretDeferred = CompletableDeferred()
|
|
146
157
|
|
|
@@ -311,10 +322,16 @@ class OnrampSdkModule(
|
|
|
311
322
|
)
|
|
312
323
|
} else {
|
|
313
324
|
null
|
|
314
|
-
|
|
325
|
+
}
|
|
315
326
|
|
|
316
327
|
val addressMap = kycInfo.getMap("address")
|
|
317
328
|
val addressObj = mapToPaymentSheetAddress(addressMap)
|
|
329
|
+
val birthCountry = kycInfo.getString("birthCountry")?.let(CountryCode::create)
|
|
330
|
+
val birthCity = kycInfo.getString("birthCity")
|
|
331
|
+
val nationalities =
|
|
332
|
+
kycInfo.getStringList("nationalities")
|
|
333
|
+
?.map(CountryCode::create)
|
|
334
|
+
?.takeIf { it.isNotEmpty() }
|
|
318
335
|
|
|
319
336
|
val kycInfoObj =
|
|
320
337
|
KycInfo(
|
|
@@ -323,6 +340,9 @@ class OnrampSdkModule(
|
|
|
323
340
|
idNumber = idNumber,
|
|
324
341
|
dateOfBirth = dob,
|
|
325
342
|
address = addressObj,
|
|
343
|
+
birthCountry = birthCountry,
|
|
344
|
+
birthCity = birthCity,
|
|
345
|
+
nationalities = nationalities,
|
|
326
346
|
)
|
|
327
347
|
|
|
328
348
|
when (val result = coordinator.attachKycInfo(kycInfoObj)) {
|
|
@@ -336,6 +356,75 @@ class OnrampSdkModule(
|
|
|
336
356
|
}
|
|
337
357
|
}
|
|
338
358
|
|
|
359
|
+
@ReactMethod
|
|
360
|
+
override fun retrieveMissingIdentifiers(promise: Promise) {
|
|
361
|
+
val coordinator =
|
|
362
|
+
onrampCoordinator ?: run {
|
|
363
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
364
|
+
return
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
368
|
+
when (val result = coordinator.retrieveMissingIdentifiers()) {
|
|
369
|
+
is OnrampRetrieveMissingIdentifiersResult.Completed -> {
|
|
370
|
+
promise.resolve(mapFromComplianceIdentifierRequirements(result.requirements))
|
|
371
|
+
}
|
|
372
|
+
is OnrampRetrieveMissingIdentifiersResult.Failed -> {
|
|
373
|
+
promise.resolve(createFailedError(result.error))
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
@ReactMethod
|
|
380
|
+
override fun submitIdentifiers(
|
|
381
|
+
identifiers: ReadableArray,
|
|
382
|
+
promise: Promise,
|
|
383
|
+
) {
|
|
384
|
+
val coordinator =
|
|
385
|
+
onrampCoordinator ?: run {
|
|
386
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
val complianceIdentifiers =
|
|
391
|
+
try {
|
|
392
|
+
mapToComplianceIdentifiers(identifiers)
|
|
393
|
+
} catch (error: IllegalArgumentException) {
|
|
394
|
+
val errorType =
|
|
395
|
+
if (error is ComplianceIdentifierFieldException) {
|
|
396
|
+
ErrorType.Unknown
|
|
397
|
+
} else {
|
|
398
|
+
ErrorType.Failed
|
|
399
|
+
}
|
|
400
|
+
promise.resolve(createError(errorType.toString(), error.message ?: "Invalid identifiers"))
|
|
401
|
+
return
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
405
|
+
when (val result = coordinator.submitIdentifiers(complianceIdentifiers)) {
|
|
406
|
+
is OnrampSubmitIdentifiersResult.Completed -> {
|
|
407
|
+
promise.resolve(mapFromSubmitIdentifiersResult(result.result))
|
|
408
|
+
}
|
|
409
|
+
is OnrampSubmitIdentifiersResult.Failed -> {
|
|
410
|
+
promise.resolve(createFailedError(result.error))
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
@ReactMethod
|
|
417
|
+
override fun presentCRSCARFDeclaration(promise: Promise) {
|
|
418
|
+
val presenter =
|
|
419
|
+
onrampPresenter ?: run {
|
|
420
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
421
|
+
return
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
crsCarfDeclarationPromise = promise
|
|
425
|
+
presenter.presentCrsCarfDeclaration()
|
|
426
|
+
}
|
|
427
|
+
|
|
339
428
|
@ReactMethod
|
|
340
429
|
override fun updatePhoneNumber(
|
|
341
430
|
phone: String,
|
|
@@ -689,6 +778,25 @@ class OnrampSdkModule(
|
|
|
689
778
|
}
|
|
690
779
|
}
|
|
691
780
|
|
|
781
|
+
private fun handleOnrampCrsCarfDeclarationResult(
|
|
782
|
+
result: OnrampCrsCarfDeclarationResult,
|
|
783
|
+
promise: Promise,
|
|
784
|
+
) {
|
|
785
|
+
when (result) {
|
|
786
|
+
is OnrampCrsCarfDeclarationResult.Confirmed -> {
|
|
787
|
+
promise.resolve(
|
|
788
|
+
WritableNativeMap().apply { putString("status", "Confirmed") },
|
|
789
|
+
)
|
|
790
|
+
}
|
|
791
|
+
is OnrampCrsCarfDeclarationResult.Cancelled -> {
|
|
792
|
+
promise.resolve(createCanceledError("CRS/CARF declaration was cancelled"))
|
|
793
|
+
}
|
|
794
|
+
is OnrampCrsCarfDeclarationResult.Failed -> {
|
|
795
|
+
promise.resolve(createFailedError(result.error))
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
692
800
|
private fun handleOnrampCollectPaymentResult(
|
|
693
801
|
result: OnrampCollectPaymentMethodResult,
|
|
694
802
|
promise: Promise,
|
|
@@ -41,9 +41,13 @@ class DrawableLoadingTest {
|
|
|
41
41
|
canvas.drawColor(Color.RED)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
override fun setAlpha(alpha: Int) {
|
|
44
|
+
override fun setAlpha(alpha: Int) {
|
|
45
|
+
// NO-OP
|
|
46
|
+
}
|
|
45
47
|
|
|
46
|
-
override fun setColorFilter(colorFilter: ColorFilter?) {
|
|
48
|
+
override fun setColorFilter(colorFilter: ColorFilter?) {
|
|
49
|
+
// NO-OP
|
|
50
|
+
}
|
|
47
51
|
|
|
48
52
|
override fun getOpacity(): Int = PixelFormat.OPAQUE
|
|
49
53
|
}
|