@stripe/stripe-react-native 0.61.0 → 0.63.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/gradle.properties +2 -2
- package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +4 -0
- package/android/src/main/java/com/reactnativestripesdk/FakeOnrampSdkModule.kt +6 -0
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +200 -198
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +3 -1
- package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt +17 -16
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +8 -11
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +4 -0
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +16 -1
- package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +3 -0
- package/ios/Mappers.swift +15 -2
- package/ios/StripeOnrampSdk.h +3 -4
- package/lib/commonjs/components/AddToWalletButton.js +1 -1
- package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
- package/lib/commonjs/components/AddressSheet.js +1 -1
- package/lib/commonjs/components/AddressSheet.js.map +1 -1
- package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
- package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
- package/lib/commonjs/components/CardField.js +1 -1
- package/lib/commonjs/components/CardField.js.map +1 -1
- package/lib/commonjs/components/CardForm.js +1 -1
- package/lib/commonjs/components/CardForm.js.map +1 -1
- package/lib/commonjs/components/PlatformPayButton.js +1 -1
- package/lib/commonjs/components/PlatformPayButton.js.map +1 -1
- package/lib/commonjs/components/StripeContainer.js +1 -1
- package/lib/commonjs/components/StripeContainer.js.map +1 -1
- package/lib/commonjs/connect/Components.js +1 -1
- package/lib/commonjs/connect/Components.js.map +1 -1
- package/lib/commonjs/connect/ConnectComponentsProvider.js +1 -1
- package/lib/commonjs/connect/ConnectComponentsProvider.js.map +1 -1
- package/lib/commonjs/connect/EmbeddedComponent.js +1 -1
- package/lib/commonjs/connect/EmbeddedComponent.js.map +1 -1
- package/lib/commonjs/connect/ModalCloseButton.js +1 -1
- package/lib/commonjs/connect/ModalCloseButton.js.map +1 -1
- package/lib/commonjs/connect/NavigationBar.js +1 -1
- package/lib/commonjs/connect/NavigationBar.js.map +1 -1
- package/lib/commonjs/events.js +1 -1
- package/lib/commonjs/events.js.map +1 -1
- package/lib/commonjs/helpers.js +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/NativeCardField.js.map +1 -1
- package/lib/commonjs/specs/NativeCardForm.js +1 -1
- package/lib/commonjs/specs/NativeCardForm.js.map +1 -1
- package/lib/commonjs/specs/NativeConnectAccountOnboardingView.js +1 -1
- package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js +1 -1
- package/lib/commonjs/specs/NativeEmbeddedPaymentElement.js.map +1 -1
- package/lib/commonjs/specs/NativeGooglePayButton.js +1 -1
- package/lib/commonjs/specs/NativeNavigationBar.js +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/EmbeddedPaymentElement.js.map +1 -1
- package/lib/module/components/AddToWalletButton.js +1 -1
- package/lib/module/components/AddToWalletButton.js.map +1 -1
- package/lib/module/components/AddressSheet.js +1 -1
- package/lib/module/components/AddressSheet.js.map +1 -1
- package/lib/module/components/AuBECSDebitForm.js +1 -1
- package/lib/module/components/AuBECSDebitForm.js.map +1 -1
- package/lib/module/components/CardField.js +1 -1
- package/lib/module/components/CardField.js.map +1 -1
- package/lib/module/components/CardForm.js +1 -1
- package/lib/module/components/CardForm.js.map +1 -1
- package/lib/module/components/PlatformPayButton.js +1 -1
- package/lib/module/components/PlatformPayButton.js.map +1 -1
- package/lib/module/components/StripeContainer.js +1 -1
- package/lib/module/components/StripeContainer.js.map +1 -1
- package/lib/module/connect/Components.js +1 -1
- package/lib/module/connect/Components.js.map +1 -1
- package/lib/module/connect/ConnectComponentsProvider.js +1 -1
- package/lib/module/connect/ConnectComponentsProvider.js.map +1 -1
- package/lib/module/connect/EmbeddedComponent.js +1 -1
- package/lib/module/connect/EmbeddedComponent.js.map +1 -1
- package/lib/module/connect/ModalCloseButton.js +1 -1
- package/lib/module/connect/ModalCloseButton.js.map +1 -1
- package/lib/module/connect/NavigationBar.js +1 -1
- package/lib/module/connect/NavigationBar.js.map +1 -1
- package/lib/module/events.js +1 -1
- package/lib/module/events.js.map +1 -1
- package/lib/module/helpers.js +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/NativeCardField.js.map +1 -1
- package/lib/module/specs/NativeCardForm.js +1 -1
- package/lib/module/specs/NativeCardForm.js.map +1 -1
- package/lib/module/specs/NativeConnectAccountOnboardingView.js +1 -1
- package/lib/module/specs/NativeEmbeddedPaymentElement.js +1 -1
- package/lib/module/specs/NativeEmbeddedPaymentElement.js.map +1 -1
- package/lib/module/specs/NativeGooglePayButton.js +1 -1
- package/lib/module/specs/NativeNavigationBar.js +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/EmbeddedPaymentElement.js.map +1 -1
- package/lib/typescript/src/connect/connectTypes.d.ts +76 -0
- package/lib/typescript/src/connect/connectTypes.d.ts.map +1 -1
- package/lib/typescript/src/events.d.ts +5 -3
- package/lib/typescript/src/events.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +2 -2
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/connect/connectTypes.ts +88 -0
- package/src/events.ts +10 -13
- package/src/specs/NativeOnrampSdkModule.ts +2 -2
- package/stripe-react-native.podspec +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
StripeSdk_kotlinVersion=2.
|
|
1
|
+
StripeSdk_kotlinVersion=2.2.21
|
|
2
2
|
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=23.
|
|
6
|
+
StripeSdk_stripeVersion=23.3.+
|
|
@@ -99,4 +99,8 @@ class EventEmitterCompat(
|
|
|
99
99
|
fun emitPaymentMethodMessagingElementConfigureResult(value: ReadableMap?) {
|
|
100
100
|
invoke("paymentMethodMessagingElementConfigureResult", value)
|
|
101
101
|
}
|
|
102
|
+
|
|
103
|
+
fun emitOnCheckoutClientSecretRequested(value: ReadableMap?) {
|
|
104
|
+
invoke("onCheckoutClientSecretRequested", value)
|
|
105
|
+
}
|
|
102
106
|
}
|
|
@@ -137,6 +137,12 @@ class FakeOnrampSdkModule(
|
|
|
137
137
|
promise.resolveNotImplemented()
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
@ReactMethod
|
|
141
|
+
override fun addListener(eventType: String?) {}
|
|
142
|
+
|
|
143
|
+
@ReactMethod
|
|
144
|
+
override fun removeListeners(count: Double) {}
|
|
145
|
+
|
|
140
146
|
private fun Promise.resolveNotImplemented() {
|
|
141
147
|
this.resolve(
|
|
142
148
|
createFailedError(
|
|
@@ -86,209 +86,15 @@ class PaymentSheetManager(
|
|
|
86
86
|
internal var paymentSheetIntentCreationCallback = CompletableDeferred<ReadableMap>()
|
|
87
87
|
internal var paymentSheetConfirmationTokenCreationCallback = CompletableDeferred<ReadableMap>()
|
|
88
88
|
private var keepJsAwake: KeepJsAwakeTask? = null
|
|
89
|
+
private var lastConfigureWasCustomFlow: Boolean? = null
|
|
89
90
|
|
|
90
91
|
@SuppressLint("RestrictedApi")
|
|
91
92
|
override fun onCreate() {
|
|
92
|
-
val activity = getCurrentActivityOrResolveWithError(initPromise) ?: return
|
|
93
|
-
val merchantDisplayName = arguments.getString("merchantDisplayName").orEmpty()
|
|
94
|
-
if (merchantDisplayName.isEmpty()) {
|
|
95
|
-
initPromise.resolve(
|
|
96
|
-
createError(ErrorType.Failed.toString(), "merchantDisplayName cannot be empty or null."),
|
|
97
|
-
)
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
paymentIntentClientSecret = arguments.getString("paymentIntentClientSecret").orEmpty()
|
|
101
|
-
setupIntentClientSecret = arguments.getString("setupIntentClientSecret").orEmpty()
|
|
102
|
-
intentConfiguration =
|
|
103
|
-
try {
|
|
104
|
-
buildIntentConfiguration(arguments.getMap("intentConfiguration"))
|
|
105
|
-
} catch (error: PaymentSheetException) {
|
|
106
|
-
initPromise.resolve(createError(ErrorType.Failed.toString(), error))
|
|
107
|
-
return
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Determine which callback type to use based on what's provided
|
|
111
|
-
val intentConfigMap = arguments.getMap("intentConfiguration")
|
|
112
|
-
val useConfirmationTokenCallback = intentConfigMap?.hasKey("confirmationTokenConfirmHandler") == true
|
|
113
|
-
|
|
114
|
-
val paymentOptionCallback =
|
|
115
|
-
PaymentOptionResultCallback { paymentOptionResult ->
|
|
116
|
-
paymentOptionResult.paymentOption?.let { paymentOption ->
|
|
117
|
-
// Convert drawable to bitmap asynchronously to avoid shared state issues
|
|
118
|
-
CoroutineScope(Dispatchers.Default).launch {
|
|
119
|
-
val imageString =
|
|
120
|
-
try {
|
|
121
|
-
convertDrawableToBase64(paymentOption.icon())
|
|
122
|
-
} catch (e: Exception) {
|
|
123
|
-
val result =
|
|
124
|
-
createError(
|
|
125
|
-
PaymentSheetErrorType.Failed.toString(),
|
|
126
|
-
"Failed to process payment option image: ${e.message}",
|
|
127
|
-
)
|
|
128
|
-
resolvePresentPromise(result)
|
|
129
|
-
return@launch
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
val option: WritableMap = Arguments.createMap()
|
|
133
|
-
option.putString("label", paymentOption.label)
|
|
134
|
-
option.putString("image", imageString)
|
|
135
|
-
val additionalFields: Map<String, Any> = mapOf("didCancel" to paymentOptionResult.didCancel)
|
|
136
|
-
val result = createResult("paymentOption", option, additionalFields)
|
|
137
|
-
resolvePresentPromise(result)
|
|
138
|
-
}
|
|
139
|
-
} ?: run {
|
|
140
|
-
val result =
|
|
141
|
-
if (paymentSheetTimedOut) {
|
|
142
|
-
paymentSheetTimedOut = false
|
|
143
|
-
createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out")
|
|
144
|
-
} else {
|
|
145
|
-
createError(
|
|
146
|
-
PaymentSheetErrorType.Canceled.toString(),
|
|
147
|
-
"The payment option selection flow has been canceled",
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
resolvePresentPromise(result)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
val paymentResultCallback =
|
|
155
|
-
PaymentSheetResultCallback { paymentResult ->
|
|
156
|
-
if (paymentSheetTimedOut) {
|
|
157
|
-
paymentSheetTimedOut = false
|
|
158
|
-
resolvePaymentResult(
|
|
159
|
-
createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out"),
|
|
160
|
-
)
|
|
161
|
-
} else {
|
|
162
|
-
when (paymentResult) {
|
|
163
|
-
is PaymentSheetResult.Canceled -> {
|
|
164
|
-
resolvePaymentResult(
|
|
165
|
-
createError(
|
|
166
|
-
PaymentSheetErrorType.Canceled.toString(),
|
|
167
|
-
"The payment flow has been canceled",
|
|
168
|
-
),
|
|
169
|
-
)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
is PaymentSheetResult.Failed -> {
|
|
173
|
-
resolvePaymentResult(
|
|
174
|
-
createError(PaymentSheetErrorType.Failed.toString(), paymentResult.error),
|
|
175
|
-
)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
is PaymentSheetResult.Completed -> {
|
|
179
|
-
resolvePaymentResult(Arguments.createMap())
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
val createIntentCallback =
|
|
186
|
-
CreateIntentCallback { paymentMethod, shouldSavePaymentMethod ->
|
|
187
|
-
val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
|
|
188
|
-
val params =
|
|
189
|
-
Arguments.createMap().apply {
|
|
190
|
-
putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
191
|
-
putBoolean("shouldSavePaymentMethod", shouldSavePaymentMethod)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
stripeSdkModule?.eventEmitter?.emitOnConfirmHandlerCallback(params)
|
|
195
|
-
|
|
196
|
-
val resultFromJavascript = paymentSheetIntentCreationCallback.await()
|
|
197
|
-
// reset the completable
|
|
198
|
-
paymentSheetIntentCreationCallback = CompletableDeferred<ReadableMap>()
|
|
199
|
-
|
|
200
|
-
return@CreateIntentCallback resultFromJavascript.getString("clientSecret")?.let {
|
|
201
|
-
CreateIntentResult.Success(clientSecret = it)
|
|
202
|
-
}
|
|
203
|
-
?: run {
|
|
204
|
-
val errorMap = resultFromJavascript.getMap("error")
|
|
205
|
-
CreateIntentResult.Failure(
|
|
206
|
-
cause = Exception(errorMap?.getString("message")),
|
|
207
|
-
displayMessage = errorMap?.getString("localizedMessage"),
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
val createConfirmationTokenCallback =
|
|
213
|
-
CreateIntentWithConfirmationTokenCallback { confirmationToken ->
|
|
214
|
-
val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
|
|
215
|
-
val params =
|
|
216
|
-
Arguments.createMap().apply {
|
|
217
|
-
putMap("confirmationToken", mapFromConfirmationToken(confirmationToken))
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
stripeSdkModule?.eventEmitter?.emitOnConfirmationTokenHandlerCallback(params)
|
|
221
|
-
|
|
222
|
-
val resultFromJavascript = paymentSheetConfirmationTokenCreationCallback.await()
|
|
223
|
-
// reset the completable
|
|
224
|
-
paymentSheetConfirmationTokenCreationCallback = CompletableDeferred<ReadableMap>()
|
|
225
|
-
|
|
226
|
-
return@CreateIntentWithConfirmationTokenCallback resultFromJavascript.getString("clientSecret")?.let {
|
|
227
|
-
CreateIntentResult.Success(clientSecret = it)
|
|
228
|
-
}
|
|
229
|
-
?: run {
|
|
230
|
-
val errorMap = resultFromJavascript.getMap("error")
|
|
231
|
-
CreateIntentResult.Failure(
|
|
232
|
-
cause = Exception(errorMap?.getString("message")),
|
|
233
|
-
displayMessage = errorMap?.getString("localizedMessage"),
|
|
234
|
-
)
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (arguments.getBooleanOr("customFlow", false)) {
|
|
239
|
-
if (flowController == null) {
|
|
240
|
-
flowController =
|
|
241
|
-
if (intentConfiguration != null) {
|
|
242
|
-
val builder =
|
|
243
|
-
PaymentSheet.FlowController
|
|
244
|
-
.Builder(
|
|
245
|
-
resultCallback = paymentResultCallback,
|
|
246
|
-
paymentOptionResultCallback = paymentOptionCallback,
|
|
247
|
-
)
|
|
248
|
-
if (useConfirmationTokenCallback) {
|
|
249
|
-
builder.createIntentCallback(createConfirmationTokenCallback)
|
|
250
|
-
} else {
|
|
251
|
-
builder.createIntentCallback(createIntentCallback)
|
|
252
|
-
}
|
|
253
|
-
builder
|
|
254
|
-
.confirmCustomPaymentMethodCallback(this)
|
|
255
|
-
.build(activity)
|
|
256
|
-
} else {
|
|
257
|
-
PaymentSheet.FlowController
|
|
258
|
-
.Builder(
|
|
259
|
-
resultCallback = paymentResultCallback,
|
|
260
|
-
paymentOptionResultCallback = paymentOptionCallback,
|
|
261
|
-
).confirmCustomPaymentMethodCallback(this)
|
|
262
|
-
.build(activity)
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
} else {
|
|
266
|
-
if (paymentSheet == null) {
|
|
267
|
-
paymentSheet =
|
|
268
|
-
if (intentConfiguration != null) {
|
|
269
|
-
val builder = PaymentSheet.Builder(paymentResultCallback)
|
|
270
|
-
if (useConfirmationTokenCallback) {
|
|
271
|
-
builder.createIntentCallback(createConfirmationTokenCallback)
|
|
272
|
-
} else {
|
|
273
|
-
builder.createIntentCallback(createIntentCallback)
|
|
274
|
-
}
|
|
275
|
-
@SuppressLint("RestrictedApi")
|
|
276
|
-
builder
|
|
277
|
-
.confirmCustomPaymentMethodCallback(this)
|
|
278
|
-
.build(activity, signal)
|
|
279
|
-
} else {
|
|
280
|
-
@SuppressLint("RestrictedApi")
|
|
281
|
-
PaymentSheet
|
|
282
|
-
.Builder(paymentResultCallback)
|
|
283
|
-
.confirmCustomPaymentMethodCallback(this)
|
|
284
|
-
.build(activity, signal)
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
93
|
configure(arguments, initPromise)
|
|
289
94
|
}
|
|
290
95
|
|
|
291
96
|
override fun onDestroy() {
|
|
97
|
+
super.onDestroy()
|
|
292
98
|
flowController = null
|
|
293
99
|
paymentSheet = null
|
|
294
100
|
}
|
|
@@ -380,15 +186,211 @@ class PaymentSheetManager(
|
|
|
380
186
|
|
|
381
187
|
paymentSheetConfiguration = configurationBuilder.build()
|
|
382
188
|
if (args.getBooleanOr("customFlow", false)) {
|
|
189
|
+
lastConfigureWasCustomFlow = true
|
|
190
|
+
if (flowController == null) {
|
|
191
|
+
initFlowController(args, promise)
|
|
192
|
+
}
|
|
383
193
|
configureFlowController(promise)
|
|
384
194
|
} else {
|
|
195
|
+
lastConfigureWasCustomFlow = false
|
|
196
|
+
if (paymentSheet == null) {
|
|
197
|
+
initPaymentSheet(args, promise)
|
|
198
|
+
}
|
|
385
199
|
promise.resolve(Arguments.createMap())
|
|
386
200
|
}
|
|
387
201
|
}
|
|
388
202
|
|
|
203
|
+
private fun initPaymentSheet(
|
|
204
|
+
args: ReadableMap,
|
|
205
|
+
promise: Promise,
|
|
206
|
+
) {
|
|
207
|
+
val activity = getCurrentActivityOrResolveWithError(promise) ?: return
|
|
208
|
+
val intentConfigMap = args.getMap("intentConfiguration")
|
|
209
|
+
val useConfirmationTokenCallback = intentConfigMap?.hasKey("confirmationTokenConfirmHandler") == true
|
|
210
|
+
paymentSheet =
|
|
211
|
+
if (intentConfiguration != null) {
|
|
212
|
+
val builder = PaymentSheet.Builder(buildPaymentSheetResultCallback())
|
|
213
|
+
if (useConfirmationTokenCallback) {
|
|
214
|
+
builder.createIntentCallback(buildCreateConfirmationTokenCallback())
|
|
215
|
+
} else {
|
|
216
|
+
builder.createIntentCallback(buildIntentCreationCallback())
|
|
217
|
+
}
|
|
218
|
+
@SuppressLint("RestrictedApi")
|
|
219
|
+
builder
|
|
220
|
+
.confirmCustomPaymentMethodCallback(this)
|
|
221
|
+
.build(activity, signal)
|
|
222
|
+
} else {
|
|
223
|
+
@SuppressLint("RestrictedApi")
|
|
224
|
+
PaymentSheet
|
|
225
|
+
.Builder(buildPaymentSheetResultCallback())
|
|
226
|
+
.confirmCustomPaymentMethodCallback(this)
|
|
227
|
+
.build(activity, signal)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private fun initFlowController(
|
|
232
|
+
args: ReadableMap,
|
|
233
|
+
promise: Promise,
|
|
234
|
+
) {
|
|
235
|
+
val activity = getCurrentActivityOrResolveWithError(promise) ?: return
|
|
236
|
+
val intentConfigMap = args.getMap("intentConfiguration")
|
|
237
|
+
val useConfirmationTokenCallback =
|
|
238
|
+
intentConfigMap?.hasKey("confirmationTokenConfirmHandler") == true
|
|
239
|
+
flowController =
|
|
240
|
+
if (intentConfiguration != null) {
|
|
241
|
+
val builder =
|
|
242
|
+
PaymentSheet.FlowController
|
|
243
|
+
.Builder(
|
|
244
|
+
resultCallback = buildPaymentSheetResultCallback(),
|
|
245
|
+
paymentOptionResultCallback = buildPaymentOptionCallback(),
|
|
246
|
+
)
|
|
247
|
+
if (useConfirmationTokenCallback) {
|
|
248
|
+
builder.createIntentCallback(buildCreateConfirmationTokenCallback())
|
|
249
|
+
} else {
|
|
250
|
+
builder.createIntentCallback(buildIntentCreationCallback())
|
|
251
|
+
}
|
|
252
|
+
builder.confirmCustomPaymentMethodCallback(this)
|
|
253
|
+
builder.build(activity)
|
|
254
|
+
} else {
|
|
255
|
+
PaymentSheet.FlowController
|
|
256
|
+
.Builder(
|
|
257
|
+
resultCallback = buildPaymentSheetResultCallback(),
|
|
258
|
+
paymentOptionResultCallback = buildPaymentOptionCallback(),
|
|
259
|
+
).confirmCustomPaymentMethodCallback(this)
|
|
260
|
+
.build(activity)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private fun buildCreateConfirmationTokenCallback(): CreateIntentWithConfirmationTokenCallback {
|
|
265
|
+
return CreateIntentWithConfirmationTokenCallback { confirmationToken ->
|
|
266
|
+
val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
|
|
267
|
+
val params =
|
|
268
|
+
Arguments.createMap().apply {
|
|
269
|
+
putMap("confirmationToken", mapFromConfirmationToken(confirmationToken))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
stripeSdkModule?.eventEmitter?.emitOnConfirmationTokenHandlerCallback(params)
|
|
273
|
+
|
|
274
|
+
val resultFromJavascript = paymentSheetConfirmationTokenCreationCallback.await()
|
|
275
|
+
// reset the completable
|
|
276
|
+
paymentSheetConfirmationTokenCreationCallback = CompletableDeferred<ReadableMap>()
|
|
277
|
+
|
|
278
|
+
return@CreateIntentWithConfirmationTokenCallback resultFromJavascript.getString("clientSecret")?.let {
|
|
279
|
+
CreateIntentResult.Success(clientSecret = it)
|
|
280
|
+
}
|
|
281
|
+
?: run {
|
|
282
|
+
val errorMap = resultFromJavascript.getMap("error")
|
|
283
|
+
CreateIntentResult.Failure(
|
|
284
|
+
cause = Exception(errorMap?.getString("message")),
|
|
285
|
+
displayMessage = errorMap?.getString("localizedMessage"),
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private fun buildIntentCreationCallback(): CreateIntentCallback {
|
|
292
|
+
return CreateIntentCallback { paymentMethod, shouldSavePaymentMethod ->
|
|
293
|
+
val stripeSdkModule: StripeSdkModule? = context.getNativeModule(StripeSdkModule::class.java)
|
|
294
|
+
val params =
|
|
295
|
+
Arguments.createMap().apply {
|
|
296
|
+
putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
297
|
+
putBoolean("shouldSavePaymentMethod", shouldSavePaymentMethod)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
stripeSdkModule?.eventEmitter?.emitOnConfirmHandlerCallback(params)
|
|
301
|
+
|
|
302
|
+
val resultFromJavascript = paymentSheetIntentCreationCallback.await()
|
|
303
|
+
// reset the completable
|
|
304
|
+
paymentSheetIntentCreationCallback = CompletableDeferred<ReadableMap>()
|
|
305
|
+
|
|
306
|
+
return@CreateIntentCallback resultFromJavascript.getString("clientSecret")?.let {
|
|
307
|
+
CreateIntentResult.Success(clientSecret = it)
|
|
308
|
+
}
|
|
309
|
+
?: run {
|
|
310
|
+
val errorMap = resultFromJavascript.getMap("error")
|
|
311
|
+
CreateIntentResult.Failure(
|
|
312
|
+
cause = Exception(errorMap?.getString("message")),
|
|
313
|
+
displayMessage = errorMap?.getString("localizedMessage"),
|
|
314
|
+
)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
private fun buildPaymentSheetResultCallback(): PaymentSheetResultCallback =
|
|
320
|
+
PaymentSheetResultCallback { paymentResult ->
|
|
321
|
+
if (paymentSheetTimedOut) {
|
|
322
|
+
paymentSheetTimedOut = false
|
|
323
|
+
resolvePaymentResult(
|
|
324
|
+
createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out"),
|
|
325
|
+
)
|
|
326
|
+
} else {
|
|
327
|
+
when (paymentResult) {
|
|
328
|
+
is PaymentSheetResult.Canceled -> {
|
|
329
|
+
resolvePaymentResult(
|
|
330
|
+
createError(
|
|
331
|
+
PaymentSheetErrorType.Canceled.toString(),
|
|
332
|
+
"The payment flow has been canceled",
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
is PaymentSheetResult.Failed -> {
|
|
338
|
+
resolvePaymentResult(
|
|
339
|
+
createError(PaymentSheetErrorType.Failed.toString(), paymentResult.error),
|
|
340
|
+
)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
is PaymentSheetResult.Completed -> {
|
|
344
|
+
resolvePaymentResult(Arguments.createMap())
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private fun buildPaymentOptionCallback(): PaymentOptionResultCallback {
|
|
351
|
+
return PaymentOptionResultCallback { paymentOptionResult ->
|
|
352
|
+
paymentOptionResult.paymentOption?.let { paymentOption ->
|
|
353
|
+
// Convert drawable to bitmap asynchronously to avoid shared state issues
|
|
354
|
+
CoroutineScope(Dispatchers.Default).launch {
|
|
355
|
+
val imageString =
|
|
356
|
+
try {
|
|
357
|
+
convertDrawableToBase64(paymentOption.icon())
|
|
358
|
+
} catch (e: Exception) {
|
|
359
|
+
val result =
|
|
360
|
+
createError(
|
|
361
|
+
PaymentSheetErrorType.Failed.toString(),
|
|
362
|
+
"Failed to process payment option image: ${e.message}",
|
|
363
|
+
)
|
|
364
|
+
resolvePresentPromise(result)
|
|
365
|
+
return@launch
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
val option: WritableMap = Arguments.createMap()
|
|
369
|
+
option.putString("label", paymentOption.label)
|
|
370
|
+
option.putString("image", imageString)
|
|
371
|
+
val additionalFields: Map<String, Any> = mapOf("didCancel" to paymentOptionResult.didCancel)
|
|
372
|
+
val result = createResult("paymentOption", option, additionalFields)
|
|
373
|
+
resolvePresentPromise(result)
|
|
374
|
+
}
|
|
375
|
+
} ?: run {
|
|
376
|
+
val result =
|
|
377
|
+
if (paymentSheetTimedOut) {
|
|
378
|
+
paymentSheetTimedOut = false
|
|
379
|
+
createError(PaymentSheetErrorType.Timeout.toString(), "The payment has timed out")
|
|
380
|
+
} else {
|
|
381
|
+
createError(
|
|
382
|
+
PaymentSheetErrorType.Canceled.toString(),
|
|
383
|
+
"The payment option selection flow has been canceled",
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
resolvePresentPromise(result)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
389
391
|
override fun onPresent() {
|
|
390
392
|
keepJsAwake = KeepJsAwakeTask(context).apply { start() }
|
|
391
|
-
if (
|
|
393
|
+
if (lastConfigureWasCustomFlow == false) {
|
|
392
394
|
if (!paymentIntentClientSecret.isNullOrEmpty()) {
|
|
393
395
|
paymentSheet?.presentWithPaymentIntent(
|
|
394
396
|
paymentIntentClientSecret!!,
|
|
@@ -402,7 +404,7 @@ class PaymentSheetManager(
|
|
|
402
404
|
configuration = paymentSheetConfiguration,
|
|
403
405
|
)
|
|
404
406
|
}
|
|
405
|
-
} else if (flowController != null) {
|
|
407
|
+
} else if (lastConfigureWasCustomFlow == true && flowController != null) {
|
|
406
408
|
flowController?.presentPaymentOptions()
|
|
407
409
|
} else {
|
|
408
410
|
promise?.resolve(createMissingInitError())
|
|
@@ -258,7 +258,9 @@ class StripeSdkModule(
|
|
|
258
258
|
promise: Promise,
|
|
259
259
|
) {
|
|
260
260
|
if (paymentSheetManager != null) {
|
|
261
|
-
|
|
261
|
+
UiThreadUtil.runOnUiThread {
|
|
262
|
+
paymentSheetManager?.configure(params, promise)
|
|
263
|
+
}
|
|
262
264
|
} else {
|
|
263
265
|
paymentSheetManager =
|
|
264
266
|
PaymentSheetManager(reactApplicationContext, params, promise).also {
|
package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt
CHANGED
|
@@ -2,6 +2,7 @@ package com.reactnativestripesdk.pushprovisioning
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.res.ColorStateList
|
|
5
|
+
import android.graphics.Bitmap
|
|
5
6
|
import android.graphics.drawable.Drawable
|
|
6
7
|
import android.graphics.drawable.RippleDrawable
|
|
7
8
|
import android.view.MotionEvent
|
|
@@ -12,10 +13,9 @@ import androidx.core.graphics.toColorInt
|
|
|
12
13
|
import androidx.core.net.toUri
|
|
13
14
|
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
|
14
15
|
import com.facebook.common.references.CloseableReference
|
|
15
|
-
import com.facebook.datasource.BaseDataSubscriber
|
|
16
16
|
import com.facebook.datasource.DataSource
|
|
17
17
|
import com.facebook.drawee.backends.pipeline.Fresco
|
|
18
|
-
import com.facebook.imagepipeline.
|
|
18
|
+
import com.facebook.imagepipeline.datasource.BaseBitmapReferenceDataSubscriber
|
|
19
19
|
import com.facebook.imagepipeline.image.CloseableImage
|
|
20
20
|
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
|
21
21
|
import com.facebook.react.bridge.ReadableMap
|
|
@@ -36,6 +36,7 @@ class AddToWalletButtonView(
|
|
|
36
36
|
|
|
37
37
|
private var loadedSource: String? = null
|
|
38
38
|
private var currentDataSource: DataSource<CloseableReference<CloseableImage>>? = null
|
|
39
|
+
private var currentBitmapReference: CloseableReference<Bitmap>? = null
|
|
39
40
|
|
|
40
41
|
init {
|
|
41
42
|
scaleType = ScaleType.CENTER_CROP
|
|
@@ -118,20 +119,14 @@ class AddToWalletButtonView(
|
|
|
118
119
|
currentDataSource = dataSource
|
|
119
120
|
|
|
120
121
|
dataSource.subscribe(
|
|
121
|
-
object :
|
|
122
|
-
override fun onNewResultImpl(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
val drawable = image.underlyingBitmap.toDrawable(resources)
|
|
130
|
-
setImageWithRipple(drawable)
|
|
131
|
-
}
|
|
132
|
-
} finally {
|
|
133
|
-
CloseableReference.closeSafely(imageRef)
|
|
134
|
-
}
|
|
122
|
+
object : BaseBitmapReferenceDataSubscriber() {
|
|
123
|
+
override fun onNewResultImpl(bitmapReference: CloseableReference<Bitmap>?) {
|
|
124
|
+
val image = bitmapReference?.get() ?: return
|
|
125
|
+
|
|
126
|
+
currentBitmapReference = bitmapReference.cloneOrNull()
|
|
127
|
+
|
|
128
|
+
val drawable = image.toDrawable(resources)
|
|
129
|
+
setImageWithRipple(drawable)
|
|
135
130
|
}
|
|
136
131
|
|
|
137
132
|
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
|
|
@@ -165,6 +160,12 @@ class AddToWalletButtonView(
|
|
|
165
160
|
|
|
166
161
|
private fun cancelCurrentRequest() {
|
|
167
162
|
currentDataSource?.close()
|
|
163
|
+
|
|
164
|
+
currentBitmapReference?.let {
|
|
165
|
+
CloseableReference.closeSafely(it)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
currentBitmapReference = null
|
|
168
169
|
currentDataSource = null
|
|
169
170
|
}
|
|
170
171
|
|
|
@@ -18,7 +18,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
|
|
18
18
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
19
19
|
import com.facebook.react.bridge.ReactMethod;
|
|
20
20
|
import com.facebook.react.bridge.ReadableMap;
|
|
21
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
22
21
|
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
|
23
22
|
import javax.annotation.Nonnull;
|
|
24
23
|
|
|
@@ -34,16 +33,6 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
34
33
|
return NAME;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
private void invoke(String eventName, Object params) {
|
|
38
|
-
getReactApplicationContext()
|
|
39
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
40
|
-
.emit(eventName, params);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
protected final void emitOnCheckoutClientSecretRequested(ReadableMap value) {
|
|
44
|
-
invoke("onCheckoutClientSecretRequested", value);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
36
|
@ReactMethod
|
|
48
37
|
@DoNotStrip
|
|
49
38
|
public abstract void initialise(ReadableMap params, Promise promise);
|
|
@@ -111,4 +100,12 @@ public abstract class NativeOnrampSdkModuleSpec extends ReactContextBaseJavaModu
|
|
|
111
100
|
@ReactMethod
|
|
112
101
|
@DoNotStrip
|
|
113
102
|
public abstract void logout(Promise promise);
|
|
103
|
+
|
|
104
|
+
@ReactMethod
|
|
105
|
+
@DoNotStrip
|
|
106
|
+
public abstract void addListener(String eventType);
|
|
107
|
+
|
|
108
|
+
@ReactMethod
|
|
109
|
+
@DoNotStrip
|
|
110
|
+
public abstract void removeListeners(double count);
|
|
114
111
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalCryptoOnramp::class)
|
|
2
|
+
|
|
1
3
|
package com.reactnativestripesdk
|
|
2
4
|
|
|
3
5
|
import android.annotation.SuppressLint
|
|
4
6
|
import androidx.compose.ui.graphics.Color
|
|
5
7
|
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
6
9
|
import com.stripe.android.crypto.onramp.model.OnrampConfiguration
|
|
7
10
|
import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
|
|
8
11
|
import com.stripe.android.googlepaylauncher.GooglePayEnvironment
|
|
@@ -148,6 +151,7 @@ internal fun mapAppearance(appearanceMap: ReadableMap): LinkAppearance {
|
|
|
148
151
|
.primaryButton(primaryButton)
|
|
149
152
|
}
|
|
150
153
|
|
|
154
|
+
@OptIn(ExperimentalCryptoOnramp::class)
|
|
151
155
|
@SuppressLint("RestrictedApi")
|
|
152
156
|
internal fun mapPaymentDetailsType(type: PaymentMethodDisplayData.Type): String =
|
|
153
157
|
when (type) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalCryptoOnramp::class)
|
|
2
|
+
|
|
1
3
|
package com.reactnativestripesdk
|
|
2
4
|
|
|
3
5
|
import android.annotation.SuppressLint
|
|
@@ -23,6 +25,7 @@ import com.reactnativestripesdk.utils.createOnrampNotConfiguredError
|
|
|
23
25
|
import com.reactnativestripesdk.utils.createResult
|
|
24
26
|
import com.reactnativestripesdk.utils.getValOr
|
|
25
27
|
import com.reactnativestripesdk.utils.mapToPaymentSheetAddress
|
|
28
|
+
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
26
29
|
import com.stripe.android.crypto.onramp.OnrampCoordinator
|
|
27
30
|
import com.stripe.android.crypto.onramp.model.CryptoNetwork
|
|
28
31
|
import com.stripe.android.crypto.onramp.model.KycInfo
|
|
@@ -57,10 +60,12 @@ import kotlinx.coroutines.withContext
|
|
|
57
60
|
import kotlinx.coroutines.withTimeout
|
|
58
61
|
|
|
59
62
|
@SuppressLint("RestrictedApi")
|
|
63
|
+
@OptIn(ExperimentalCryptoOnramp::class)
|
|
60
64
|
@ReactModule(name = NativeOnrampSdkModuleSpec.NAME)
|
|
61
65
|
class OnrampSdkModule(
|
|
62
66
|
reactContext: ReactApplicationContext,
|
|
63
67
|
) : NativeOnrampSdkModuleSpec(reactContext) {
|
|
68
|
+
private val eventEmitterCompat = EventEmitterCompat(reactContext)
|
|
64
69
|
private lateinit var publishableKey: String
|
|
65
70
|
private var stripeAccountId: String? = null
|
|
66
71
|
|
|
@@ -142,7 +147,7 @@ class OnrampSdkModule(
|
|
|
142
147
|
val params = Arguments.createMap()
|
|
143
148
|
params.putString("onrampSessionId", sessionId)
|
|
144
149
|
|
|
145
|
-
emitOnCheckoutClientSecretRequested(params)
|
|
150
|
+
eventEmitterCompat.emitOnCheckoutClientSecretRequested(params)
|
|
146
151
|
|
|
147
152
|
checkoutClientSecretDeferred!!.await()
|
|
148
153
|
}
|
|
@@ -632,6 +637,16 @@ class OnrampSdkModule(
|
|
|
632
637
|
}
|
|
633
638
|
}
|
|
634
639
|
|
|
640
|
+
@ReactMethod
|
|
641
|
+
override fun addListener(eventType: String?) {
|
|
642
|
+
// noop, iOS only
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
@ReactMethod
|
|
646
|
+
override fun removeListeners(count: Double) {
|
|
647
|
+
// noop, iOS only
|
|
648
|
+
}
|
|
649
|
+
|
|
635
650
|
private fun handleOnrampIdentityVerificationResult(
|
|
636
651
|
result: OnrampVerifyIdentityResult,
|
|
637
652
|
promise: Promise,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalCryptoOnramp::class)
|
|
2
|
+
|
|
1
3
|
package com.reactnativestripesdk.mappers
|
|
2
4
|
|
|
3
5
|
import android.annotation.SuppressLint
|
|
@@ -5,6 +7,7 @@ import androidx.compose.ui.graphics.toArgb
|
|
|
5
7
|
import com.reactnativestripesdk.mapAppearance
|
|
6
8
|
import com.reactnativestripesdk.mapConfig
|
|
7
9
|
import com.reactnativestripesdk.utils.readableMapOf
|
|
10
|
+
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
8
11
|
import com.stripe.android.link.LinkAppearance.Style
|
|
9
12
|
import org.junit.Assert.assertEquals
|
|
10
13
|
import org.junit.Assert.assertNotNull
|