@stripe/stripe-react-native 0.65.1 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/detekt/detekt-baseline.xml +0 -10
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +51 -57
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementEvent.kt +26 -0
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementView.kt +129 -16
- package/android/src/main/java/com/reactnativestripesdk/CurrencySelectorElementViewManager.kt +17 -0
- package/android/src/main/java/com/reactnativestripesdk/EventEmitterCompat.kt +4 -0
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetManager.kt +8 -19
- package/android/src/main/java/com/reactnativestripesdk/StripeAbstractComposeView.kt +1 -0
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +89 -31
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkPackage.kt +1 -0
- package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetManager.kt +2 -16
- package/android/src/main/java/com/reactnativestripesdk/utils/CheckoutMappers.kt +59 -33
- package/android/src/main/java/com/reactnativestripesdk/utils/DefaultActivityLifecycleCallbacks.kt +41 -0
- package/android/src/main/java/com/reactnativestripesdk/utils/Errors.kt +11 -6
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeOnrampSdkModuleSpec.java +17 -3
- package/android/src/oldarch/java/com/reactnativestripesdk/NativeStripeSdkModuleSpec.java +2 -2
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampErrors.kt +145 -0
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampMappers.kt +125 -0
- package/android/src/onramp/java/com/reactnativestripesdk/OnrampSdkModule.kt +144 -22
- package/android/src/test/java/com/reactnativestripesdk/DrawableLoadingTest.kt +6 -2
- package/android/src/test/java/com/reactnativestripesdk/OnrampErrorsTest.kt +168 -0
- package/android/src/test/java/com/reactnativestripesdk/mappers/OnrampMappersTest.kt +107 -0
- package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutMappersTest.kt +39 -30
- package/android/src/test/java/com/reactnativestripesdk/utils/CheckoutTestFixtures.java +8 -0
- package/ios/CurrencySelectorElementManager.m +7 -0
- package/ios/CurrencySelectorElementView.swift +142 -7
- package/ios/EmbeddedPaymentElementView.swift +1 -1
- package/ios/Mappers+Checkout.swift +251 -107
- package/ios/Mappers.swift +97 -7
- package/ios/NewArch/StripeCurrencySelectorElementComponentView.mm +14 -0
- package/ios/OldArch/StripeSdkEventEmitterCompat.h +1 -0
- package/ios/OldArch/StripeSdkEventEmitterCompat.m +6 -0
- package/ios/OnrampErrors.swift +132 -0
- package/ios/PaymentOptionDisplayData+ReactNative.swift +1 -1
- package/ios/PaymentSheetAppearance.swift +1 -1
- package/ios/StripeOnrampSdk.mm +19 -0
- package/ios/StripeSdk.mm +14 -14
- package/ios/StripeSdkEmitter.swift +1 -0
- package/ios/StripeSdkImpl+Checkout.swift +66 -31
- package/ios/StripeSdkImpl+CustomerSheet.swift +1 -1
- package/ios/StripeSdkImpl+Embedded.swift +1 -1
- package/ios/StripeSdkImpl+PaymentSheet.swift +1 -1
- package/ios/StripeSdkImpl.swift +116 -24
- package/lib/commonjs/components/PaymentMethodMessagingElement.js +1 -1
- package/lib/commonjs/components/PaymentMethodMessagingElement.js.map +1 -1
- package/lib/commonjs/components/StripeProvider.js +1 -1
- package/lib/commonjs/components/StripeProvider.js.map +1 -1
- package/lib/commonjs/hooks/useCheckout.js +1 -1
- package/lib/commonjs/hooks/useCheckout.js.map +1 -1
- package/lib/commonjs/hooks/useOnramp.js +1 -1
- package/lib/commonjs/hooks/useOnramp.js.map +1 -1
- package/lib/commonjs/internal/stripeConfig.js +2 -0
- package/lib/commonjs/internal/stripeConfig.js.map +1 -0
- package/lib/commonjs/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/commonjs/specs/NativeStripeSdkModule.js.map +1 -1
- package/lib/commonjs/types/Errors.js +1 -1
- package/lib/commonjs/types/Errors.js.map +1 -1
- package/lib/commonjs/types/Onramp.js +1 -1
- package/lib/commonjs/types/Onramp.js.map +1 -1
- package/lib/module/components/PaymentMethodMessagingElement.js +1 -1
- package/lib/module/components/PaymentMethodMessagingElement.js.map +1 -1
- package/lib/module/components/StripeProvider.js +1 -1
- package/lib/module/components/StripeProvider.js.map +1 -1
- package/lib/module/hooks/useCheckout.js +1 -1
- package/lib/module/hooks/useCheckout.js.map +1 -1
- package/lib/module/hooks/useOnramp.js +1 -1
- package/lib/module/hooks/useOnramp.js.map +1 -1
- package/lib/module/internal/stripeConfig.js +2 -0
- package/lib/module/internal/stripeConfig.js.map +1 -0
- package/lib/module/specs/NativeOnrampSdkModule.js.map +1 -1
- package/lib/module/specs/NativeStripeSdkModule.js.map +1 -1
- package/lib/module/types/Errors.js +1 -1
- package/lib/module/types/Errors.js.map +1 -1
- package/lib/module/types/Onramp.js +1 -1
- package/lib/module/types/Onramp.js.map +1 -1
- package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts +1 -1
- package/lib/typescript/src/components/PaymentMethodMessagingElement.d.ts.map +1 -1
- package/lib/typescript/src/components/StripeProvider.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useCheckout.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useOnramp.d.ts +32 -10
- package/lib/typescript/src/hooks/useOnramp.d.ts.map +1 -1
- package/lib/typescript/src/internal/stripeConfig.d.ts +3 -0
- package/lib/typescript/src/internal/stripeConfig.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts +3 -0
- package/lib/typescript/src/specs/NativeOnrampSdkModule.d.ts.map +1 -1
- package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts +2 -2
- package/lib/typescript/src/specs/NativeStripeSdkModule.d.ts.map +1 -1
- package/lib/typescript/src/types/Checkout.d.ts +266 -92
- package/lib/typescript/src/types/Checkout.d.ts.map +1 -1
- package/lib/typescript/src/types/Errors.d.ts +0 -5
- package/lib/typescript/src/types/Errors.d.ts.map +1 -1
- package/lib/typescript/src/types/Onramp.d.ts +168 -9
- package/lib/typescript/src/types/Onramp.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/components/PaymentMethodMessagingElement.tsx +54 -52
- package/src/components/StripeProvider.tsx +2 -0
- package/src/hooks/useCheckout.tsx +20 -13
- package/src/hooks/useOnramp.tsx +139 -12
- package/src/internal/stripeConfig.ts +9 -0
- package/src/specs/NativeOnrampSdkModule.ts +5 -0
- package/src/specs/NativeStripeSdkModule.ts +6 -5
- package/src/types/Checkout.ts +289 -93
- package/src/types/Errors.ts +0 -6
- package/src/types/Onramp.ts +192 -9
- package/stripe-react-native.podspec +3 -3
- package/ios/CurrencySelectorElementManager.swift +0 -12
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
@file:OptIn(ExperimentalCryptoOnramp::class)
|
|
2
|
+
|
|
3
|
+
package com.reactnativestripesdk
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
6
|
+
import com.facebook.react.bridge.WritableArray
|
|
7
|
+
import com.facebook.react.bridge.WritableMap
|
|
8
|
+
import com.reactnativestripesdk.utils.ErrorType
|
|
9
|
+
import com.stripe.android.core.exception.StripeException
|
|
10
|
+
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
11
|
+
import com.stripe.android.crypto.onramp.exception.AppAttestationException
|
|
12
|
+
import com.stripe.android.crypto.onramp.exception.CryptoOnrampApiException
|
|
13
|
+
import com.stripe.android.crypto.onramp.exception.SDKVersion
|
|
14
|
+
import com.stripe.android.crypto.onramp.exception.StripeCryptoOnrampError
|
|
15
|
+
|
|
16
|
+
internal fun createOnrampFailedError(error: Throwable): WritableMap =
|
|
17
|
+
createOnrampError(ErrorType.Failed.toString(), error)
|
|
18
|
+
|
|
19
|
+
internal fun createOnrampNotConfiguredError(): WritableMap =
|
|
20
|
+
createOnrampMessageError(
|
|
21
|
+
ErrorType.Failed.toString(),
|
|
22
|
+
"Onramp is not configured.",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
private fun createOnrampError(
|
|
26
|
+
code: String,
|
|
27
|
+
error: Throwable,
|
|
28
|
+
): WritableMap {
|
|
29
|
+
val apiException =
|
|
30
|
+
error as? CryptoOnrampApiException
|
|
31
|
+
?: return createNonApiOnrampError(code, error)
|
|
32
|
+
|
|
33
|
+
val stripeError = apiException.stripeError
|
|
34
|
+
val onrampErrorType = apiException.toOnrampErrorType()
|
|
35
|
+
|
|
36
|
+
return createOnrampErrorMap(
|
|
37
|
+
code = code,
|
|
38
|
+
message = apiException.userMessage,
|
|
39
|
+
localizedMessage = apiException.localizedMessage,
|
|
40
|
+
declineCode = stripeError?.declineCode,
|
|
41
|
+
type = apiException.context.apiErrorType ?: stripeError?.type,
|
|
42
|
+
stripeErrorCode = apiException.code,
|
|
43
|
+
) {
|
|
44
|
+
putString("onrampErrorType", onrampErrorType)
|
|
45
|
+
putString("developerMessage", apiException.developerMessage)
|
|
46
|
+
putString("userMessage", apiException.userMessage)
|
|
47
|
+
putString("reason", apiException.context.reason)
|
|
48
|
+
putString("operation", apiException.context.operation)
|
|
49
|
+
putString("appPackageName", apiException.context.appPackageName)
|
|
50
|
+
putString("mode", apiException.context.mode)
|
|
51
|
+
putArray("sdkVersions", mapFromSdkVersions(apiException.sdkVersions))
|
|
52
|
+
putString("requestId", apiException.context.requestId)
|
|
53
|
+
putString("apiErrorCode", apiException.context.apiErrorCode)
|
|
54
|
+
putString("apiErrorType", apiException.context.apiErrorType)
|
|
55
|
+
putString("apiErrorMessage", apiException.context.apiErrorMessage)
|
|
56
|
+
putString("apiUserMessage", apiException.context.apiUserMessage)
|
|
57
|
+
putString("docUrl", apiException.context.docUrl)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private fun createNonApiOnrampError(
|
|
62
|
+
code: String,
|
|
63
|
+
error: Throwable,
|
|
64
|
+
): WritableMap {
|
|
65
|
+
val onrampError =
|
|
66
|
+
error as? StripeCryptoOnrampError
|
|
67
|
+
?: return createGenericError(code, error)
|
|
68
|
+
|
|
69
|
+
return createOnrampErrorMap(
|
|
70
|
+
code = code,
|
|
71
|
+
message = onrampError.userMessage,
|
|
72
|
+
localizedMessage = error.localizedMessage,
|
|
73
|
+
stripeErrorCode = onrampError.code,
|
|
74
|
+
) {
|
|
75
|
+
putString("developerMessage", onrampError.developerMessage)
|
|
76
|
+
putString("userMessage", onrampError.userMessage)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private fun createOnrampMessageError(
|
|
81
|
+
code: String,
|
|
82
|
+
message: String?,
|
|
83
|
+
): WritableMap =
|
|
84
|
+
createOnrampErrorMap(code = code, message = message)
|
|
85
|
+
|
|
86
|
+
private fun CryptoOnrampApiException.toOnrampErrorType(): String =
|
|
87
|
+
if (this is AppAttestationException) {
|
|
88
|
+
"AppAttestationError"
|
|
89
|
+
} else {
|
|
90
|
+
"UncategorizedApiError"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private fun createGenericError(
|
|
94
|
+
code: String,
|
|
95
|
+
error: Throwable,
|
|
96
|
+
): WritableMap {
|
|
97
|
+
val stripeError = (error as? StripeException)?.stripeError
|
|
98
|
+
|
|
99
|
+
return createOnrampErrorMap(
|
|
100
|
+
code = code,
|
|
101
|
+
message = error.message,
|
|
102
|
+
localizedMessage = error.localizedMessage,
|
|
103
|
+
declineCode = stripeError?.declineCode,
|
|
104
|
+
type = stripeError?.type,
|
|
105
|
+
stripeErrorCode = stripeError?.code,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private fun createOnrampErrorMap(
|
|
110
|
+
code: String,
|
|
111
|
+
message: String?,
|
|
112
|
+
localizedMessage: String? = message,
|
|
113
|
+
declineCode: String? = null,
|
|
114
|
+
type: String? = null,
|
|
115
|
+
stripeErrorCode: String? = null,
|
|
116
|
+
configure: (WritableMap.() -> Unit)? = null,
|
|
117
|
+
): WritableMap {
|
|
118
|
+
val map: WritableMap = Arguments.createMap()
|
|
119
|
+
val details: WritableMap = Arguments.createMap()
|
|
120
|
+
|
|
121
|
+
details.putString("code", code)
|
|
122
|
+
details.putString("message", message)
|
|
123
|
+
details.putString("localizedMessage", localizedMessage)
|
|
124
|
+
details.putString("declineCode", declineCode)
|
|
125
|
+
details.putString("type", type)
|
|
126
|
+
details.putString("stripeErrorCode", stripeErrorCode)
|
|
127
|
+
configure?.invoke(details)
|
|
128
|
+
|
|
129
|
+
map.putMap("error", details)
|
|
130
|
+
return map
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private fun mapFromSdkVersions(
|
|
134
|
+
sdkVersions: List<SDKVersion>,
|
|
135
|
+
): WritableArray =
|
|
136
|
+
Arguments.createArray().apply {
|
|
137
|
+
sdkVersions.forEach { sdkVersion ->
|
|
138
|
+
pushMap(
|
|
139
|
+
Arguments.createMap().apply {
|
|
140
|
+
putString("name", sdkVersion.name)
|
|
141
|
+
putString("version", sdkVersion.version)
|
|
142
|
+
},
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -5,11 +5,21 @@ package com.reactnativestripesdk
|
|
|
5
5
|
import android.annotation.SuppressLint
|
|
6
6
|
import androidx.compose.ui.graphics.Color
|
|
7
7
|
import com.facebook.react.bridge.Arguments
|
|
8
|
+
import com.facebook.react.bridge.ReadableArray
|
|
8
9
|
import com.facebook.react.bridge.ReadableMap
|
|
10
|
+
import com.facebook.react.bridge.WritableArray
|
|
11
|
+
import com.stripe.android.core.model.CountryCode
|
|
9
12
|
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
13
|
+
import com.stripe.android.crypto.onramp.exception.SDKVersion
|
|
10
14
|
import com.stripe.android.crypto.onramp.model.KycInfo
|
|
11
15
|
import com.stripe.android.crypto.onramp.model.OnrampConfiguration
|
|
12
16
|
import com.stripe.android.crypto.onramp.model.PaymentMethodDisplayData
|
|
17
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifier
|
|
18
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierAlternativeGroup
|
|
19
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierRequirement
|
|
20
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierRequirements
|
|
21
|
+
import com.stripe.android.crypto.onramp.model.compliance.ComplianceIdentifierType
|
|
22
|
+
import com.stripe.android.crypto.onramp.model.compliance.SubmitIdentifiersResult
|
|
13
23
|
import com.stripe.android.googlepaylauncher.GooglePayEnvironment
|
|
14
24
|
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
|
|
15
25
|
import com.stripe.android.link.LinkAppearance
|
|
@@ -23,6 +33,7 @@ import com.stripe.android.paymentsheet.PaymentSheet
|
|
|
23
33
|
internal fun mapConfig(
|
|
24
34
|
configMap: ReadableMap,
|
|
25
35
|
publishableKey: String,
|
|
36
|
+
additionalSdkVersions: List<SDKVersion> = emptyList(),
|
|
26
37
|
): OnrampConfiguration {
|
|
27
38
|
val appearanceMap = configMap.getMap("appearance")
|
|
28
39
|
val appearance =
|
|
@@ -43,6 +54,11 @@ internal fun mapConfig(
|
|
|
43
54
|
.appearance(appearance)
|
|
44
55
|
.cryptoCustomerId(cryptoCustomerId)
|
|
45
56
|
.apply { googlePayConfig?.let { googlePayConfig(it) } }
|
|
57
|
+
.apply {
|
|
58
|
+
if (additionalSdkVersions.isNotEmpty()) {
|
|
59
|
+
this.additionalSdkVersions(additionalSdkVersions)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
@SuppressLint("RestrictedApi")
|
|
@@ -178,10 +194,112 @@ internal fun mapFromKycInfo(kycInfo: KycInfo): ReadableMap {
|
|
|
178
194
|
kycInfo.idNumber?.let { result.putString("idNumber", it) }
|
|
179
195
|
kycInfo.address?.let { result.putMap("address", mapFromKycAddress(it)) }
|
|
180
196
|
kycInfo.dateOfBirth?.let { result.putMap("dateOfBirth", mapFromDateOfBirth(it)) }
|
|
197
|
+
kycInfo.birthCountry?.let { result.putString("birthCountry", it.value) }
|
|
198
|
+
kycInfo.birthCity?.let { result.putString("birthCity", it) }
|
|
199
|
+
kycInfo.nationalities?.let {
|
|
200
|
+
result.putArray("nationalities", mapFromCountryCodes(it))
|
|
201
|
+
}
|
|
181
202
|
|
|
182
203
|
return result
|
|
183
204
|
}
|
|
184
205
|
|
|
206
|
+
internal fun mapToComplianceIdentifiers(identifiers: ReadableArray): List<ComplianceIdentifier> {
|
|
207
|
+
val complianceIdentifiers = mutableListOf<ComplianceIdentifier>()
|
|
208
|
+
|
|
209
|
+
for (index in 0 until identifiers.size()) {
|
|
210
|
+
val identifierMap =
|
|
211
|
+
runCatching { identifiers.getMap(index) }
|
|
212
|
+
.getOrNull()
|
|
213
|
+
?: throw InvalidIdentifiersArrayException()
|
|
214
|
+
val type = identifierMap.getRequiredNormalizedString("type")
|
|
215
|
+
val value = identifierMap.getRequiredNormalizedString("value")
|
|
216
|
+
|
|
217
|
+
complianceIdentifiers.add(
|
|
218
|
+
ComplianceIdentifier()
|
|
219
|
+
.type(ComplianceIdentifierType(type))
|
|
220
|
+
.value(value),
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return complianceIdentifiers
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
internal fun mapFromComplianceIdentifierRequirements(
|
|
228
|
+
requirements: ComplianceIdentifierRequirements,
|
|
229
|
+
) = Arguments.createMap().apply {
|
|
230
|
+
putArray("identifiers", mapFromComplianceIdentifierRequirementsList(requirements.identifiers))
|
|
231
|
+
putArray("alternatives", mapFromComplianceIdentifierAlternativeGroups(requirements.alternatives))
|
|
232
|
+
putBoolean("carfTinRequired", requirements.carfTinRequired)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
internal fun mapFromSubmitIdentifiersResult(
|
|
236
|
+
result: SubmitIdentifiersResult,
|
|
237
|
+
) = Arguments.createMap().apply {
|
|
238
|
+
putBoolean("completed", result.completed)
|
|
239
|
+
putArray("identifiers", mapFromComplianceIdentifierRequirementsList(result.identifiers))
|
|
240
|
+
putArray("alternatives", mapFromComplianceIdentifierAlternativeGroups(result.alternatives))
|
|
241
|
+
putBoolean("carfTinRequired", result.carfTinRequired)
|
|
242
|
+
putArray("invalidIdentifiers", mapFromComplianceIdentifierTypes(result.invalidIdentifiers))
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private fun mapFromComplianceIdentifierRequirementsList(
|
|
246
|
+
requirements: List<ComplianceIdentifierRequirement>,
|
|
247
|
+
): WritableArray =
|
|
248
|
+
Arguments.createArray().apply {
|
|
249
|
+
requirements.forEach { requirement ->
|
|
250
|
+
pushMap(
|
|
251
|
+
Arguments.createMap().apply {
|
|
252
|
+
putString("type", requirement.type.value)
|
|
253
|
+
putString("regulation", requirement.regulation.value)
|
|
254
|
+
},
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private fun mapFromComplianceIdentifierAlternativeGroups(
|
|
260
|
+
groups: List<ComplianceIdentifierAlternativeGroup>,
|
|
261
|
+
): WritableArray =
|
|
262
|
+
Arguments.createArray().apply {
|
|
263
|
+
groups.forEach { group ->
|
|
264
|
+
pushMap(
|
|
265
|
+
Arguments.createMap().apply {
|
|
266
|
+
putArray(
|
|
267
|
+
"originalMissingIdentifiers",
|
|
268
|
+
mapFromComplianceIdentifierTypes(group.originalMissingIdentifiers),
|
|
269
|
+
)
|
|
270
|
+
putArray(
|
|
271
|
+
"alternativeMissingIdentifiers",
|
|
272
|
+
mapFromComplianceIdentifierTypes(group.alternativeMissingIdentifiers),
|
|
273
|
+
)
|
|
274
|
+
},
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private fun mapFromComplianceIdentifierTypes(
|
|
280
|
+
identifierTypes: List<ComplianceIdentifierType>,
|
|
281
|
+
): WritableArray =
|
|
282
|
+
Arguments.createArray().apply {
|
|
283
|
+
identifierTypes.forEach { identifierType ->
|
|
284
|
+
pushString(identifierType.value)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private fun mapFromCountryCodes(
|
|
289
|
+
countryCodes: List<CountryCode>,
|
|
290
|
+
): WritableArray =
|
|
291
|
+
Arguments.createArray().apply {
|
|
292
|
+
countryCodes.forEach { countryCode ->
|
|
293
|
+
pushString(countryCode.value)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private fun ReadableMap.getRequiredNormalizedString(key: String): String =
|
|
298
|
+
getString(key)
|
|
299
|
+
?.trim()
|
|
300
|
+
?.takeIf { it.isNotEmpty() }
|
|
301
|
+
?: throw ComplianceIdentifierFieldException(key)
|
|
302
|
+
|
|
185
303
|
private fun mapFromKycAddress(address: PaymentSheet.Address): ReadableMap {
|
|
186
304
|
val result = Arguments.createMap()
|
|
187
305
|
|
|
@@ -202,3 +320,10 @@ private fun mapFromDateOfBirth(dateOfBirth: DateOfBirth): ReadableMap {
|
|
|
202
320
|
result.putInt("year", dateOfBirth.year)
|
|
203
321
|
return result
|
|
204
322
|
}
|
|
323
|
+
|
|
324
|
+
internal class ComplianceIdentifierFieldException(
|
|
325
|
+
field: String,
|
|
326
|
+
) : IllegalArgumentException("Invalid format for field: $field")
|
|
327
|
+
|
|
328
|
+
internal class InvalidIdentifiersArrayException :
|
|
329
|
+
IllegalArgumentException("Unexpected format of identifiers array. Expected dictionaries with String keys.")
|
|
@@ -7,10 +7,12 @@ import android.app.Application
|
|
|
7
7
|
import androidx.activity.ComponentActivity
|
|
8
8
|
import androidx.fragment.app.FragmentActivity
|
|
9
9
|
import androidx.lifecycle.SavedStateHandle
|
|
10
|
+
import com.stripe.android.core.model.CountryCode
|
|
10
11
|
import com.facebook.react.bridge.Arguments
|
|
11
12
|
import com.facebook.react.bridge.Promise
|
|
12
13
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
13
14
|
import com.facebook.react.bridge.ReactMethod
|
|
15
|
+
import com.facebook.react.bridge.ReadableArray
|
|
14
16
|
import com.facebook.react.bridge.ReadableMap
|
|
15
17
|
import com.facebook.react.bridge.WritableNativeMap
|
|
16
18
|
import com.facebook.react.module.annotations.ReactModule
|
|
@@ -18,15 +20,15 @@ import com.reactnativestripesdk.utils.ErrorType
|
|
|
18
20
|
import com.reactnativestripesdk.utils.createCanceledError
|
|
19
21
|
import com.reactnativestripesdk.utils.createEmptyResult
|
|
20
22
|
import com.reactnativestripesdk.utils.createError
|
|
21
|
-
import com.reactnativestripesdk.utils.createFailedError
|
|
22
23
|
import com.reactnativestripesdk.utils.createMissingActivityError
|
|
23
24
|
import com.reactnativestripesdk.utils.createMissingInitError
|
|
24
|
-
import com.reactnativestripesdk.utils.createOnrampNotConfiguredError
|
|
25
25
|
import com.reactnativestripesdk.utils.createResult
|
|
26
|
+
import com.reactnativestripesdk.utils.getStringList
|
|
26
27
|
import com.reactnativestripesdk.utils.getValOr
|
|
27
28
|
import com.reactnativestripesdk.utils.mapToPaymentSheetAddress
|
|
28
29
|
import com.stripe.android.crypto.onramp.ExperimentalCryptoOnramp
|
|
29
30
|
import com.stripe.android.crypto.onramp.OnrampCoordinator
|
|
31
|
+
import com.stripe.android.crypto.onramp.exception.SDKVersion
|
|
30
32
|
import com.stripe.android.crypto.onramp.model.CryptoNetwork
|
|
31
33
|
import com.stripe.android.crypto.onramp.model.KycInfo
|
|
32
34
|
import com.stripe.android.crypto.onramp.model.LinkUserInfo
|
|
@@ -37,10 +39,13 @@ import com.stripe.android.crypto.onramp.model.OnrampCheckoutResult
|
|
|
37
39
|
import com.stripe.android.crypto.onramp.model.OnrampCollectPaymentMethodResult
|
|
38
40
|
import com.stripe.android.crypto.onramp.model.OnrampConfigurationResult
|
|
39
41
|
import com.stripe.android.crypto.onramp.model.OnrampCreateCryptoPaymentTokenResult
|
|
42
|
+
import com.stripe.android.crypto.onramp.model.OnrampCrsCarfDeclarationResult
|
|
40
43
|
import com.stripe.android.crypto.onramp.model.OnrampHasLinkAccountResult
|
|
41
44
|
import com.stripe.android.crypto.onramp.model.OnrampLogOutResult
|
|
42
45
|
import com.stripe.android.crypto.onramp.model.OnrampRegisterLinkUserResult
|
|
43
46
|
import com.stripe.android.crypto.onramp.model.OnrampRegisterWalletAddressResult
|
|
47
|
+
import com.stripe.android.crypto.onramp.model.OnrampRetrieveMissingIdentifiersResult
|
|
48
|
+
import com.stripe.android.crypto.onramp.model.OnrampSubmitIdentifiersResult
|
|
44
49
|
import com.stripe.android.crypto.onramp.model.OnrampTokenAuthenticationResult
|
|
45
50
|
import com.stripe.android.crypto.onramp.model.OnrampUpdatePhoneNumberResult
|
|
46
51
|
import com.stripe.android.crypto.onramp.model.OnrampVerifyIdentityResult
|
|
@@ -66,6 +71,7 @@ class OnrampSdkModule(
|
|
|
66
71
|
reactContext: ReactApplicationContext,
|
|
67
72
|
) : NativeOnrampSdkModuleSpec(reactContext) {
|
|
68
73
|
private val eventEmitterCompat = EventEmitterCompat(reactContext)
|
|
74
|
+
private var reactNativeSdkVersion: String? = null
|
|
69
75
|
private lateinit var publishableKey: String
|
|
70
76
|
private var stripeAccountId: String? = null
|
|
71
77
|
|
|
@@ -78,6 +84,7 @@ class OnrampSdkModule(
|
|
|
78
84
|
private var authorizePromise: Promise? = null
|
|
79
85
|
private var checkoutPromise: Promise? = null
|
|
80
86
|
private var verifyKycPromise: Promise? = null
|
|
87
|
+
private var userAttestationPromise: Promise? = null
|
|
81
88
|
|
|
82
89
|
private var checkoutClientSecretDeferred: CompletableDeferred<String>? = null
|
|
83
90
|
private val rnScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
|
|
@@ -89,6 +96,10 @@ class OnrampSdkModule(
|
|
|
89
96
|
) {
|
|
90
97
|
// Note: This method depends on `StripeSdkModule#initialise()` being called as well.
|
|
91
98
|
val publishableKey = getValOr(params, "publishableKey", null) as String
|
|
99
|
+
reactNativeSdkVersion =
|
|
100
|
+
params.getMap("appInfo")
|
|
101
|
+
?.getString("version")
|
|
102
|
+
?.takeIf { it.isNotBlank() }
|
|
92
103
|
this.stripeAccountId = getValOr(params, "stripeAccountId", null)
|
|
93
104
|
this.publishableKey = publishableKey
|
|
94
105
|
|
|
@@ -141,6 +152,10 @@ class OnrampSdkModule(
|
|
|
141
152
|
handleOnrampCheckoutResult(result, checkoutPromise!!)
|
|
142
153
|
}.verifyKycCallback { result ->
|
|
143
154
|
handleOnrampKycVerificationResult(result, verifyKycPromise!!)
|
|
155
|
+
}.crsCarfDeclarationCallback { result ->
|
|
156
|
+
userAttestationPromise?.let {
|
|
157
|
+
handleUserAttestationResult(result, it)
|
|
158
|
+
}
|
|
144
159
|
}.onrampSessionClientSecretProvider { sessionId ->
|
|
145
160
|
checkoutClientSecretDeferred = CompletableDeferred()
|
|
146
161
|
|
|
@@ -159,7 +174,7 @@ class OnrampSdkModule(
|
|
|
159
174
|
.also { this.onrampCoordinator = it }
|
|
160
175
|
|
|
161
176
|
CoroutineScope(Dispatchers.IO).launch {
|
|
162
|
-
val configuration = mapConfig(config, publishableKey)
|
|
177
|
+
val configuration = mapConfig(config, publishableKey, onrampAdditionalSdkVersions())
|
|
163
178
|
val configureResult = coordinator.configure(configuration)
|
|
164
179
|
|
|
165
180
|
CoroutineScope(Dispatchers.Main).launch {
|
|
@@ -168,7 +183,7 @@ class OnrampSdkModule(
|
|
|
168
183
|
createOnrampPresenter(promise)
|
|
169
184
|
}
|
|
170
185
|
is OnrampConfigurationResult.Failed -> {
|
|
171
|
-
promise.resolve(
|
|
186
|
+
promise.resolve(createOnrampFailedError(configureResult.error))
|
|
172
187
|
}
|
|
173
188
|
}
|
|
174
189
|
}
|
|
@@ -195,7 +210,7 @@ class OnrampSdkModule(
|
|
|
195
210
|
onrampPresenter = onrampCoordinator!!.createPresenter(activity)
|
|
196
211
|
promise.resolveVoid()
|
|
197
212
|
} catch (e: Exception) {
|
|
198
|
-
promise.resolve(
|
|
213
|
+
promise.resolve(createOnrampFailedError(e))
|
|
199
214
|
}
|
|
200
215
|
}
|
|
201
216
|
|
|
@@ -215,7 +230,7 @@ class OnrampSdkModule(
|
|
|
215
230
|
promise.resolveBoolean("hasLinkAccount", result.hasLinkAccount)
|
|
216
231
|
}
|
|
217
232
|
is OnrampHasLinkAccountResult.Failed -> {
|
|
218
|
-
promise.resolve(
|
|
233
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
219
234
|
}
|
|
220
235
|
}
|
|
221
236
|
}
|
|
@@ -246,7 +261,7 @@ class OnrampSdkModule(
|
|
|
246
261
|
promise.resolveString("customerId", result.customerId)
|
|
247
262
|
}
|
|
248
263
|
is OnrampRegisterLinkUserResult.Failed -> {
|
|
249
|
-
promise.resolve(
|
|
264
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
250
265
|
}
|
|
251
266
|
}
|
|
252
267
|
}
|
|
@@ -275,7 +290,7 @@ class OnrampSdkModule(
|
|
|
275
290
|
promise.resolveVoid()
|
|
276
291
|
}
|
|
277
292
|
is OnrampRegisterWalletAddressResult.Failed -> {
|
|
278
|
-
promise.resolve(
|
|
293
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
279
294
|
}
|
|
280
295
|
}
|
|
281
296
|
}
|
|
@@ -311,10 +326,16 @@ class OnrampSdkModule(
|
|
|
311
326
|
)
|
|
312
327
|
} else {
|
|
313
328
|
null
|
|
314
|
-
|
|
329
|
+
}
|
|
315
330
|
|
|
316
331
|
val addressMap = kycInfo.getMap("address")
|
|
317
332
|
val addressObj = mapToPaymentSheetAddress(addressMap)
|
|
333
|
+
val birthCountry = kycInfo.getString("birthCountry")?.let(CountryCode::create)
|
|
334
|
+
val birthCity = kycInfo.getString("birthCity")
|
|
335
|
+
val nationalities =
|
|
336
|
+
kycInfo.getStringList("nationalities")
|
|
337
|
+
?.map(CountryCode::create)
|
|
338
|
+
?.takeIf { it.isNotEmpty() }
|
|
318
339
|
|
|
319
340
|
val kycInfoObj =
|
|
320
341
|
KycInfo(
|
|
@@ -323,6 +344,9 @@ class OnrampSdkModule(
|
|
|
323
344
|
idNumber = idNumber,
|
|
324
345
|
dateOfBirth = dob,
|
|
325
346
|
address = addressObj,
|
|
347
|
+
birthCountry = birthCountry,
|
|
348
|
+
birthCity = birthCity,
|
|
349
|
+
nationalities = nationalities,
|
|
326
350
|
)
|
|
327
351
|
|
|
328
352
|
when (val result = coordinator.attachKycInfo(kycInfoObj)) {
|
|
@@ -330,12 +354,81 @@ class OnrampSdkModule(
|
|
|
330
354
|
promise.resolveVoid()
|
|
331
355
|
}
|
|
332
356
|
is OnrampAttachKycInfoResult.Failed -> {
|
|
333
|
-
promise.resolve(
|
|
357
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
@ReactMethod
|
|
364
|
+
override fun retrieveMissingIdentifiers(promise: Promise) {
|
|
365
|
+
val coordinator =
|
|
366
|
+
onrampCoordinator ?: run {
|
|
367
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
368
|
+
return
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
372
|
+
when (val result = coordinator.retrieveMissingIdentifiers()) {
|
|
373
|
+
is OnrampRetrieveMissingIdentifiersResult.Completed -> {
|
|
374
|
+
promise.resolve(mapFromComplianceIdentifierRequirements(result.requirements))
|
|
375
|
+
}
|
|
376
|
+
is OnrampRetrieveMissingIdentifiersResult.Failed -> {
|
|
377
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@ReactMethod
|
|
384
|
+
override fun submitIdentifiers(
|
|
385
|
+
identifiers: ReadableArray,
|
|
386
|
+
promise: Promise,
|
|
387
|
+
) {
|
|
388
|
+
val coordinator =
|
|
389
|
+
onrampCoordinator ?: run {
|
|
390
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
391
|
+
return
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
val complianceIdentifiers =
|
|
395
|
+
try {
|
|
396
|
+
mapToComplianceIdentifiers(identifiers)
|
|
397
|
+
} catch (error: IllegalArgumentException) {
|
|
398
|
+
val errorType =
|
|
399
|
+
if (error is ComplianceIdentifierFieldException) {
|
|
400
|
+
ErrorType.Unknown
|
|
401
|
+
} else {
|
|
402
|
+
ErrorType.Failed
|
|
403
|
+
}
|
|
404
|
+
promise.resolve(createError(errorType.toString(), error.message ?: "Invalid identifiers"))
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
409
|
+
when (val result = coordinator.submitIdentifiers(complianceIdentifiers)) {
|
|
410
|
+
is OnrampSubmitIdentifiersResult.Completed -> {
|
|
411
|
+
promise.resolve(mapFromSubmitIdentifiersResult(result.result))
|
|
412
|
+
}
|
|
413
|
+
is OnrampSubmitIdentifiersResult.Failed -> {
|
|
414
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
334
415
|
}
|
|
335
416
|
}
|
|
336
417
|
}
|
|
337
418
|
}
|
|
338
419
|
|
|
420
|
+
@ReactMethod
|
|
421
|
+
override fun presentUserAttestation(promise: Promise) {
|
|
422
|
+
val presenter =
|
|
423
|
+
onrampPresenter ?: run {
|
|
424
|
+
promise.resolve(createOnrampNotConfiguredError())
|
|
425
|
+
return
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
userAttestationPromise = promise
|
|
429
|
+
presenter.presentCrsCarfDeclaration()
|
|
430
|
+
}
|
|
431
|
+
|
|
339
432
|
@ReactMethod
|
|
340
433
|
override fun updatePhoneNumber(
|
|
341
434
|
phone: String,
|
|
@@ -352,7 +445,7 @@ class OnrampSdkModule(
|
|
|
352
445
|
promise.resolveVoid()
|
|
353
446
|
}
|
|
354
447
|
is OnrampUpdatePhoneNumberResult.Failed -> {
|
|
355
|
-
promise.resolve(
|
|
448
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
356
449
|
}
|
|
357
450
|
}
|
|
358
451
|
}
|
|
@@ -410,7 +503,7 @@ class OnrampSdkModule(
|
|
|
410
503
|
platformPayParams.getMap("googlePay")
|
|
411
504
|
?: run {
|
|
412
505
|
promise.resolve(
|
|
413
|
-
|
|
506
|
+
createOnrampFailedError(
|
|
414
507
|
IllegalArgumentException("Missing googlePay params in platformPayParams"),
|
|
415
508
|
),
|
|
416
509
|
)
|
|
@@ -431,7 +524,7 @@ class OnrampSdkModule(
|
|
|
431
524
|
}
|
|
432
525
|
else -> {
|
|
433
526
|
promise.resolve(
|
|
434
|
-
|
|
527
|
+
createOnrampFailedError(
|
|
435
528
|
IllegalArgumentException("Unsupported payment method: $paymentMethod"),
|
|
436
529
|
),
|
|
437
530
|
)
|
|
@@ -559,7 +652,7 @@ class OnrampSdkModule(
|
|
|
559
652
|
|
|
560
653
|
if (paymentDetails == null) {
|
|
561
654
|
promise.resolve(
|
|
562
|
-
|
|
655
|
+
createOnrampFailedError(
|
|
563
656
|
IllegalArgumentException("Unsupported payment method"),
|
|
564
657
|
),
|
|
565
658
|
)
|
|
@@ -660,7 +753,7 @@ class OnrampSdkModule(
|
|
|
660
753
|
promise.resolve(createCanceledError("Identity verification was cancelled"))
|
|
661
754
|
}
|
|
662
755
|
is OnrampVerifyIdentityResult.Failed -> {
|
|
663
|
-
promise.resolve(
|
|
756
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
664
757
|
}
|
|
665
758
|
}
|
|
666
759
|
}
|
|
@@ -684,7 +777,26 @@ class OnrampSdkModule(
|
|
|
684
777
|
promise.resolve(createCanceledError("KYC verification was cancelled"))
|
|
685
778
|
}
|
|
686
779
|
is OnrampVerifyKycInfoResult.Failed -> {
|
|
687
|
-
promise.resolve(
|
|
780
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private fun handleUserAttestationResult(
|
|
786
|
+
result: OnrampCrsCarfDeclarationResult,
|
|
787
|
+
promise: Promise,
|
|
788
|
+
) {
|
|
789
|
+
when (result) {
|
|
790
|
+
is OnrampCrsCarfDeclarationResult.Confirmed -> {
|
|
791
|
+
promise.resolve(
|
|
792
|
+
WritableNativeMap().apply { putString("status", "Confirmed") },
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
is OnrampCrsCarfDeclarationResult.Cancelled -> {
|
|
796
|
+
promise.resolve(createCanceledError("User attestation was canceled"))
|
|
797
|
+
}
|
|
798
|
+
is OnrampCrsCarfDeclarationResult.Failed -> {
|
|
799
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
688
800
|
}
|
|
689
801
|
}
|
|
690
802
|
}
|
|
@@ -735,7 +847,7 @@ class OnrampSdkModule(
|
|
|
735
847
|
}
|
|
736
848
|
|
|
737
849
|
is OnrampCollectPaymentMethodResult.Failed -> {
|
|
738
|
-
promise.resolve(
|
|
850
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
739
851
|
}
|
|
740
852
|
}
|
|
741
853
|
}
|
|
@@ -764,7 +876,7 @@ class OnrampSdkModule(
|
|
|
764
876
|
promise.resolve(createCanceledError("Authorization was cancelled"))
|
|
765
877
|
}
|
|
766
878
|
is OnrampAuthorizeResult.Failed -> {
|
|
767
|
-
promise.resolve(
|
|
879
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
768
880
|
}
|
|
769
881
|
}
|
|
770
882
|
}
|
|
@@ -781,7 +893,7 @@ class OnrampSdkModule(
|
|
|
781
893
|
promise.resolve(createCanceledError("Checkout was cancelled"))
|
|
782
894
|
}
|
|
783
895
|
is OnrampCheckoutResult.Failed -> {
|
|
784
|
-
promise.resolve(
|
|
896
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
785
897
|
}
|
|
786
898
|
}
|
|
787
899
|
}
|
|
@@ -795,7 +907,7 @@ class OnrampSdkModule(
|
|
|
795
907
|
promise.resolveString("cryptoPaymentToken", result.cryptoPaymentToken)
|
|
796
908
|
}
|
|
797
909
|
is OnrampCreateCryptoPaymentTokenResult.Failed -> {
|
|
798
|
-
promise.resolve(
|
|
910
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
799
911
|
}
|
|
800
912
|
}
|
|
801
913
|
}
|
|
@@ -809,7 +921,7 @@ class OnrampSdkModule(
|
|
|
809
921
|
promise.resolveVoid()
|
|
810
922
|
}
|
|
811
923
|
is OnrampLogOutResult.Failed -> {
|
|
812
|
-
promise.resolve(
|
|
924
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
813
925
|
}
|
|
814
926
|
}
|
|
815
927
|
}
|
|
@@ -823,7 +935,7 @@ class OnrampSdkModule(
|
|
|
823
935
|
promise.resolveVoid()
|
|
824
936
|
}
|
|
825
937
|
is OnrampTokenAuthenticationResult.Failed -> {
|
|
826
|
-
promise.resolve(
|
|
938
|
+
promise.resolve(createOnrampFailedError(result.error))
|
|
827
939
|
}
|
|
828
940
|
}
|
|
829
941
|
}
|
|
@@ -845,4 +957,14 @@ class OnrampSdkModule(
|
|
|
845
957
|
) {
|
|
846
958
|
resolve(WritableNativeMap().apply { putBoolean(key, value) })
|
|
847
959
|
}
|
|
960
|
+
|
|
961
|
+
private fun onrampAdditionalSdkVersions(): List<SDKVersion> =
|
|
962
|
+
reactNativeSdkVersion?.let {
|
|
963
|
+
listOf(
|
|
964
|
+
SDKVersion(
|
|
965
|
+
name = "stripe-react-native",
|
|
966
|
+
version = it,
|
|
967
|
+
),
|
|
968
|
+
)
|
|
969
|
+
} ?: emptyList()
|
|
848
970
|
}
|