@stripe/stripe-react-native 0.47.1 → 0.49.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/CHANGELOG.md +16 -1
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementView.kt +85 -65
- package/android/src/main/java/com/reactnativestripesdk/EmbeddedPaymentElementViewManager.kt +18 -2
- package/android/src/main/java/com/reactnativestripesdk/PaymentOptionDisplayDataMapper.kt +0 -2
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +83 -3
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +25 -0
- package/ios/PaymentSheetAppearance.swift +46 -1
- package/ios/StripeSdkImpl+PaymentSheet.swift +43 -5
- package/ios/StripeSdkImpl.swift +5 -1
- package/lib/commonjs/components/CustomerSheet.js +1 -1
- package/lib/commonjs/components/CustomerSheet.js.map +1 -1
- package/lib/commonjs/events.js.map +1 -1
- package/lib/commonjs/functions.js +1 -1
- package/lib/commonjs/functions.js.map +1 -1
- package/lib/commonjs/hooks/useStripe.js +1 -1
- package/lib/commonjs/hooks/useStripe.js.map +1 -1
- package/lib/commonjs/types/EmbeddedPaymentElement.js +1 -1
- package/lib/commonjs/types/EmbeddedPaymentElement.js.map +1 -1
- package/lib/commonjs/types/PaymentSheet.js +1 -1
- package/lib/commonjs/types/PaymentSheet.js.map +1 -1
- package/lib/module/components/CustomerSheet.js +1 -1
- package/lib/module/components/CustomerSheet.js.map +1 -1
- package/lib/module/events.js.map +1 -1
- package/lib/module/functions.js +1 -1
- package/lib/module/functions.js.map +1 -1
- package/lib/module/hooks/useStripe.js +1 -1
- package/lib/module/hooks/useStripe.js.map +1 -1
- package/lib/module/types/EmbeddedPaymentElement.js +1 -1
- package/lib/module/types/EmbeddedPaymentElement.js.map +1 -1
- package/lib/module/types/PaymentSheet.js +1 -1
- package/lib/module/types/PaymentSheet.js.map +1 -1
- package/lib/typescript/src/events.d.ts +1 -1
- package/lib/typescript/src/events.d.ts.map +1 -1
- package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts +27 -0
- package/lib/typescript/src/types/EmbeddedPaymentElement.d.ts.map +1 -1
- package/lib/typescript/src/types/PaymentIntent.d.ts +1 -1
- package/lib/typescript/src/types/PaymentIntent.d.ts.map +1 -1
- package/lib/typescript/src/types/PaymentSheet.d.ts +30 -2
- package/lib/typescript/src/types/PaymentSheet.d.ts.map +1 -1
- package/package-lock.json +14114 -0
- package/package.json +1 -1
- package/src/events.ts +1 -0
- package/src/types/EmbeddedPaymentElement.tsx +47 -2
- package/src/types/PaymentIntent.ts +1 -1
- package/src/types/PaymentSheet.ts +35 -1
- package/stripe-react-native.podspec +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
## 0.49.0 - 2025-07-02
|
|
4
|
+
|
|
5
|
+
**Features**
|
|
6
|
+
- Added rowSelectionBehavior to `EmbeddedPaymentElementConfiguration` with `immediateAction` option
|
|
7
|
+
- Added `flatWithChevron` to `AppearanceParams.embeddedPaymentElement.rowConfig.style`
|
|
8
|
+
- Added `PaymentMethodOptions` to `PaymentMode` to enable setting payment method level setup future usage value
|
|
9
|
+
- Added `None` to `FutureUsage`
|
|
10
|
+
|
|
11
|
+
## 0.48.0 - 2025-06-11
|
|
12
|
+
|
|
13
|
+
**Feature**
|
|
14
|
+
- Added `height` to `PrimaryButtonConfig.shapes`.
|
|
15
|
+
- Added `formInsetValues` to `AppearanceParams`.
|
|
16
|
+
|
|
17
|
+
## 0.47.1 - 2025-05-29
|
|
3
18
|
|
|
4
19
|
**Fixes**
|
|
5
20
|
- Fixed EmbeddedPaymentElement unable to present view controllers after navigating back and forth between screens.
|
|
@@ -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=21.
|
|
6
|
+
StripeSdk_stripeVersion=21.19.+
|
|
@@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable
|
|
|
7
7
|
import androidx.compose.runtime.LaunchedEffect
|
|
8
8
|
import androidx.compose.runtime.getValue
|
|
9
9
|
import androidx.compose.runtime.mutableIntStateOf
|
|
10
|
+
import androidx.compose.runtime.mutableStateOf
|
|
10
11
|
import androidx.compose.runtime.remember
|
|
11
12
|
import androidx.compose.runtime.setValue
|
|
12
13
|
import androidx.compose.ui.Modifier
|
|
@@ -20,7 +21,6 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
20
21
|
import com.reactnativestripesdk.utils.KeepJsAwakeTask
|
|
21
22
|
import com.reactnativestripesdk.utils.mapFromPaymentMethod
|
|
22
23
|
import com.stripe.android.paymentelement.EmbeddedPaymentElement
|
|
23
|
-
import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
|
|
24
24
|
import com.stripe.android.paymentelement.rememberEmbeddedPaymentElement
|
|
25
25
|
import com.stripe.android.paymentsheet.CreateIntentResult
|
|
26
26
|
import com.stripe.android.paymentsheet.PaymentSheet
|
|
@@ -29,7 +29,11 @@ import kotlinx.coroutines.channels.Channel
|
|
|
29
29
|
import kotlinx.coroutines.flow.consumeAsFlow
|
|
30
30
|
import toWritableMap
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
enum class RowSelectionBehaviorType {
|
|
33
|
+
Default,
|
|
34
|
+
ImmediateAction,
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
class EmbeddedPaymentElementView(
|
|
34
38
|
context: Context,
|
|
35
39
|
) : StripeAbstractComposeView(context) {
|
|
@@ -47,75 +51,91 @@ class EmbeddedPaymentElementView(
|
|
|
47
51
|
var latestIntentConfig: PaymentSheet.IntentConfiguration? = null
|
|
48
52
|
var latestElementConfig: EmbeddedPaymentElement.Configuration? = null
|
|
49
53
|
|
|
54
|
+
val rowSelectionBehaviorType = mutableStateOf<RowSelectionBehaviorType?>(null)
|
|
55
|
+
|
|
50
56
|
private val reactContext get() = context as ThemedReactContext
|
|
51
57
|
private val events = Channel<Event>(Channel.UNLIMITED)
|
|
52
58
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
is EmbeddedPaymentElement.Result.Completed -> {
|
|
101
|
-
putString("status", "completed")
|
|
102
|
-
}
|
|
103
|
-
is EmbeddedPaymentElement.Result.Canceled -> {
|
|
104
|
-
putString("status", "canceled")
|
|
59
|
+
@Composable
|
|
60
|
+
override fun Content() {
|
|
61
|
+
val type by remember { rowSelectionBehaviorType }
|
|
62
|
+
val builder =
|
|
63
|
+
remember(type) {
|
|
64
|
+
EmbeddedPaymentElement
|
|
65
|
+
.Builder(
|
|
66
|
+
createIntentCallback = { paymentMethod, shouldSavePaymentMethod ->
|
|
67
|
+
val stripeSdkModule =
|
|
68
|
+
try {
|
|
69
|
+
requireStripeSdkModule()
|
|
70
|
+
} catch (ex: IllegalArgumentException) {
|
|
71
|
+
return@Builder CreateIntentResult.Failure(
|
|
72
|
+
cause =
|
|
73
|
+
Exception(
|
|
74
|
+
"Tried to call confirmHandler, but no callback was found. Please file an issue: https://github.com/stripe/stripe-react-native/issues",
|
|
75
|
+
),
|
|
76
|
+
displayMessage = "An unexpected error occurred",
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Make sure that JS is active since the activity will be paused when stripe ui is presented.
|
|
81
|
+
val keepJsAwakeTask =
|
|
82
|
+
KeepJsAwakeTask(reactContext.reactApplicationContext).apply { start() }
|
|
83
|
+
|
|
84
|
+
val params =
|
|
85
|
+
Arguments.createMap().apply {
|
|
86
|
+
putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
87
|
+
putBoolean("shouldSavePaymentMethod", shouldSavePaymentMethod)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
stripeSdkModule.emitOnConfirmHandlerCallback(params)
|
|
91
|
+
|
|
92
|
+
val resultFromJavascript = stripeSdkModule.embeddedIntentCreationCallback.await()
|
|
93
|
+
// reset the completable
|
|
94
|
+
stripeSdkModule.embeddedIntentCreationCallback = CompletableDeferred()
|
|
95
|
+
|
|
96
|
+
keepJsAwakeTask.stop()
|
|
97
|
+
|
|
98
|
+
resultFromJavascript.getString("clientSecret")?.let {
|
|
99
|
+
CreateIntentResult.Success(clientSecret = it)
|
|
100
|
+
} ?: run {
|
|
101
|
+
val errorMap = resultFromJavascript.getMap("error")
|
|
102
|
+
CreateIntentResult.Failure(
|
|
103
|
+
cause = Exception(errorMap?.getString("message")),
|
|
104
|
+
displayMessage = errorMap?.getString("localizedMessage"),
|
|
105
|
+
)
|
|
105
106
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
},
|
|
108
|
+
resultCallback = { result ->
|
|
109
|
+
val map =
|
|
110
|
+
Arguments.createMap().apply {
|
|
111
|
+
when (result) {
|
|
112
|
+
is EmbeddedPaymentElement.Result.Completed -> {
|
|
113
|
+
putString("status", "completed")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
is EmbeddedPaymentElement.Result.Canceled -> {
|
|
117
|
+
putString("status", "canceled")
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
is EmbeddedPaymentElement.Result.Failed -> {
|
|
121
|
+
putString("status", "failed")
|
|
122
|
+
putString("error", result.error.message ?: "Unknown error")
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
requireStripeSdkModule().emitEmbeddedPaymentElementFormSheetConfirmComplete(map)
|
|
127
|
+
},
|
|
128
|
+
).rowSelectionBehavior(
|
|
129
|
+
if (type == RowSelectionBehaviorType.Default) {
|
|
130
|
+
EmbeddedPaymentElement.RowSelectionBehavior.default()
|
|
131
|
+
} else {
|
|
132
|
+
EmbeddedPaymentElement.RowSelectionBehavior.immediateAction {
|
|
133
|
+
requireStripeSdkModule().emitEmbeddedPaymentElementRowSelectionImmediateAction()
|
|
109
134
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
)
|
|
115
|
-
}
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
}
|
|
116
138
|
|
|
117
|
-
@Composable
|
|
118
|
-
override fun Content() {
|
|
119
139
|
val embedded = rememberEmbeddedPaymentElement(builder)
|
|
120
140
|
var height by remember {
|
|
121
141
|
mutableIntStateOf(0)
|
|
@@ -21,10 +21,8 @@ import com.reactnativestripesdk.utils.mapToPreferredNetworks
|
|
|
21
21
|
import com.reactnativestripesdk.utils.toBundleObject
|
|
22
22
|
import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
|
|
23
23
|
import com.stripe.android.paymentelement.EmbeddedPaymentElement
|
|
24
|
-
import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
|
|
25
24
|
import com.stripe.android.paymentsheet.PaymentSheet
|
|
26
25
|
|
|
27
|
-
@OptIn(ExperimentalEmbeddedPaymentElementApi::class)
|
|
28
26
|
@ReactModule(name = EmbeddedPaymentElementViewManager.NAME)
|
|
29
27
|
class EmbeddedPaymentElementViewManager :
|
|
30
28
|
ViewGroupManager<EmbeddedPaymentElementView>(),
|
|
@@ -54,6 +52,9 @@ class EmbeddedPaymentElementViewManager :
|
|
|
54
52
|
view: EmbeddedPaymentElementView,
|
|
55
53
|
cfg: Dynamic,
|
|
56
54
|
) {
|
|
55
|
+
val rowSelectionBehaviorType = parseRowSelectionBehavior(cfg.asMap())
|
|
56
|
+
view.rowSelectionBehaviorType.value = rowSelectionBehaviorType
|
|
57
|
+
|
|
57
58
|
val elementConfig = parseElementConfiguration(cfg.asMap(), view.context)
|
|
58
59
|
view.latestElementConfig = elementConfig
|
|
59
60
|
// if intentConfig is already set, configure immediately:
|
|
@@ -190,6 +191,21 @@ class EmbeddedPaymentElementViewManager :
|
|
|
190
191
|
return configurationBuilder.build()
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
private fun parseRowSelectionBehavior(map: ReadableMap): RowSelectionBehaviorType {
|
|
195
|
+
val rowSelectionBehavior =
|
|
196
|
+
map
|
|
197
|
+
.getMap("rowSelectionBehavior")
|
|
198
|
+
?.getString("type")
|
|
199
|
+
?.let { type ->
|
|
200
|
+
when (type) {
|
|
201
|
+
"immediateAction" -> RowSelectionBehaviorType.ImmediateAction
|
|
202
|
+
else -> RowSelectionBehaviorType.Default
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
?: RowSelectionBehaviorType.Default
|
|
206
|
+
return rowSelectionBehavior
|
|
207
|
+
}
|
|
208
|
+
|
|
193
209
|
private fun parseIntentConfiguration(map: ReadableMap): PaymentSheet.IntentConfiguration {
|
|
194
210
|
val intentConfig = PaymentSheetFragment.buildIntentConfiguration(toBundleObject(map))
|
|
195
211
|
return intentConfig ?: throw IllegalArgumentException("IntentConfiguration is null")
|
|
@@ -2,13 +2,11 @@ import com.facebook.react.bridge.Arguments
|
|
|
2
2
|
import com.facebook.react.bridge.WritableMap
|
|
3
3
|
import com.reactnativestripesdk.utils.mapFromPaymentSheetBillingDetails
|
|
4
4
|
import com.stripe.android.paymentelement.EmbeddedPaymentElement
|
|
5
|
-
import com.stripe.android.paymentelement.ExperimentalEmbeddedPaymentElementApi
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Serialize Stripe's PaymentOptionDisplayData into a WritableMap
|
|
9
8
|
* that can be sent over the RN bridge.
|
|
10
9
|
*/
|
|
11
|
-
@OptIn(ExperimentalEmbeddedPaymentElementApi::class)
|
|
12
10
|
fun EmbeddedPaymentElement.PaymentOptionDisplayData.toWritableMap(): WritableMap =
|
|
13
11
|
Arguments.createMap().apply {
|
|
14
12
|
putString("label", label)
|
|
@@ -6,8 +6,9 @@ import android.content.res.Configuration
|
|
|
6
6
|
import android.graphics.Color
|
|
7
7
|
import android.os.Bundle
|
|
8
8
|
import com.reactnativestripesdk.utils.PaymentSheetAppearanceException
|
|
9
|
-
import com.stripe.android.paymentelement.
|
|
9
|
+
import com.stripe.android.paymentelement.AppearanceAPIAdditionsPreview
|
|
10
10
|
import com.stripe.android.paymentsheet.PaymentSheet
|
|
11
|
+
import com.stripe.android.uicore.StripeThemeDefaults
|
|
11
12
|
|
|
12
13
|
@SuppressLint("RestrictedApi")
|
|
13
14
|
fun buildPaymentSheetAppearance(
|
|
@@ -17,6 +18,7 @@ fun buildPaymentSheetAppearance(
|
|
|
17
18
|
val colorParams = userParams?.getBundle(PaymentSheetAppearanceKeys.COLORS)
|
|
18
19
|
val lightColorParams = colorParams?.getBundle(PaymentSheetAppearanceKeys.LIGHT) ?: colorParams
|
|
19
20
|
val darkColorParams = colorParams?.getBundle(PaymentSheetAppearanceKeys.DARK) ?: colorParams
|
|
21
|
+
val insetParams = userParams?.getBundle(PaymentSheetAppearanceKeys.FORM_INSETS)
|
|
20
22
|
|
|
21
23
|
val embeddedAppearance =
|
|
22
24
|
buildEmbeddedAppearance(
|
|
@@ -37,6 +39,7 @@ fun buildPaymentSheetAppearance(
|
|
|
37
39
|
context,
|
|
38
40
|
),
|
|
39
41
|
embeddedAppearance = embeddedAppearance,
|
|
42
|
+
formInsetValues = buildFormInsets(insetParams),
|
|
40
43
|
)
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -50,9 +53,11 @@ fun buildPaymentSheetAppearance(
|
|
|
50
53
|
userParams?.getBundle(PaymentSheetAppearanceKeys.PRIMARY_BUTTON),
|
|
51
54
|
context,
|
|
52
55
|
),
|
|
56
|
+
formInsetValues = buildFormInsets(insetParams),
|
|
53
57
|
)
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
@OptIn(AppearanceAPIAdditionsPreview::class)
|
|
56
61
|
private fun buildTypography(
|
|
57
62
|
fontParams: Bundle?,
|
|
58
63
|
context: Context,
|
|
@@ -198,6 +203,7 @@ private fun buildPrimaryButton(
|
|
|
198
203
|
getFloatOrNull(shapeParams, PaymentSheetAppearanceKeys.BORDER_RADIUS),
|
|
199
204
|
borderStrokeWidthDp =
|
|
200
205
|
getFloatOrNull(shapeParams, PaymentSheetAppearanceKeys.BORDER_WIDTH),
|
|
206
|
+
heightDp = getFloatOrNull(shapeParams, PaymentSheetAppearanceKeys.HEIGHT),
|
|
201
207
|
),
|
|
202
208
|
typography =
|
|
203
209
|
PaymentSheet.PrimaryButtonTypography(
|
|
@@ -239,7 +245,6 @@ private fun buildPrimaryButtonColors(
|
|
|
239
245
|
),
|
|
240
246
|
)
|
|
241
247
|
|
|
242
|
-
@OptIn(ExperimentalEmbeddedPaymentElementApi::class)
|
|
243
248
|
@SuppressLint("RestrictedApi")
|
|
244
249
|
@Throws(PaymentSheetAppearanceException::class)
|
|
245
250
|
private fun buildEmbeddedAppearance(
|
|
@@ -336,7 +341,7 @@ private fun buildEmbeddedAppearance(
|
|
|
336
341
|
val checkmarkParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHECKMARK)
|
|
337
342
|
val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
|
|
338
343
|
|
|
339
|
-
// Default separator insets specific to FlatWithCheckmark
|
|
344
|
+
// Default separator insets specific to FlatWithCheckmark and FlatWithChevron
|
|
340
345
|
val defaultSeparatorStartInsetDp = 0.0f
|
|
341
346
|
val defaultSeparatorEndInsetDp = 0.0f
|
|
342
347
|
|
|
@@ -387,6 +392,59 @@ private fun buildEmbeddedAppearance(
|
|
|
387
392
|
colorsDark = flatCheckmarkColors,
|
|
388
393
|
)
|
|
389
394
|
}
|
|
395
|
+
"flatWithChevron" -> {
|
|
396
|
+
val flatParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLAT)
|
|
397
|
+
val chevronParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.CHEVRON)
|
|
398
|
+
val separatorInsetsParams = getBundleOrNull(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_INSETS)
|
|
399
|
+
|
|
400
|
+
// Default separator insets specific to FlatWithCheckmark and FlatWithChevron
|
|
401
|
+
val defaultSeparatorStartInsetDp = 0.0f
|
|
402
|
+
val defaultSeparatorEndInsetDp = 0.0f
|
|
403
|
+
|
|
404
|
+
// Parse dimensions as Floats
|
|
405
|
+
val separatorThickness = getFloatOr(flatParams, PaymentSheetAppearanceKeys.SEPARATOR_THICKNESS, defaultSeparatorThicknessDp)
|
|
406
|
+
val startSeparatorInset = getFloatOr(separatorInsetsParams, PaymentSheetAppearanceKeys.LEFT, defaultSeparatorStartInsetDp)
|
|
407
|
+
val endSeparatorInset = getFloatOr(separatorInsetsParams, PaymentSheetAppearanceKeys.RIGHT, defaultSeparatorEndInsetDp)
|
|
408
|
+
|
|
409
|
+
// Parse booleans
|
|
410
|
+
val topEnabled = getBooleanOr(flatParams, PaymentSheetAppearanceKeys.TOP_SEPARATOR_ENABLED, true)
|
|
411
|
+
val bottomEnabled = getBooleanOr(flatParams, PaymentSheetAppearanceKeys.BOTTOM_SEPARATOR_ENABLED, true)
|
|
412
|
+
|
|
413
|
+
val parsedSeparatorColor =
|
|
414
|
+
dynamicColorFromParams(
|
|
415
|
+
context,
|
|
416
|
+
flatParams,
|
|
417
|
+
PaymentSheetAppearanceKeys.SEPARATOR_COLOR,
|
|
418
|
+
Color.GRAY,
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
val parsedChevronColor =
|
|
422
|
+
dynamicColorFromParams(
|
|
423
|
+
context,
|
|
424
|
+
chevronParams,
|
|
425
|
+
PaymentSheetAppearanceKeys.COLOR,
|
|
426
|
+
defaultColors.componentBorder, // Default to component border color like other elements
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
// Create the required Colors object
|
|
430
|
+
val flatChevronColors =
|
|
431
|
+
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron.Colors(
|
|
432
|
+
separatorColor = parsedSeparatorColor,
|
|
433
|
+
chevronColor = parsedChevronColor,
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
PaymentSheet.Appearance.Embedded.RowStyle.FlatWithChevron(
|
|
437
|
+
separatorThicknessDp = separatorThickness,
|
|
438
|
+
startSeparatorInsetDp = startSeparatorInset,
|
|
439
|
+
endSeparatorInsetDp = endSeparatorInset,
|
|
440
|
+
topSeparatorEnabled = topEnabled,
|
|
441
|
+
bottomSeparatorEnabled = bottomEnabled,
|
|
442
|
+
additionalVerticalInsetsDp = additionalInsets,
|
|
443
|
+
horizontalInsetsDp = 0.0F, // We do not have an iOS equal for this API so it's not configurable in React Native
|
|
444
|
+
colorsLight = flatChevronColors,
|
|
445
|
+
colorsDark = flatChevronColors,
|
|
446
|
+
)
|
|
447
|
+
}
|
|
390
448
|
"floatingButton" -> {
|
|
391
449
|
val floatingParams = getBundleOrNull(rowParams, PaymentSheetAppearanceKeys.FLOATING)
|
|
392
450
|
PaymentSheet.Appearance.Embedded.RowStyle.FloatingButton(
|
|
@@ -403,6 +461,22 @@ private fun buildEmbeddedAppearance(
|
|
|
403
461
|
return PaymentSheet.Appearance.Embedded(style = rowStyle)
|
|
404
462
|
}
|
|
405
463
|
|
|
464
|
+
@SuppressLint("RestrictedApi")
|
|
465
|
+
private fun buildFormInsets(insetParams: Bundle?): PaymentSheet.Insets {
|
|
466
|
+
val defaults = StripeThemeDefaults.formInsets
|
|
467
|
+
val left = getFloatOr(insetParams, PaymentSheetAppearanceKeys.LEFT, defaults.start)
|
|
468
|
+
val top = getFloatOr(insetParams, PaymentSheetAppearanceKeys.TOP, defaults.top)
|
|
469
|
+
val right = getFloatOr(insetParams, PaymentSheetAppearanceKeys.RIGHT, defaults.end)
|
|
470
|
+
val bottom = getFloatOr(insetParams, PaymentSheetAppearanceKeys.BOTTOM, defaults.bottom)
|
|
471
|
+
|
|
472
|
+
return PaymentSheet.Insets(
|
|
473
|
+
startDp = left,
|
|
474
|
+
topDp = top,
|
|
475
|
+
endDp = right,
|
|
476
|
+
bottomDp = bottom,
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
|
|
406
480
|
/**
|
|
407
481
|
* Pulls a light/dark hex‑string map out of [params],
|
|
408
482
|
* chooses the right one based on the current UI mode,
|
|
@@ -564,6 +638,7 @@ private class PaymentSheetAppearanceKeys {
|
|
|
564
638
|
const val SHAPES = "shapes"
|
|
565
639
|
const val BORDER_RADIUS = "borderRadius"
|
|
566
640
|
const val BORDER_WIDTH = "borderWidth"
|
|
641
|
+
const val HEIGHT = "height"
|
|
567
642
|
|
|
568
643
|
const val PRIMARY_BUTTON = "primaryButton"
|
|
569
644
|
const val TEXT = "text"
|
|
@@ -584,6 +659,7 @@ private class PaymentSheetAppearanceKeys {
|
|
|
584
659
|
const val SELECTED_COLOR = "selectedColor"
|
|
585
660
|
const val UNSELECTED_COLOR = "unselectedColor"
|
|
586
661
|
const val CHECKMARK = "checkmark"
|
|
662
|
+
const val CHEVRON = "chevron"
|
|
587
663
|
const val COLOR = "color"
|
|
588
664
|
const val CHECKMARK_INSET = "inset"
|
|
589
665
|
|
|
@@ -593,5 +669,9 @@ private class PaymentSheetAppearanceKeys {
|
|
|
593
669
|
// Keys for EdgeInsetsConfig
|
|
594
670
|
const val LEFT = "left"
|
|
595
671
|
const val RIGHT = "right"
|
|
672
|
+
const val TOP = "top"
|
|
673
|
+
const val BOTTOM = "bottom"
|
|
674
|
+
|
|
675
|
+
const val FORM_INSETS = "formInsetValues"
|
|
596
676
|
}
|
|
597
677
|
}
|
|
@@ -32,6 +32,8 @@ import com.reactnativestripesdk.utils.mapFromPaymentMethod
|
|
|
32
32
|
import com.reactnativestripesdk.utils.mapToPreferredNetworks
|
|
33
33
|
import com.reactnativestripesdk.utils.removeFragment
|
|
34
34
|
import com.stripe.android.ExperimentalAllowsRemovalOfLastSavedPaymentMethodApi
|
|
35
|
+
import com.stripe.android.model.PaymentMethod
|
|
36
|
+
import com.stripe.android.paymentelement.PaymentMethodOptionsSetupFutureUsagePreview
|
|
35
37
|
import com.stripe.android.paymentsheet.CreateIntentCallback
|
|
36
38
|
import com.stripe.android.paymentsheet.CreateIntentResult
|
|
37
39
|
import com.stripe.android.paymentsheet.ExperimentalCustomerSessionApi
|
|
@@ -518,6 +520,7 @@ class PaymentSheetFragment : StripeFragment() {
|
|
|
518
520
|
)
|
|
519
521
|
}
|
|
520
522
|
|
|
523
|
+
@OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class)
|
|
521
524
|
private fun buildIntentConfigurationMode(modeParams: Bundle): PaymentSheet.IntentConfiguration.Mode {
|
|
522
525
|
val currencyCode =
|
|
523
526
|
modeParams.getString("currencyCode")
|
|
@@ -531,6 +534,7 @@ class PaymentSheetFragment : StripeFragment() {
|
|
|
531
534
|
currency = currencyCode,
|
|
532
535
|
setupFutureUse = mapToSetupFutureUse(modeParams.getString("setupFutureUsage")),
|
|
533
536
|
captureMethod = mapToCaptureMethod(modeParams.getString("captureMethod")),
|
|
537
|
+
paymentMethodOptions = mapToPaymentMethodOptions(modeParams.getBundle("paymentMethodOptions")),
|
|
534
538
|
)
|
|
535
539
|
} else {
|
|
536
540
|
val setupFutureUsage =
|
|
@@ -639,6 +643,7 @@ fun mapToSetupFutureUse(type: String?): PaymentSheet.IntentConfiguration.SetupFu
|
|
|
639
643
|
when (type) {
|
|
640
644
|
"OffSession" -> PaymentSheet.IntentConfiguration.SetupFutureUse.OffSession
|
|
641
645
|
"OnSession" -> PaymentSheet.IntentConfiguration.SetupFutureUse.OnSession
|
|
646
|
+
"None" -> PaymentSheet.IntentConfiguration.SetupFutureUse.None
|
|
642
647
|
else -> null
|
|
643
648
|
}
|
|
644
649
|
|
|
@@ -650,6 +655,26 @@ fun mapToCaptureMethod(type: String?): PaymentSheet.IntentConfiguration.CaptureM
|
|
|
650
655
|
else -> PaymentSheet.IntentConfiguration.CaptureMethod.Automatic
|
|
651
656
|
}
|
|
652
657
|
|
|
658
|
+
@OptIn(PaymentMethodOptionsSetupFutureUsagePreview::class)
|
|
659
|
+
fun mapToPaymentMethodOptions(options: Bundle?): PaymentSheet.IntentConfiguration.Mode.Payment.PaymentMethodOptions? {
|
|
660
|
+
val sfuBundle = options?.getBundle("setupFutureUsageValues")
|
|
661
|
+
val paymentMethodToSfuMap = mutableMapOf<PaymentMethod.Type, PaymentSheet.IntentConfiguration.SetupFutureUse>()
|
|
662
|
+
sfuBundle?.keySet()?.forEach { code ->
|
|
663
|
+
val sfuValue = mapToSetupFutureUse(sfuBundle?.getString(code))
|
|
664
|
+
val paymentMethodType = PaymentMethod.Type.fromCode(code)
|
|
665
|
+
if (paymentMethodType != null && sfuValue != null) {
|
|
666
|
+
paymentMethodToSfuMap[paymentMethodType] = sfuValue
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return if (paymentMethodToSfuMap.isNotEmpty()) {
|
|
670
|
+
PaymentSheet.IntentConfiguration.Mode.Payment.PaymentMethodOptions(
|
|
671
|
+
setupFutureUsageValues = paymentMethodToSfuMap,
|
|
672
|
+
)
|
|
673
|
+
} else {
|
|
674
|
+
null
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
653
678
|
fun mapToCardBrandAcceptance(params: Bundle?): PaymentSheet.CardBrandAcceptance {
|
|
654
679
|
val cardBrandAcceptanceParams = params?.getBundle("cardBrandAcceptance") ?: return PaymentSheet.CardBrandAcceptance.all()
|
|
655
680
|
val filter = cardBrandAcceptanceParams.getString("filter") ?: return PaymentSheet.CardBrandAcceptance.all()
|
|
@@ -33,6 +33,10 @@ internal class PaymentSheetAppearance {
|
|
|
33
33
|
appearance.embeddedPaymentElement = try buildEmbeddedPaymentElementAppearance(params: embeddedPaymentElementParams)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
if let formInsetParams = userParams[PaymentSheetAppearanceKeys.FORM_INSETS] as? NSDictionary {
|
|
37
|
+
appearance.formInsets = try buildFormInsets(params: formInsetParams)
|
|
38
|
+
}
|
|
39
|
+
|
|
36
40
|
return appearance
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -114,6 +118,9 @@ internal class PaymentSheetAppearance {
|
|
|
114
118
|
if let shadowParams = shapeParams[PaymentSheetAppearanceKeys.SHADOW] as? NSDictionary {
|
|
115
119
|
primaryButton.shadow = try buildShadow(params: shadowParams)
|
|
116
120
|
}
|
|
121
|
+
if let height = shapeParams[PaymentSheetAppearanceKeys.HEIGHT] as? CGFloat {
|
|
122
|
+
primaryButton.height = height
|
|
123
|
+
}
|
|
117
124
|
}
|
|
118
125
|
if let colorParams = params[PaymentSheetAppearanceKeys.COLORS] as? NSDictionary {
|
|
119
126
|
if (colorParams.object(forKey: PaymentSheetAppearanceKeys.LIGHT) != nil && colorParams.object(forKey: PaymentSheetAppearanceKeys.DARK) == nil ||
|
|
@@ -178,6 +185,8 @@ internal class PaymentSheetAppearance {
|
|
|
178
185
|
row.style = .floatingButton
|
|
179
186
|
case PaymentSheetAppearanceKeys.ROW_STYLE_FLAT_WITH_CHECKMARK:
|
|
180
187
|
row.style = .flatWithCheckmark
|
|
188
|
+
case PaymentSheetAppearanceKeys.ROW_STYLE_FLAT_WITH_CHEVRON:
|
|
189
|
+
row.style = .flatWithChevron
|
|
181
190
|
default:
|
|
182
191
|
throw PaymentSheetAppearanceError.invalidRowStyle(styleString)
|
|
183
192
|
}
|
|
@@ -232,6 +241,10 @@ internal class PaymentSheetAppearance {
|
|
|
232
241
|
flat.checkmark = try buildEmbeddedCheckmark(params: checkmarkParams)
|
|
233
242
|
}
|
|
234
243
|
|
|
244
|
+
if let chevronParams = params[PaymentSheetAppearanceKeys.CHEVRON] as? NSDictionary {
|
|
245
|
+
flat.chevron = try buildEmbeddedChevron(params: chevronParams)
|
|
246
|
+
}
|
|
247
|
+
|
|
235
248
|
return flat
|
|
236
249
|
}
|
|
237
250
|
|
|
@@ -270,6 +283,19 @@ internal class PaymentSheetAppearance {
|
|
|
270
283
|
return checkmark
|
|
271
284
|
}
|
|
272
285
|
|
|
286
|
+
private class func buildEmbeddedChevron(params: NSDictionary) throws -> PaymentSheet.Appearance.EmbeddedPaymentElement.Row.Flat.Chevron {
|
|
287
|
+
var chevron = PaymentSheet.Appearance.default.embeddedPaymentElement.row.flat.chevron
|
|
288
|
+
|
|
289
|
+
if let colorHexes = params[PaymentSheetAppearanceKeys.COLOR] as? [String: String] {
|
|
290
|
+
chevron.color = dynamicColor(
|
|
291
|
+
from: colorHexes,
|
|
292
|
+
default: UIColor.systemGray // Default iOS system gray color
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return chevron
|
|
297
|
+
}
|
|
298
|
+
|
|
273
299
|
private class func buildEmbeddedFloating(params: NSDictionary) throws -> PaymentSheet.Appearance.EmbeddedPaymentElement.Row.Floating {
|
|
274
300
|
var floating = PaymentSheet.Appearance.default.embeddedPaymentElement.row.floating
|
|
275
301
|
|
|
@@ -314,6 +340,20 @@ internal class PaymentSheetAppearance {
|
|
|
314
340
|
return defaultColor
|
|
315
341
|
})
|
|
316
342
|
}
|
|
343
|
+
|
|
344
|
+
private class func buildFormInsets(params: NSDictionary) throws -> NSDirectionalEdgeInsets {
|
|
345
|
+
let top = params[PaymentSheetAppearanceKeys.TOP] as? CGFloat ?? PaymentSheet.Appearance.default.formInsets.top
|
|
346
|
+
let leading = params[PaymentSheetAppearanceKeys.LEFT] as? CGFloat ?? PaymentSheet.Appearance.default.formInsets.leading
|
|
347
|
+
let bottom = params[PaymentSheetAppearanceKeys.BOTTOM] as? CGFloat ?? PaymentSheet.Appearance.default.formInsets.bottom
|
|
348
|
+
let trailing = params[PaymentSheetAppearanceKeys.RIGHT] as? CGFloat ?? PaymentSheet.Appearance.default.formInsets.trailing
|
|
349
|
+
|
|
350
|
+
return NSDirectionalEdgeInsets(
|
|
351
|
+
top: top,
|
|
352
|
+
leading: leading,
|
|
353
|
+
bottom: bottom,
|
|
354
|
+
trailing: trailing
|
|
355
|
+
)
|
|
356
|
+
}
|
|
317
357
|
}
|
|
318
358
|
|
|
319
359
|
enum PaymentSheetAppearanceError : Error {
|
|
@@ -333,7 +373,7 @@ extension PaymentSheetAppearanceError: LocalizedError {
|
|
|
333
373
|
case .unexpectedHexStringLength(let hexString):
|
|
334
374
|
return NSLocalizedString("Failed to set Payment Sheet appearance. Expected hex string of length 6 or 8, but received: \(hexString)", comment: "Failed to set color")
|
|
335
375
|
case .invalidRowStyle(let styleString):
|
|
336
|
-
return NSLocalizedString("Failed to set Embedded Payment Element appearance. Invalid row style '\(styleString)'. Expected one of: 'flatWithRadio', 'floatingButton', 'flatWithCheckmark'.", comment: "Invalid row style string")
|
|
376
|
+
return NSLocalizedString("Failed to set Embedded Payment Element appearance. Invalid row style '\(styleString)'. Expected one of: 'flatWithRadio', 'floatingButton', 'flatWithCheckmark', 'flatWithChevron'.", comment: "Invalid row style string")
|
|
337
377
|
}
|
|
338
378
|
}
|
|
339
379
|
}
|
|
@@ -361,6 +401,7 @@ private struct PaymentSheetAppearanceKeys {
|
|
|
361
401
|
static let SHAPES = "shapes"
|
|
362
402
|
static let BORDER_RADIUS = "borderRadius"
|
|
363
403
|
static let BORDER_WIDTH = "borderWidth"
|
|
404
|
+
static let HEIGHT = "height"
|
|
364
405
|
|
|
365
406
|
static let SHADOW = "shadow"
|
|
366
407
|
static let SHADOW_COLOR = "color"
|
|
@@ -389,6 +430,7 @@ private struct PaymentSheetAppearanceKeys {
|
|
|
389
430
|
static let SELECTED_COLOR = "selectedColor"
|
|
390
431
|
static let UNSELECTED_COLOR = "unselectedColor"
|
|
391
432
|
static let CHECKMARK = "checkmark"
|
|
433
|
+
static let CHEVRON = "chevron"
|
|
392
434
|
static let SPACING = "spacing"
|
|
393
435
|
static let TOP = "top"
|
|
394
436
|
static let LEFT = "left"
|
|
@@ -400,4 +442,7 @@ private struct PaymentSheetAppearanceKeys {
|
|
|
400
442
|
static let ROW_STYLE_FLAT_WITH_RADIO = "flatWithRadio"
|
|
401
443
|
static let ROW_STYLE_FLOATING_BUTTON = "floatingButton"
|
|
402
444
|
static let ROW_STYLE_FLAT_WITH_CHECKMARK = "flatWithCheckmark"
|
|
445
|
+
static let ROW_STYLE_FLAT_WITH_CHEVRON = "flatWithChevron"
|
|
446
|
+
|
|
447
|
+
static let FORM_INSETS = "formInsetValues"
|
|
403
448
|
}
|