@stripe/stripe-react-native 0.59.0 → 0.59.2
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/README.md +5 -2
- package/android/gradle.properties +1 -1
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/reactnativestripesdk/FakeOnrampSdkModule.kt +0 -5
- package/android/src/main/java/com/reactnativestripesdk/PaymentElementConfig.kt +17 -5
- package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt +1 -1
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +1 -8
- package/android/src/main/java/com/reactnativestripesdk/StripeFileProvider.kt +17 -0
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +1 -1
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +0 -4
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +103 -0
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +97 -187
- package/android/src/test/java/com/reactnativestripesdk/PaymentElementConfigTest.kt +52 -17
- package/android/src/test/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfigTest.kt +3 -3
- package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +219 -0
- package/ios/PaymentMethodMessagingElementConfig.swift +3 -3
- package/ios/StripeOnrampSdk.mm +0 -6
- package/ios/StripeSdkImpl+PaymentSheet.swift +20 -7
- package/ios/StripeSdkImpl.swift +2 -36
- package/jest/setup.js +0 -1
- package/lib/commonjs/components/AddToWalletButton.js +1 -1
- package/lib/commonjs/components/AddressSheet.js +1 -1
- package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
- package/lib/commonjs/components/CardField.js +1 -1
- package/lib/commonjs/components/CardForm.js +1 -1
- package/lib/commonjs/components/PlatformPayButton.js +1 -1
- package/lib/commonjs/components/StripeContainer.js +1 -1
- package/lib/commonjs/connect/Components.js +1 -1
- package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
- package/lib/commonjs/connect/EmbeddedComponent.js +1 -1
- package/lib/commonjs/connect/ModalCloseButton.js +1 -1
- package/lib/commonjs/connect/NavigationBar.js +1 -1
- package/lib/commonjs/helpers.js +1 -1
- package/lib/commonjs/hooks/useOnramp.js +1 -1
- package/lib/commonjs/hooks/useOnramp.js.map +1 -1
- package/lib/commonjs/specs/NativeAddToWalletButton.js +1 -1
- package/lib/commonjs/specs/NativeAddressSheet.js +1 -1
- package/lib/commonjs/specs/NativeApplePayButton.js +1 -1
- package/lib/commonjs/specs/NativeAuBECSDebitForm.js +1 -1
- package/lib/commonjs/specs/NativeCardField.js +1 -1
- package/lib/commonjs/specs/NativeCardForm.js +1 -1
- package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
- package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
- package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
- package/lib/commonjs/specs/NativeNavigationBar.js +1 -1
- package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/commonjs/specs/NativePaymentMethodMessagingElement.js +1 -1
- package/lib/commonjs/specs/NativeStripeContainer.js +1 -1
- package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
- package/lib/commonjs/types/PaymentSheet.js +1 -1
- package/lib/commonjs/types/PaymentSheet.js.map +1 -1
- package/lib/module/components/AddToWalletButton.js +1 -1
- package/lib/module/components/AddressSheet.js +1 -1
- package/lib/module/components/AuBECSDebitForm.js +1 -1
- package/lib/module/components/CardField.js +1 -1
- package/lib/module/components/CardForm.js +1 -1
- package/lib/module/components/PlatformPayButton.js +1 -1
- package/lib/module/components/StripeContainer.js +1 -1
- package/lib/module/connect/Components.js +1 -1
- package/lib/module/connect/ConnectComponentsProvider.js +1 -1
- package/lib/module/connect/EmbeddedComponent.js +1 -1
- package/lib/module/connect/ModalCloseButton.js +1 -1
- package/lib/module/connect/NavigationBar.js +1 -1
- package/lib/module/helpers.js +1 -1
- package/lib/module/hooks/useOnramp.js +1 -1
- package/lib/module/hooks/useOnramp.js.map +1 -1
- package/lib/module/specs/NativeAddToWalletButton.js +1 -1
- package/lib/module/specs/NativeAddressSheet.js +1 -1
- package/lib/module/specs/NativeApplePayButton.js +1 -1
- package/lib/module/specs/NativeAuBECSDebitForm.js +1 -1
- package/lib/module/specs/NativeCardField.js +1 -1
- package/lib/module/specs/NativeCardForm.js +1 -1
- package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
- package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
- package/lib/module/specs/NativeGooglePayButton.js +1 -1
- package/lib/module/specs/NativeNavigationBar.js +1 -1
- package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/module/specs/NativePaymentMethodMessagingElement.js +1 -1
- package/lib/module/specs/NativeStripeContainer.js +1 -1
- package/lib/module/types/EmbeddedPaymentElement.js +1 -1
- package/lib/module/types/PaymentSheet.js +1 -1
- package/lib/module/types/PaymentSheet.js.map +1 -1
- package/lib/typescript/src/hooks/useOnramp.d.ts +2 -8
- package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +0 -1
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
- package/lib/typescript/src/types/Onramp.d.ts +0 -12
- package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
- package/lib/typescript/src/types/PaymentSheet.d.ts +22 -0
- package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/hooks/useOnramp.tsx +2 -14
- package/src/specs/NativeOnrampSdkModule.ts +0 -1
- package/src/types/Onramp.ts +0 -15
- package/src/types/PaymentSheet.ts +23 -0
- package/stripe-react-native.podspec +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,10 @@ Get started with our [📚 integration guides](https://stripe.com/docs/payments/
|
|
|
23
23
|
|
|
24
24
|
**Native UI**: We provide native screens and elements to securely collect payment details on Android and iOS.
|
|
25
25
|
|
|
26
|
-
**PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps.
|
|
26
|
+
**PaymentSheet**: [Learn how to integrate](https://stripe.com/docs/payments/accept-a-payment) PaymentSheet, our new pre-built payments UI for mobile apps.
|
|
27
|
+
- PaymentSheet lets you accept cards, Apple Pay, Google Pay, and much more out of the box and also supports saving & reusing payment methods.
|
|
28
|
+
- PaymentSheet currently accepts the following payment methods: Card, Apple Pay, Google Pay, SEPA Debit, Bancontact, Billie, iDEAL, EPS, P24, Afterpay/Clearpay, Klarna, Giropay, and ACH.
|
|
29
|
+
- PaymentSheet provides card scanning on iOS and Android, with the Android functionality provided by [Google Payment Card Recognition](https://developers.google.com/pay/payment-card-recognition/debit-credit-card-recognition). To enable card scanning in your app, follow [our guide](https://docs.corp.stripe.com/payments/accept-a-payment?payment-ui=mobile&platform=react-native#react-native-card-scanning).
|
|
27
30
|
|
|
28
31
|
#### Recommended usage
|
|
29
32
|
|
|
@@ -283,5 +286,5 @@ While installing pods in your iOS project using a Stripe React Native version be
|
|
|
283
286
|
UnsupportedModulePropertyParserError: Module NativeStripeSdkModule: TypeScript interfaces extending TurboModule must only contain 'FunctionTypeAnnotation's. Property 'onConfirmHandlerCallback' refers to a 'TSTypeReference'.
|
|
284
287
|
```
|
|
285
288
|
|
|
286
|
-
If possible, update to version 0.52 or above of the Stripe React Native SDK.
|
|
289
|
+
If possible, update to version 0.52 or above of the Stripe React Native SDK.
|
|
287
290
|
If you are unable to do so, please follow our [guide to apply the fix patch](https://github.com/stripe/stripe-react-native/tree/master/patches).
|
|
@@ -3,4 +3,4 @@ StripeSdk_compileSdkVersion=30
|
|
|
3
3
|
StripeSdk_targetSdkVersion=28
|
|
4
4
|
StripeSdk_minSdkVersion=21
|
|
5
5
|
# Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
|
|
6
|
-
StripeSdk_stripeVersion=22.
|
|
6
|
+
StripeSdk_stripeVersion=22.8.+
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
</activity>
|
|
28
28
|
|
|
29
29
|
<provider
|
|
30
|
-
android:name="
|
|
31
|
-
android:authorities="${applicationId}.
|
|
30
|
+
android:name="com.reactnativestripesdk.StripeFileProvider"
|
|
31
|
+
android:authorities="${applicationId}.fileprovider"
|
|
32
32
|
android:exported="false"
|
|
33
33
|
android:grantUriPermissions="true">
|
|
34
34
|
<meta-data
|
|
@@ -68,11 +68,6 @@ class FakeOnrampSdkModule(
|
|
|
68
68
|
promise?.resolveNotImplemented()
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
@ReactMethod
|
|
72
|
-
override fun authenticateUser(promise: Promise?) {
|
|
73
|
-
promise?.resolveNotImplemented()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
71
|
@ReactMethod
|
|
77
72
|
override fun verifyIdentity(promise: Promise?) {
|
|
78
73
|
promise?.resolveNotImplemented()
|
|
@@ -2,6 +2,7 @@ package com.reactnativestripesdk
|
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.ReadableMap
|
|
4
4
|
import com.reactnativestripesdk.utils.PaymentSheetException
|
|
5
|
+
import com.reactnativestripesdk.utils.forEachKey
|
|
5
6
|
import com.reactnativestripesdk.utils.getBooleanOr
|
|
6
7
|
import com.reactnativestripesdk.utils.getIntOr
|
|
7
8
|
import com.reactnativestripesdk.utils.getLongOr
|
|
@@ -78,12 +79,23 @@ private fun mapStringToLinkDisplay(value: String?): PaymentSheet.LinkConfigurati
|
|
|
78
79
|
else -> PaymentSheet.LinkConfiguration.Display.Automatic
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
internal fun
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
internal fun mapToTermsDisplay(params: ReadableMap?): Map<PaymentMethod.Type, PaymentSheet.TermsDisplay>? {
|
|
83
|
+
val termsDisplayMap = params?.getMap("termsDisplay") ?: return null
|
|
84
|
+
val result = mutableMapOf<PaymentMethod.Type, PaymentSheet.TermsDisplay>()
|
|
85
|
+
termsDisplayMap.forEachKey { code ->
|
|
86
|
+
val paymentMethodType = PaymentMethod.Type.fromCode(code)
|
|
87
|
+
val termsDisplay =
|
|
88
|
+
when (termsDisplayMap.getString(code)) {
|
|
89
|
+
"never" -> PaymentSheet.TermsDisplay.NEVER
|
|
90
|
+
"automatic" -> PaymentSheet.TermsDisplay.AUTOMATIC
|
|
91
|
+
else -> null
|
|
92
|
+
}
|
|
93
|
+
if (paymentMethodType != null && termsDisplay != null) {
|
|
94
|
+
result[paymentMethodType] = termsDisplay
|
|
95
|
+
}
|
|
86
96
|
}
|
|
97
|
+
return result.ifEmpty { null }
|
|
98
|
+
}
|
|
87
99
|
|
|
88
100
|
private val mapIntToButtonType =
|
|
89
101
|
mapOf(
|
package/android/src/main/java/com/reactnativestripesdk/PaymentMethodMessagingElementConfig.kt
CHANGED
|
@@ -61,7 +61,7 @@ fun parseAppearance(
|
|
|
61
61
|
font?.let { appearance.font(font) }
|
|
62
62
|
val colors = PaymentMethodMessagingElement.Appearance.Colors()
|
|
63
63
|
textColor?.let { colors.textColor(it) }
|
|
64
|
-
linkTextColor?.let { colors.
|
|
64
|
+
linkTextColor?.let { colors.linkTextColor(linkTextColor) }
|
|
65
65
|
appearance.colors(colors)
|
|
66
66
|
|
|
67
67
|
return appearance
|
|
@@ -39,7 +39,6 @@ import com.reactnativestripesdk.utils.mapFromPaymentMethod
|
|
|
39
39
|
import com.reactnativestripesdk.utils.mapToPreferredNetworks
|
|
40
40
|
import com.reactnativestripesdk.utils.parseCustomPaymentMethods
|
|
41
41
|
import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
|
|
42
|
-
import com.stripe.android.PaymentConfiguration
|
|
43
42
|
import com.stripe.android.core.reactnative.ReactNativeSdkInternal
|
|
44
43
|
import com.stripe.android.model.PaymentMethod
|
|
45
44
|
import com.stripe.android.paymentelement.ConfirmCustomPaymentMethodCallback
|
|
@@ -299,13 +298,7 @@ class PaymentSheetManager(
|
|
|
299
298
|
mapToPaymentMethodLayout(arguments.getString("paymentMethodLayout")),
|
|
300
299
|
)
|
|
301
300
|
|
|
302
|
-
|
|
303
|
-
computeTermsDisplayForUserKey(
|
|
304
|
-
PaymentConfiguration.getInstance(context).publishableKey,
|
|
305
|
-
)
|
|
306
|
-
if (userKeyTermsDisplay.isNotEmpty()) {
|
|
307
|
-
configurationBuilder.termsDisplay(userKeyTermsDisplay)
|
|
308
|
-
}
|
|
301
|
+
mapToTermsDisplay(arguments)?.let { configurationBuilder.termsDisplay(it) }
|
|
309
302
|
|
|
310
303
|
paymentSheetConfiguration = configurationBuilder.build()
|
|
311
304
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.reactnativestripesdk
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A custom FileProvider subclass for the Stripe React Native SDK.
|
|
5
|
+
*
|
|
6
|
+
* This class extends androidx.core.content.FileProvider to provide a unique
|
|
7
|
+
* android:name in the manifest, preventing conflicts with other libraries that
|
|
8
|
+
* also use FileProvider (e.g., react-native-document-viewer, expo-file-system).
|
|
9
|
+
*
|
|
10
|
+
* By using a library-specific class name, the Android manifest merger keeps
|
|
11
|
+
* this provider separate from other FileProviders, avoiding the
|
|
12
|
+
* "Attribute provider@authorities value=... is also present at..." error.
|
|
13
|
+
*
|
|
14
|
+
* No additional implementation is needed - this simply inherits all functionality
|
|
15
|
+
* from the parent FileProvider class.
|
|
16
|
+
*/
|
|
17
|
+
class StripeFileProvider : androidx.core.content.FileProvider()
|
|
@@ -1518,7 +1518,7 @@ class StripeSdkModule(
|
|
|
1518
1518
|
val uri =
|
|
1519
1519
|
androidx.core.content.FileProvider.getUriForFile(
|
|
1520
1520
|
reactApplicationContext,
|
|
1521
|
-
"${reactApplicationContext.packageName}.
|
|
1521
|
+
"${reactApplicationContext.packageName}.fileprovider",
|
|
1522
1522
|
file,
|
|
1523
1523
|
)
|
|
1524
1524
|
|
|
@@ -72,10 +72,6 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
72
72
|
@DoNotStrip
|
|
73
73
|
public abstract void updatePhoneNumber(String phone, Promise promise);
|
|
74
74
|
|
|
75
|
-
@ReactMethod
|
|
76
|
-
@DoNotStrip
|
|
77
|
-
public abstract void authenticateUser(Promise promise);
|
|
78
|
-
|
|
79
75
|
@ReactMethod
|
|
80
76
|
@DoNotStrip
|
|
81
77
|
public abstract void verifyIdentity(Promise promise);
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package com.reactnativestripesdk
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import androidx.compose.ui.graphics.Color
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.stripe.android.crypto.onramp.model.OnrampConfiguration
|
|
7
|
+
import com.stripe.android.link.LinkAppearance
|
|
8
|
+
import com.stripe.android.link.LinkAppearance.Colors
|
|
9
|
+
import com.stripe.android.link.LinkAppearance.PrimaryButton
|
|
10
|
+
import com.stripe.android.link.LinkAppearance.Style
|
|
11
|
+
|
|
12
|
+
@SuppressLint("RestrictedApi")
|
|
13
|
+
internal fun mapConfig(
|
|
14
|
+
configMap: ReadableMap,
|
|
15
|
+
publishableKey: String,
|
|
16
|
+
): OnrampConfiguration {
|
|
17
|
+
val appearanceMap = configMap.getMap("appearance")
|
|
18
|
+
val appearance =
|
|
19
|
+
if (appearanceMap != null) {
|
|
20
|
+
mapAppearance(appearanceMap)
|
|
21
|
+
} else {
|
|
22
|
+
LinkAppearance()
|
|
23
|
+
.style(Style.AUTOMATIC)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
val displayName = configMap.getString("merchantDisplayName") ?: ""
|
|
27
|
+
val cryptoCustomerId = configMap.getString("cryptoCustomerId")
|
|
28
|
+
|
|
29
|
+
return OnrampConfiguration()
|
|
30
|
+
.merchantDisplayName(displayName)
|
|
31
|
+
.publishableKey(publishableKey)
|
|
32
|
+
.appearance(appearance)
|
|
33
|
+
.cryptoCustomerId(cryptoCustomerId)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@SuppressLint("RestrictedApi")
|
|
37
|
+
internal fun mapAppearance(appearanceMap: ReadableMap): LinkAppearance {
|
|
38
|
+
val lightColorsMap = appearanceMap.getMap("lightColors")
|
|
39
|
+
val darkColorsMap = appearanceMap.getMap("darkColors")
|
|
40
|
+
val styleStr = appearanceMap.getString("style")
|
|
41
|
+
val primaryButtonMap = appearanceMap.getMap("primaryButton")
|
|
42
|
+
|
|
43
|
+
val lightColors =
|
|
44
|
+
if (lightColorsMap != null) {
|
|
45
|
+
val primaryColorStr = lightColorsMap.getString("primary")
|
|
46
|
+
val contentColorStr = lightColorsMap.getString("contentOnPrimary")
|
|
47
|
+
val borderSelectedColorStr = lightColorsMap.getString("borderSelected")
|
|
48
|
+
|
|
49
|
+
Colors()
|
|
50
|
+
.primary(Color(android.graphics.Color.parseColor(primaryColorStr)))
|
|
51
|
+
.contentOnPrimary(Color(android.graphics.Color.parseColor(contentColorStr)))
|
|
52
|
+
.borderSelected(Color(android.graphics.Color.parseColor(borderSelectedColorStr)))
|
|
53
|
+
} else {
|
|
54
|
+
Colors()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
val darkColors =
|
|
58
|
+
if (darkColorsMap != null) {
|
|
59
|
+
val primaryColorStr = darkColorsMap.getString("primary")
|
|
60
|
+
val contentColorStr = darkColorsMap.getString("contentOnPrimary")
|
|
61
|
+
val borderSelectedColorStr = darkColorsMap.getString("borderSelected")
|
|
62
|
+
|
|
63
|
+
Colors()
|
|
64
|
+
.primary(Color(android.graphics.Color.parseColor(primaryColorStr)))
|
|
65
|
+
.contentOnPrimary(Color(android.graphics.Color.parseColor(contentColorStr)))
|
|
66
|
+
.borderSelected(Color(android.graphics.Color.parseColor(borderSelectedColorStr)))
|
|
67
|
+
} else {
|
|
68
|
+
Colors()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
val style =
|
|
72
|
+
when (styleStr) {
|
|
73
|
+
"ALWAYS_LIGHT" -> Style.ALWAYS_LIGHT
|
|
74
|
+
"ALWAYS_DARK" -> Style.ALWAYS_DARK
|
|
75
|
+
else -> Style.AUTOMATIC
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
val primaryButton =
|
|
79
|
+
if (primaryButtonMap != null) {
|
|
80
|
+
PrimaryButton()
|
|
81
|
+
.cornerRadiusDp(
|
|
82
|
+
if (primaryButtonMap.hasKey("cornerRadius")) {
|
|
83
|
+
primaryButtonMap.getDouble("cornerRadius").toFloat()
|
|
84
|
+
} else {
|
|
85
|
+
null
|
|
86
|
+
},
|
|
87
|
+
).heightDp(
|
|
88
|
+
if (primaryButtonMap.hasKey("height")) {
|
|
89
|
+
primaryButtonMap.getDouble("height").toFloat()
|
|
90
|
+
} else {
|
|
91
|
+
null
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
} else {
|
|
95
|
+
PrimaryButton()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return LinkAppearance()
|
|
99
|
+
.lightColors(lightColors)
|
|
100
|
+
.darkColors(darkColors)
|
|
101
|
+
.style(style)
|
|
102
|
+
.primaryButton(primaryButton)
|
|
103
|
+
}
|
|
@@ -3,8 +3,6 @@ package com.reactnativestripesdk
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.app.Application
|
|
5
5
|
import androidx.activity.ComponentActivity
|
|
6
|
-
import androidx.compose.ui.graphics.Color
|
|
7
|
-
import androidx.core.content.ContextCompat
|
|
8
6
|
import androidx.fragment.app.FragmentActivity
|
|
9
7
|
import androidx.lifecycle.SavedStateHandle
|
|
10
8
|
import com.facebook.react.bridge.Arguments
|
|
@@ -30,12 +28,10 @@ import com.stripe.android.crypto.onramp.model.CryptoNetwork
|
|
|
30
28
|
import com.stripe.android.crypto.onramp.model.KycInfo
|
|
31
29
|
import com.stripe.android.crypto.onramp.model.LinkUserInfo
|
|
32
30
|
import com.stripe.android.crypto.onramp.model.OnrampAttachKycInfoResult
|
|
33
|
-
import com.stripe.android.crypto.onramp.model.OnrampAuthenticateResult
|
|
34
31
|
import com.stripe.android.crypto.onramp.model.OnrampAuthorizeResult
|
|
35
32
|
import com.stripe.android.crypto.onramp.model.OnrampCallbacks
|
|
36
33
|
import com.stripe.android.crypto.onramp.model.OnrampCheckoutResult
|
|
37
34
|
import com.stripe.android.crypto.onramp.model.OnrampCollectPaymentMethodResult
|
|
38
|
-
import com.stripe.android.crypto.onramp.model.OnrampConfiguration
|
|
39
35
|
import com.stripe.android.crypto.onramp.model.OnrampConfigurationResult
|
|
40
36
|
import com.stripe.android.crypto.onramp.model.OnrampCreateCryptoPaymentTokenResult
|
|
41
37
|
import com.stripe.android.crypto.onramp.model.OnrampHasLinkAccountResult
|
|
@@ -47,10 +43,6 @@ import com.stripe.android.crypto.onramp.model.OnrampUpdatePhoneNumberResult
|
|
|
47
43
|
import com.stripe.android.crypto.onramp.model.OnrampVerifyIdentityResult
|
|
48
44
|
import com.stripe.android.crypto.onramp.model.OnrampVerifyKycInfoResult
|
|
49
45
|
import com.stripe.android.crypto.onramp.model.PaymentMethodType
|
|
50
|
-
import com.stripe.android.link.LinkAppearance
|
|
51
|
-
import com.stripe.android.link.LinkAppearance.Colors
|
|
52
|
-
import com.stripe.android.link.LinkAppearance.PrimaryButton
|
|
53
|
-
import com.stripe.android.link.LinkAppearance.Style
|
|
54
46
|
import com.stripe.android.link.LinkController.PaymentMethodPreview
|
|
55
47
|
import com.stripe.android.link.PaymentMethodPreviewDetails
|
|
56
48
|
import com.stripe.android.model.CardBrand
|
|
@@ -59,8 +51,11 @@ import com.stripe.android.paymentsheet.PaymentSheet
|
|
|
59
51
|
import kotlinx.coroutines.CompletableDeferred
|
|
60
52
|
import kotlinx.coroutines.CoroutineScope
|
|
61
53
|
import kotlinx.coroutines.Dispatchers
|
|
54
|
+
import kotlinx.coroutines.SupervisorJob
|
|
55
|
+
import kotlinx.coroutines.cancel
|
|
62
56
|
import kotlinx.coroutines.launch
|
|
63
57
|
import kotlinx.coroutines.withContext
|
|
58
|
+
import kotlinx.coroutines.withTimeout
|
|
64
59
|
|
|
65
60
|
@SuppressLint("RestrictedApi")
|
|
66
61
|
@ReactModule(name = NativeOnrampSdkModuleSpec.NAME)
|
|
@@ -81,6 +76,7 @@ class OnrampSdkModule(
|
|
|
81
76
|
private var verifyKycPromise: Promise? = null
|
|
82
77
|
|
|
83
78
|
private var checkoutClientSecretDeferred: CompletableDeferred<String>? = null
|
|
79
|
+
private val rnScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
84
80
|
|
|
85
81
|
@ReactMethod
|
|
86
82
|
override fun initialise(
|
|
@@ -95,6 +91,11 @@ class OnrampSdkModule(
|
|
|
95
91
|
promise.resolve(null)
|
|
96
92
|
}
|
|
97
93
|
|
|
94
|
+
override fun invalidate() {
|
|
95
|
+
super.invalidate()
|
|
96
|
+
rnScope.cancel()
|
|
97
|
+
}
|
|
98
|
+
|
|
98
99
|
/**
|
|
99
100
|
* Safely get and cast the current activity as an AppCompatActivity. If that fails, the promise
|
|
100
101
|
* provided will be resolved with an error message instructing the user to retry the method.
|
|
@@ -124,33 +125,37 @@ class OnrampSdkModule(
|
|
|
124
125
|
return
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
val onrampCallbacks =
|
|
129
|
+
OnrampCallbacks()
|
|
130
|
+
.verifyIdentityCallback { result ->
|
|
131
|
+
handleOnrampIdentityVerificationResult(result, identityVerificationPromise!!)
|
|
132
|
+
}.collectPaymentCallback { result ->
|
|
133
|
+
handleOnrampCollectPaymentResult(result, collectPaymentPromise!!)
|
|
134
|
+
}.authorizeCallback { result ->
|
|
135
|
+
handleOnrampAuthorizationResult(result, authorizePromise!!)
|
|
136
|
+
}.checkoutCallback { result ->
|
|
137
|
+
handleOnrampCheckoutResult(result, checkoutPromise!!)
|
|
138
|
+
}.verifyKycCallback { result ->
|
|
139
|
+
handleOnrampKycVerificationResult(result, verifyKycPromise!!)
|
|
140
|
+
}.onrampSessionClientSecretProvider { sessionId ->
|
|
141
|
+
checkoutClientSecretDeferred = CompletableDeferred()
|
|
142
|
+
|
|
143
|
+
val params = Arguments.createMap()
|
|
144
|
+
params.putString("onrampSessionId", sessionId)
|
|
145
|
+
|
|
146
|
+
emitOnCheckoutClientSecretRequested(params)
|
|
147
|
+
|
|
148
|
+
checkoutClientSecretDeferred!!.await()
|
|
149
|
+
}
|
|
150
|
+
|
|
127
151
|
val coordinator =
|
|
128
152
|
onrampCoordinator ?: OnrampCoordinator
|
|
129
153
|
.Builder()
|
|
130
|
-
.build(application, SavedStateHandle())
|
|
154
|
+
.build(application, SavedStateHandle(), onrampCallbacks)
|
|
131
155
|
.also { this.onrampCoordinator = it }
|
|
132
156
|
|
|
133
157
|
CoroutineScope(Dispatchers.IO).launch {
|
|
134
|
-
val
|
|
135
|
-
val appearance =
|
|
136
|
-
if (appearanceMap != null) {
|
|
137
|
-
mapAppearance(appearanceMap)
|
|
138
|
-
} else {
|
|
139
|
-
LinkAppearance(style = Style.AUTOMATIC)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
val displayName = config.getString("merchantDisplayName") ?: ""
|
|
143
|
-
|
|
144
|
-
val cryptoCustomerId = config.getString("cryptoCustomerId")
|
|
145
|
-
|
|
146
|
-
val configuration =
|
|
147
|
-
OnrampConfiguration(
|
|
148
|
-
merchantDisplayName = displayName,
|
|
149
|
-
publishableKey = publishableKey,
|
|
150
|
-
appearance = appearance,
|
|
151
|
-
cryptoCustomerId = cryptoCustomerId,
|
|
152
|
-
)
|
|
153
|
-
|
|
158
|
+
val configuration = mapConfig(config, publishableKey)
|
|
154
159
|
val configureResult = coordinator.configure(configuration)
|
|
155
160
|
|
|
156
161
|
CoroutineScope(Dispatchers.Main).launch {
|
|
@@ -182,30 +187,8 @@ class OnrampSdkModule(
|
|
|
182
187
|
return
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
val onrampCallbacks =
|
|
186
|
-
OnrampCallbacks(
|
|
187
|
-
authenticateUserCallback = { result ->
|
|
188
|
-
handleOnrampAuthenticationResult(result, authenticateUserPromise!!)
|
|
189
|
-
},
|
|
190
|
-
verifyIdentityCallback = { result ->
|
|
191
|
-
handleOnrampIdentityVerificationResult(result, identityVerificationPromise!!)
|
|
192
|
-
},
|
|
193
|
-
collectPaymentCallback = { result ->
|
|
194
|
-
handleOnrampCollectPaymentResult(result, collectPaymentPromise!!)
|
|
195
|
-
},
|
|
196
|
-
authorizeCallback = { result ->
|
|
197
|
-
handleOnrampAuthorizationResult(result, authorizePromise!!)
|
|
198
|
-
},
|
|
199
|
-
checkoutCallback = { result ->
|
|
200
|
-
handleOnrampCheckoutResult(result, checkoutPromise!!)
|
|
201
|
-
},
|
|
202
|
-
verifyKycCallback = { result ->
|
|
203
|
-
handleOnrampKycVerificationResult(result, verifyKycPromise!!)
|
|
204
|
-
},
|
|
205
|
-
)
|
|
206
|
-
|
|
207
190
|
try {
|
|
208
|
-
onrampPresenter = onrampCoordinator!!.createPresenter(activity
|
|
191
|
+
onrampPresenter = onrampCoordinator!!.createPresenter(activity)
|
|
209
192
|
promise.resolveVoid()
|
|
210
193
|
} catch (e: Exception) {
|
|
211
194
|
promise.resolve(createFailedError(e))
|
|
@@ -394,7 +377,7 @@ class OnrampSdkModule(
|
|
|
394
377
|
}
|
|
395
378
|
CoroutineScope(Dispatchers.IO).launch {
|
|
396
379
|
when (val result = coordinator.updatePhoneNumber(phone)) {
|
|
397
|
-
OnrampUpdatePhoneNumberResult.Completed -> {
|
|
380
|
+
is OnrampUpdatePhoneNumberResult.Completed -> {
|
|
398
381
|
promise.resolveVoid()
|
|
399
382
|
}
|
|
400
383
|
is OnrampUpdatePhoneNumberResult.Failed -> {
|
|
@@ -404,19 +387,6 @@ class OnrampSdkModule(
|
|
|
404
387
|
}
|
|
405
388
|
}
|
|
406
389
|
|
|
407
|
-
@ReactMethod
|
|
408
|
-
override fun authenticateUser(promise: Promise) {
|
|
409
|
-
val presenter =
|
|
410
|
-
onrampPresenter ?: run {
|
|
411
|
-
promise.resolve(createOnrampNotConfiguredError())
|
|
412
|
-
return
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
authenticateUserPromise = promise
|
|
416
|
-
|
|
417
|
-
presenter.authenticateUser()
|
|
418
|
-
}
|
|
419
|
-
|
|
420
390
|
@ReactMethod
|
|
421
391
|
override fun verifyIdentity(promise: Promise) {
|
|
422
392
|
val presenter =
|
|
@@ -505,20 +475,9 @@ class OnrampSdkModule(
|
|
|
505
475
|
return
|
|
506
476
|
}
|
|
507
477
|
|
|
508
|
-
val checkoutHandler: suspend () -> String = {
|
|
509
|
-
checkoutClientSecretDeferred = CompletableDeferred()
|
|
510
|
-
|
|
511
|
-
val params = Arguments.createMap()
|
|
512
|
-
params.putString("onrampSessionId", onrampSessionId)
|
|
513
|
-
|
|
514
|
-
emitOnCheckoutClientSecretRequested(params)
|
|
515
|
-
|
|
516
|
-
checkoutClientSecretDeferred!!.await()
|
|
517
|
-
}
|
|
518
|
-
|
|
519
478
|
checkoutPromise = promise
|
|
520
479
|
|
|
521
|
-
presenter.performCheckout(onrampSessionId
|
|
480
|
+
presenter.performCheckout(onrampSessionId)
|
|
522
481
|
}
|
|
523
482
|
|
|
524
483
|
@ReactMethod
|
|
@@ -579,6 +538,7 @@ class OnrampSdkModule(
|
|
|
579
538
|
null
|
|
580
539
|
}
|
|
581
540
|
}
|
|
541
|
+
|
|
582
542
|
token.hasKey("us_bank_account") -> {
|
|
583
543
|
val bankMap = token.getMap("us_bank_account")
|
|
584
544
|
if (bankMap != null) {
|
|
@@ -597,6 +557,7 @@ class OnrampSdkModule(
|
|
|
597
557
|
null
|
|
598
558
|
}
|
|
599
559
|
}
|
|
560
|
+
|
|
600
561
|
else -> null
|
|
601
562
|
}
|
|
602
563
|
|
|
@@ -608,19 +569,35 @@ class OnrampSdkModule(
|
|
|
608
569
|
)
|
|
609
570
|
return
|
|
610
571
|
}
|
|
572
|
+
rnScope.launch {
|
|
573
|
+
val iconDataUri: String =
|
|
574
|
+
try {
|
|
575
|
+
val base64 =
|
|
576
|
+
withContext(Dispatchers.Default) {
|
|
577
|
+
val drawable =
|
|
578
|
+
withTimeout(5_000L) {
|
|
579
|
+
withContext(Dispatchers.IO) {
|
|
580
|
+
paymentDetails.imageLoader()
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
getBitmapFromDrawable(drawable)?.let { bitmap ->
|
|
585
|
+
getBase64FromBitmap(bitmap)
|
|
586
|
+
} ?: ""
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (base64.isNotEmpty()) "data:image/png;base64,$base64" else ""
|
|
590
|
+
} catch (_: Exception) {
|
|
591
|
+
""
|
|
592
|
+
}
|
|
611
593
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
val displayData = Arguments.createMap()
|
|
618
|
-
|
|
619
|
-
displayData.putString("icon", icon)
|
|
620
|
-
displayData.putString("label", paymentDetails.label)
|
|
621
|
-
displayData.putString("sublabel", paymentDetails.sublabel)
|
|
594
|
+
val displayData = Arguments.createMap()
|
|
595
|
+
displayData.putString("icon", iconDataUri)
|
|
596
|
+
displayData.putString("label", paymentDetails.label)
|
|
597
|
+
displayData.putString("sublabel", paymentDetails.sublabel)
|
|
622
598
|
|
|
623
|
-
|
|
599
|
+
promise.resolve(createResult("displayData", displayData))
|
|
600
|
+
}
|
|
624
601
|
}
|
|
625
602
|
|
|
626
603
|
@ReactMethod
|
|
@@ -659,95 +636,6 @@ class OnrampSdkModule(
|
|
|
659
636
|
}
|
|
660
637
|
}
|
|
661
638
|
|
|
662
|
-
private fun mapAppearance(appearanceMap: ReadableMap): LinkAppearance {
|
|
663
|
-
val lightColorsMap = appearanceMap.getMap("lightColors")
|
|
664
|
-
val darkColorsMap = appearanceMap.getMap("darkColors")
|
|
665
|
-
val styleStr = appearanceMap.getString("style")
|
|
666
|
-
val primaryButtonMap = appearanceMap.getMap("primaryButton")
|
|
667
|
-
|
|
668
|
-
val lightColors =
|
|
669
|
-
if (lightColorsMap != null) {
|
|
670
|
-
val primaryColorStr = lightColorsMap.getString("primary")
|
|
671
|
-
val contentColorStr = lightColorsMap.getString("contentOnPrimary")
|
|
672
|
-
val borderSelectedColorStr = lightColorsMap.getString("borderSelected")
|
|
673
|
-
|
|
674
|
-
Colors(
|
|
675
|
-
primary = Color(android.graphics.Color.parseColor(primaryColorStr)),
|
|
676
|
-
contentOnPrimary = Color(android.graphics.Color.parseColor(contentColorStr)),
|
|
677
|
-
borderSelected = Color(android.graphics.Color.parseColor(borderSelectedColorStr)),
|
|
678
|
-
)
|
|
679
|
-
} else {
|
|
680
|
-
null
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
val darkColors =
|
|
684
|
-
if (darkColorsMap != null) {
|
|
685
|
-
val primaryColorStr = darkColorsMap.getString("primary")
|
|
686
|
-
val contentColorStr = darkColorsMap.getString("contentOnPrimary")
|
|
687
|
-
val borderSelectedColorStr = darkColorsMap.getString("borderSelected")
|
|
688
|
-
|
|
689
|
-
Colors(
|
|
690
|
-
primary = Color(android.graphics.Color.parseColor(primaryColorStr)),
|
|
691
|
-
contentOnPrimary = Color(android.graphics.Color.parseColor(contentColorStr)),
|
|
692
|
-
borderSelected = Color(android.graphics.Color.parseColor(borderSelectedColorStr)),
|
|
693
|
-
)
|
|
694
|
-
} else {
|
|
695
|
-
null
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
val style =
|
|
699
|
-
when (styleStr) {
|
|
700
|
-
"ALWAYS_LIGHT" -> Style.ALWAYS_LIGHT
|
|
701
|
-
"ALWAYS_DARK" -> Style.ALWAYS_DARK
|
|
702
|
-
else -> Style.AUTOMATIC
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
val primaryButton =
|
|
706
|
-
if (primaryButtonMap != null) {
|
|
707
|
-
PrimaryButton(
|
|
708
|
-
cornerRadiusDp =
|
|
709
|
-
if (primaryButtonMap.hasKey("cornerRadius")) {
|
|
710
|
-
primaryButtonMap.getDouble("cornerRadius").toFloat()
|
|
711
|
-
} else {
|
|
712
|
-
null
|
|
713
|
-
},
|
|
714
|
-
heightDp =
|
|
715
|
-
if (primaryButtonMap.hasKey("height")) {
|
|
716
|
-
primaryButtonMap.getDouble("height").toFloat()
|
|
717
|
-
} else {
|
|
718
|
-
null
|
|
719
|
-
},
|
|
720
|
-
)
|
|
721
|
-
} else {
|
|
722
|
-
null
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
val default = LinkAppearance(style = Style.AUTOMATIC)
|
|
726
|
-
return LinkAppearance(
|
|
727
|
-
lightColors = lightColors ?: default.lightColors,
|
|
728
|
-
darkColors = darkColors ?: default.darkColors,
|
|
729
|
-
style = style,
|
|
730
|
-
primaryButton = primaryButton ?: default.primaryButton,
|
|
731
|
-
)
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
private fun handleOnrampAuthenticationResult(
|
|
735
|
-
result: OnrampAuthenticateResult,
|
|
736
|
-
promise: Promise,
|
|
737
|
-
) {
|
|
738
|
-
when (result) {
|
|
739
|
-
is OnrampAuthenticateResult.Completed -> {
|
|
740
|
-
promise.resolveString("customerId", result.customerId)
|
|
741
|
-
}
|
|
742
|
-
is OnrampAuthenticateResult.Cancelled -> {
|
|
743
|
-
promise.resolve(createCanceledError("Authentication was cancelled"))
|
|
744
|
-
}
|
|
745
|
-
is OnrampAuthenticateResult.Failed -> {
|
|
746
|
-
promise.resolve(createFailedError(result.error))
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
|
|
751
639
|
private fun handleOnrampIdentityVerificationResult(
|
|
752
640
|
result: OnrampVerifyIdentityResult,
|
|
753
641
|
promise: Promise,
|
|
@@ -795,19 +683,41 @@ class OnrampSdkModule(
|
|
|
795
683
|
) {
|
|
796
684
|
when (result) {
|
|
797
685
|
is OnrampCollectPaymentMethodResult.Completed -> {
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
686
|
+
rnScope.launch {
|
|
687
|
+
val iconDataUri =
|
|
688
|
+
try {
|
|
689
|
+
val base64 =
|
|
690
|
+
withContext(Dispatchers.Default) {
|
|
691
|
+
val drawable =
|
|
692
|
+
withTimeout(5_000L) {
|
|
693
|
+
withContext(Dispatchers.IO) {
|
|
694
|
+
result.displayData.imageLoader()
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
getBitmapFromDrawable(drawable)?.let { bitmap ->
|
|
699
|
+
getBase64FromBitmap(bitmap)
|
|
700
|
+
} ?: ""
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (base64.isNotEmpty()) "data:image/png;base64,$base64" else ""
|
|
704
|
+
} catch (_: Exception) {
|
|
705
|
+
""
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
val displayData = Arguments.createMap()
|
|
709
|
+
displayData.putString("icon", iconDataUri)
|
|
710
|
+
displayData.putString("label", result.displayData.label)
|
|
711
|
+
result.displayData.sublabel?.let { displayData.putString("sublabel", it) }
|
|
712
|
+
|
|
713
|
+
promise.resolve(createResult("displayData", displayData))
|
|
714
|
+
}
|
|
807
715
|
}
|
|
716
|
+
|
|
808
717
|
is OnrampCollectPaymentMethodResult.Cancelled -> {
|
|
809
718
|
promise.resolve(createCanceledError("Payment collection was cancelled"))
|
|
810
719
|
}
|
|
720
|
+
|
|
811
721
|
is OnrampCollectPaymentMethodResult.Failed -> {
|
|
812
722
|
promise.resolve(createFailedError(result.error))
|
|
813
723
|
}
|