@stripe/stripe-react-native 0.10.0 → 0.13.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 +42 -0
- package/README.md +3 -3
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +46 -10
- package/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt +5 -0
- package/android/src/main/java/com/reactnativestripesdk/CardFormView.kt +8 -0
- package/android/src/main/java/com/reactnativestripesdk/CardFormViewManager.kt +6 -1
- package/android/src/main/java/com/reactnativestripesdk/Errors.kt +14 -1
- package/android/src/main/java/com/reactnativestripesdk/GooglePayFragment.kt +68 -52
- package/android/src/main/java/com/reactnativestripesdk/Mappers.kt +5 -7
- package/android/src/main/java/com/reactnativestripesdk/PaymentLauncherFragment.kt +127 -37
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +173 -0
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +60 -36
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +67 -177
- package/ios/CardFieldManager.m +1 -0
- package/ios/CardFieldView.swift +6 -0
- package/ios/Mappers.swift +8 -9
- package/ios/PaymentSheetAppearance.swift +209 -0
- package/ios/StripeSdk.swift +141 -116
- package/lib/commonjs/components/AddToWalletButton.js +1 -1
- package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
- package/lib/commonjs/components/ApplePayButton.js +1 -1
- package/lib/commonjs/components/ApplePayButton.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/GooglePayButton.js +1 -1
- package/lib/commonjs/components/GooglePayButton.js.map +1 -1
- package/lib/commonjs/components/StripeContainer.js +1 -1
- package/lib/commonjs/components/StripeContainer.js.map +1 -1
- package/lib/commonjs/functions.js.map +1 -1
- package/lib/commonjs/types/components/CardFieldInput.js.map +1 -1
- package/lib/commonjs/types/index.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/ApplePayButton.js +1 -1
- package/lib/module/components/ApplePayButton.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/GooglePayButton.js +1 -1
- package/lib/module/components/GooglePayButton.js.map +1 -1
- package/lib/module/components/StripeContainer.js +1 -1
- package/lib/module/components/StripeContainer.js.map +1 -1
- package/lib/module/functions.js.map +1 -1
- package/lib/module/types/components/CardFieldInput.js.map +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/typescript/example/src/screens/PaymentSheetAppearance.d.ts +3 -0
- package/lib/typescript/src/components/CardField.d.ts +3 -0
- package/lib/typescript/src/components/CardForm.d.ts +2 -0
- package/lib/typescript/src/types/PaymentSheet.d.ts +154 -1
- package/lib/typescript/src/types/Token.d.ts +9 -1
- package/lib/typescript/src/types/components/CardFieldInput.d.ts +1 -0
- package/lib/typescript/src/types/components/CardFormView.d.ts +6 -0
- package/lib/typescript/src/types/index.d.ts +1 -4
- package/package.json +1 -1
- package/src/components/CardField.tsx +5 -0
- package/src/components/CardForm.tsx +6 -0
- package/src/functions.ts +1 -1
- package/src/types/PaymentSheet.ts +159 -2
- package/src/types/Token.ts +13 -1
- package/src/types/components/CardFieldInput.ts +1 -0
- package/src/types/components/CardFormView.ts +7 -0
- package/src/types/index.ts +1 -5
- package/stripe-react-native.podspec +1 -1
- package/android/src/main/java/com/reactnativestripesdk/Constants.kt +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,12 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.13.0
|
|
6
|
+
|
|
7
|
+
### Breaking changes
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
- Added a `defaultValues` prop to the `CardForm` component. Currently only accepts `countryCode`, and is Android-only. [#974](https://github.com/stripe/stripe-react-native/pull/974)
|
|
12
|
+
- Added the `countryCode` prop to the `CardField` component. [#989](https://github.com/stripe/stripe-react-native/pull/989)
|
|
13
|
+
- Added option to create a PII token (represents the details of personally identifiable information) to the `createToken` method. [#976](https://github.com/stripe/stripe-react-native/pull/976)
|
|
14
|
+
|
|
15
|
+
### Fixes
|
|
16
|
+
|
|
17
|
+
- Resolve with an Error (of type `Canceled`) if no payment option is selected in the Payment Sheet custom flow (i.e., the `x` button is clicked to close the Payment Sheet). [#975](https://github.com/stripe/stripe-react-native/pull/975)
|
|
18
|
+
- Fixed an issue on Android where the `complete` field in the `onCardChange` callback would incorrectly be set to `true` even if the postal code wasn't filled out. [#989](https://github.com/stripe/stripe-react-native/pull/989)
|
|
19
|
+
- Make `SetupIntent.lastSetupError` and `PaymentIntent.lastPaymentError` object shape consistent on iOS and Android.[#990](https://github.com/stripe/stripe-react-native/pull/990)
|
|
20
|
+
|
|
21
|
+
## 0.12.0
|
|
22
|
+
|
|
23
|
+
### Breaking changes
|
|
24
|
+
|
|
25
|
+
- Renamed `appearance.shapes.shadow.borderRadius` to `appearance.shapes.shadow.blurRadius`, and `appearance.primaryButton.shapes.shadow.borderRadius` to `appearance.primaryButton.shapes.shadow.blurRadius`. [#962](https://github.com/stripe/stripe-react-native/pull/962)
|
|
26
|
+
|
|
27
|
+
### New features
|
|
28
|
+
|
|
29
|
+
### Fixes
|
|
30
|
+
|
|
31
|
+
- Fixed cases where Android apps would crash with the error: `Unable to instantiate fragment com.reactnativestripesdk.PaymentLauncherFragment`. [#965](https://github.com/stripe/stripe-react-native/pull/965)
|
|
32
|
+
- Fixed `appearance.shapes.shadow.offset` and `appearance.primaryButton.shapes.shadow.offset` not applying the y-coordinate in the correct direction. [#962](https://github.com/stripe/stripe-react-native/pull/962)
|
|
33
|
+
- Fixed a bug where `handleNextAction` wouldn't resolve on Android when using 3DS2. [#966](https://github.com/stripe/stripe-react-native/pull/966)
|
|
34
|
+
- Fixed a bug where the wrong CVC icon was show in the `CardForm` component on Android. [#966](https://github.com/stripe/stripe-react-native/pull/966)
|
|
35
|
+
- The card brand tint color is now correctly set in the `CardField` component on Android via the `cardStyle.textColor` prop. [#851](https://github.com/stripe/stripe-react-native/pull/851)
|
|
36
|
+
|
|
37
|
+
## 0.11.0
|
|
38
|
+
|
|
5
39
|
### Breaking changes
|
|
6
40
|
|
|
41
|
+
- Removed support for `primaryButtonColor` field on `initPaymentSheet()`. Please use the new `appearance.primaryButton.colors.background` field instead. [#940](https://github.com/stripe/stripe-react-native/pull/940)
|
|
42
|
+
|
|
7
43
|
### New features
|
|
8
44
|
|
|
45
|
+
- You can now customize the appearance of your Payment Sheet via the `appearance` field on `initPaymentSheet()`. [#940](https://github.com/stripe/stripe-react-native/pull/940)
|
|
46
|
+
- Added Affirm and AU BECS Direct Debit support to Payment Sheet. [#940](https://github.com/stripe/stripe-react-native/pull/940)
|
|
47
|
+
|
|
9
48
|
### Fixes
|
|
10
49
|
|
|
50
|
+
- Improved error messages on Android for failed `confirmPayment` and `confirmSetupIntent` calls, and any Google Pay related methods. [#957](https://github.com/stripe/stripe-react-native/pull/957)
|
|
51
|
+
- Made Android card validation state consistent with iOS in the `CardField` `onCardChange` callback. [#958](https://github.com/stripe/stripe-react-native/pull/958)
|
|
52
|
+
|
|
11
53
|
## 0.10.0
|
|
12
54
|
|
|
13
55
|
### Breaking changes
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ to your `app.json` file, where `merchantIdentifier` is the Apple merchant ID obt
|
|
|
78
78
|
|
|
79
79
|
_Components_
|
|
80
80
|
|
|
81
|
-
In order to use [CardForm](https://stripe.dev/stripe-react-native/api-reference/
|
|
81
|
+
In order to use [CardForm](https://stripe.dev/stripe-react-native/api-reference/index.html#CardForm) component, you need to install and configure [Material Components theme](https://github.com/material-components/material-components-android/blob/master/docs/getting-started.md#4-change-your-app-theme-to-inherit-from-a-material-components-theme) in your app.
|
|
82
82
|
|
|
83
83
|
1. Add below dependency to your `app/build.gradle` file with specified version
|
|
84
84
|
|
|
@@ -96,7 +96,7 @@ implementation 'com.google.android.material:material:<version>'
|
|
|
96
96
|
|
|
97
97
|
#### iOS
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
The Stripe React Native SDK requires Xcode 13.2.1 or later and is compatible with apps targeting iOS 12 or above. For iOS 11 support, please use [`@stripe/stripe-react-native@0.5.0`](https://github.com/stripe/stripe-react-native/releases/tag/v0.5.0).
|
|
100
100
|
|
|
101
101
|
The SDK uses TypeScript features available in Babel version `7.9.0` and above.
|
|
102
102
|
Alternatively use the `plugin-transform-typescript` plugin in your project.
|
|
@@ -201,7 +201,7 @@ function App() {
|
|
|
201
201
|
}
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
You can find more details about the `StripeProvider` component in the [API reference](https://stripe.dev/stripe-react-native/api-reference/
|
|
204
|
+
You can find more details about the `StripeProvider` component in the [API reference](https://stripe.dev/stripe-react-native/api-reference/index.html#StripeProvider).
|
|
205
205
|
|
|
206
206
|
##### Additional steps for webhook forwarding
|
|
207
207
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
StripeSdk_kotlinVersion=1.6.10
|
|
2
|
-
StripeSdk_stripeVersion=20.
|
|
2
|
+
StripeSdk_stripeVersion=20.5.+
|
|
@@ -6,7 +6,9 @@ import android.graphics.Typeface
|
|
|
6
6
|
import android.os.Build
|
|
7
7
|
import android.text.Editable
|
|
8
8
|
import android.text.TextWatcher
|
|
9
|
+
import android.util.Log
|
|
9
10
|
import android.widget.FrameLayout
|
|
11
|
+
import androidx.core.os.LocaleListCompat
|
|
10
12
|
import com.facebook.react.bridge.ReadableMap
|
|
11
13
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
12
14
|
import com.facebook.react.uimanager.UIManagerModule
|
|
@@ -14,12 +16,16 @@ import com.facebook.react.uimanager.events.EventDispatcher
|
|
|
14
16
|
import com.google.android.material.shape.CornerFamily
|
|
15
17
|
import com.google.android.material.shape.MaterialShapeDrawable
|
|
16
18
|
import com.google.android.material.shape.ShapeAppearanceModel
|
|
19
|
+
import com.stripe.android.core.model.CountryCode
|
|
20
|
+
import com.stripe.android.core.model.CountryUtils
|
|
17
21
|
import com.stripe.android.databinding.CardInputWidgetBinding
|
|
18
22
|
import com.stripe.android.model.Address
|
|
19
23
|
import com.stripe.android.model.PaymentMethodCreateParams
|
|
20
24
|
import com.stripe.android.view.CardInputListener
|
|
21
25
|
import com.stripe.android.view.CardInputWidget
|
|
22
26
|
import com.stripe.android.view.CardValidCallback
|
|
27
|
+
import com.stripe.android.view.StripeEditText
|
|
28
|
+
import java.lang.Exception
|
|
23
29
|
|
|
24
30
|
class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
25
31
|
private var mCardWidget: CardInputWidget = CardInputWidget(context)
|
|
@@ -30,6 +36,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
30
36
|
private var mEventDispatcher: EventDispatcher? = context.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
|
|
31
37
|
private var dangerouslyGetFullCardDetails: Boolean = false
|
|
32
38
|
private var currentFocusedField: String? = null
|
|
39
|
+
private var isCardValid = false
|
|
33
40
|
|
|
34
41
|
init {
|
|
35
42
|
cardInputWidgetBinding.container.isFocusable = true
|
|
@@ -89,7 +96,8 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
89
96
|
cardInputWidgetBinding.cardNumberEditText,
|
|
90
97
|
cardInputWidgetBinding.cvcEditText,
|
|
91
98
|
cardInputWidgetBinding.expiryDateEditText,
|
|
92
|
-
cardInputWidgetBinding.postalCodeEditText
|
|
99
|
+
cardInputWidgetBinding.postalCodeEditText
|
|
100
|
+
)
|
|
93
101
|
|
|
94
102
|
textColor?.let {
|
|
95
103
|
for (editTextBinding in bindings) {
|
|
@@ -105,6 +113,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
105
113
|
for (editTextBinding in bindings) {
|
|
106
114
|
editTextBinding.setHintTextColor(Color.parseColor(it))
|
|
107
115
|
}
|
|
116
|
+
setCardBrandTint(Color.parseColor(it))
|
|
108
117
|
}
|
|
109
118
|
fontSize?.let {
|
|
110
119
|
for (editTextBinding in bindings) {
|
|
@@ -151,6 +160,19 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
151
160
|
}
|
|
152
161
|
}
|
|
153
162
|
|
|
163
|
+
private fun setCardBrandTint(color: Int) {
|
|
164
|
+
try {
|
|
165
|
+
cardInputWidgetBinding.cardBrandView::class.java.getDeclaredField("tintColorInt").let { internalTintColor ->
|
|
166
|
+
internalTintColor.isAccessible = true
|
|
167
|
+
internalTintColor.set(cardInputWidgetBinding.cardBrandView, color)
|
|
168
|
+
}
|
|
169
|
+
} catch (e: Exception) {
|
|
170
|
+
Log.e(
|
|
171
|
+
"StripeReactNative",
|
|
172
|
+
"Unable to set card brand tint color: " + e.message)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
154
176
|
fun setPlaceHolders(value: ReadableMap) {
|
|
155
177
|
val numberPlaceholder = getValOr(value, "number", null)
|
|
156
178
|
val expirationPlaceholder = getValOr(value, "expiration", null)
|
|
@@ -179,6 +201,14 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
179
201
|
mCardWidget.postalCodeEnabled = isEnabled
|
|
180
202
|
}
|
|
181
203
|
|
|
204
|
+
fun setCountryCode(countryCode: String?) {
|
|
205
|
+
val doesCountryUsePostalCode = CountryUtils.doesCountryUsePostalCode(
|
|
206
|
+
CountryCode.create(value = countryCode ?: LocaleListCompat.getAdjustedDefault()[0].country)
|
|
207
|
+
)
|
|
208
|
+
mCardWidget.postalCodeRequired = doesCountryUsePostalCode
|
|
209
|
+
mCardWidget.postalCodeEnabled = doesCountryUsePostalCode
|
|
210
|
+
}
|
|
211
|
+
|
|
182
212
|
fun getValue(): MutableMap<String, Any?> {
|
|
183
213
|
return cardDetails
|
|
184
214
|
}
|
|
@@ -206,7 +236,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
206
236
|
|
|
207
237
|
private fun sendCardDetailsEvent() {
|
|
208
238
|
mEventDispatcher?.dispatchEvent(
|
|
209
|
-
CardChangedEvent(id, cardDetails, mCardWidget.postalCodeEnabled,
|
|
239
|
+
CardChangedEvent(id, cardDetails, mCardWidget.postalCodeEnabled, isCardValid, dangerouslyGetFullCardDetails))
|
|
210
240
|
}
|
|
211
241
|
|
|
212
242
|
private fun setListeners() {
|
|
@@ -228,14 +258,25 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
228
258
|
}
|
|
229
259
|
|
|
230
260
|
mCardWidget.setCardValidCallback { isValid, invalidFields ->
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
261
|
+
isCardValid = isValid
|
|
262
|
+
fun getCardValidationState(field: CardValidCallback.Fields, editTextField: StripeEditText): String {
|
|
263
|
+
if (invalidFields.contains(field)) {
|
|
264
|
+
return if (editTextField.shouldShowError) "Invalid"
|
|
265
|
+
else "Incomplete"
|
|
266
|
+
}
|
|
267
|
+
return "Valid"
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
cardDetails["validNumber"] = getCardValidationState(CardValidCallback.Fields.Number, cardInputWidgetBinding.cardNumberEditText)
|
|
271
|
+
cardDetails["validCVC"] = getCardValidationState(CardValidCallback.Fields.Cvc, cardInputWidgetBinding.cvcEditText)
|
|
272
|
+
cardDetails["validExpiryDate"] = getCardValidationState(CardValidCallback.Fields.Expiry, cardInputWidgetBinding.expiryDateEditText)
|
|
273
|
+
|
|
234
274
|
if (isValid) {
|
|
235
275
|
onValidCardChange()
|
|
236
276
|
} else {
|
|
237
277
|
cardParams = null
|
|
238
278
|
cardAddress = null
|
|
279
|
+
sendCardDetailsEvent()
|
|
239
280
|
}
|
|
240
281
|
}
|
|
241
282
|
|
|
@@ -257,8 +298,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
257
298
|
if (splitText.size == 2) {
|
|
258
299
|
cardDetails["expiryYear"] = var1.toString().split("/")[1].toIntOrNull()
|
|
259
300
|
}
|
|
260
|
-
|
|
261
|
-
sendCardDetailsEvent()
|
|
262
301
|
}
|
|
263
302
|
})
|
|
264
303
|
|
|
@@ -267,7 +306,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
267
306
|
override fun afterTextChanged(p0: Editable?) {}
|
|
268
307
|
override fun onTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {
|
|
269
308
|
cardDetails["postalCode"] = var1.toString()
|
|
270
|
-
sendCardDetailsEvent()
|
|
271
309
|
}
|
|
272
310
|
})
|
|
273
311
|
|
|
@@ -278,7 +316,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
278
316
|
if (dangerouslyGetFullCardDetails) {
|
|
279
317
|
cardDetails["number"] = var1.toString().replace(" ", "")
|
|
280
318
|
}
|
|
281
|
-
sendCardDetailsEvent()
|
|
282
319
|
}
|
|
283
320
|
})
|
|
284
321
|
|
|
@@ -289,7 +326,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
289
326
|
if (dangerouslyGetFullCardDetails) {
|
|
290
327
|
cardDetails["cvc"] = var1.toString()
|
|
291
328
|
}
|
|
292
|
-
sendCardDetailsEvent()
|
|
293
329
|
}
|
|
294
330
|
})
|
|
295
331
|
}
|
|
@@ -51,6 +51,11 @@ class CardFieldViewManager : SimpleViewManager<CardFieldView>() {
|
|
|
51
51
|
view.setPlaceHolders(placeholders)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
@ReactProp(name = "countryCode")
|
|
55
|
+
fun setPlaceHolders(view: CardFieldView, countryCode: String?) {
|
|
56
|
+
view.setCountryCode(countryCode)
|
|
57
|
+
}
|
|
58
|
+
|
|
54
59
|
override fun createViewInstance(reactContext: ThemedReactContext): CardFieldView {
|
|
55
60
|
val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java)
|
|
56
61
|
val view = CardFieldView(reactContext)
|
|
@@ -14,6 +14,7 @@ import com.facebook.react.uimanager.events.EventDispatcher
|
|
|
14
14
|
import com.google.android.material.shape.CornerFamily
|
|
15
15
|
import com.google.android.material.shape.MaterialShapeDrawable
|
|
16
16
|
import com.google.android.material.shape.ShapeAppearanceModel
|
|
17
|
+
import com.stripe.android.core.model.CountryCode
|
|
17
18
|
import com.stripe.android.databinding.CardMultilineWidgetBinding
|
|
18
19
|
import com.stripe.android.databinding.StripeCardFormViewBinding
|
|
19
20
|
import com.stripe.android.model.Address
|
|
@@ -48,6 +49,13 @@ class CardFormView(context: ThemedReactContext) : FrameLayout(context) {
|
|
|
48
49
|
cardFormViewBinding.postalCodeContainer.visibility = visibility
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
fun setDefaultValues(defaults: ReadableMap) {
|
|
53
|
+
defaults.getString("countryCode")?.let {
|
|
54
|
+
cardFormViewBinding.countryLayout.setSelectedCountryCode(CountryCode(it))
|
|
55
|
+
cardFormViewBinding.countryLayout.updateUiForCountryEntered(CountryCode(it))
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
fun setPlaceHolders(value: ReadableMap) {
|
|
52
60
|
val numberPlaceholder = getValOr(value, "number", null)
|
|
53
61
|
val expirationPlaceholder = getValOr(value, "expiration", null)
|
|
@@ -38,7 +38,7 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
|
|
|
38
38
|
|
|
39
39
|
@ReactProp(name = "placeholders")
|
|
40
40
|
fun setPlaceHolders(view: CardFormView, placeholders: ReadableMap) {
|
|
41
|
-
view.setPlaceHolders(placeholders)
|
|
41
|
+
view.setPlaceHolders(placeholders)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
@ReactProp(name = "autofocus")
|
|
@@ -51,6 +51,11 @@ class CardFormViewManager : SimpleViewManager<CardFormView>() {
|
|
|
51
51
|
view.setCardStyle(cardStyle)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
@ReactProp(name = "defaultValues")
|
|
55
|
+
fun setDefaultValues(view: CardFormView, defaults: ReadableMap) {
|
|
56
|
+
view.setDefaultValues(defaults)
|
|
57
|
+
}
|
|
58
|
+
|
|
54
59
|
override fun createViewInstance(reactContext: ThemedReactContext): CardFormView {
|
|
55
60
|
val stripeSdkModule: StripeSdkModule? = reactContext.getNativeModule(StripeSdkModule::class.java)
|
|
56
61
|
val view = CardFormView(reactContext)
|
|
@@ -41,6 +41,8 @@ enum class GooglePayErrorType {
|
|
|
41
41
|
Failed, Canceled
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
class PaymentSheetAppearanceException(message: String) : Exception(message)
|
|
45
|
+
|
|
44
46
|
internal fun mapError(code: String, message: String?, localizedMessage: String?, declineCode: String?, type: String?, stripeErrorCode: String?): WritableMap {
|
|
45
47
|
val map: WritableMap = WritableNativeMap()
|
|
46
48
|
val details: WritableMap = WritableNativeMap()
|
|
@@ -96,5 +98,16 @@ internal fun createError(code: String, error: Exception): WritableMap {
|
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
internal fun createError(code: String, error: Throwable): WritableMap {
|
|
99
|
-
|
|
101
|
+
(error as? Exception)?.let {
|
|
102
|
+
return createError(
|
|
103
|
+
code,
|
|
104
|
+
it)
|
|
105
|
+
}
|
|
106
|
+
return mapError(
|
|
107
|
+
code,
|
|
108
|
+
error.message,
|
|
109
|
+
error.localizedMessage,
|
|
110
|
+
null,
|
|
111
|
+
null,
|
|
112
|
+
null)
|
|
100
113
|
}
|
|
@@ -1,44 +1,30 @@
|
|
|
1
1
|
package com.reactnativestripesdk
|
|
2
2
|
|
|
3
|
-
import android.content.Intent
|
|
4
3
|
import android.os.Bundle
|
|
5
4
|
import android.view.LayoutInflater
|
|
6
5
|
import android.view.View
|
|
7
6
|
import android.view.ViewGroup
|
|
8
7
|
import android.widget.FrameLayout
|
|
9
8
|
import androidx.fragment.app.Fragment
|
|
10
|
-
import
|
|
9
|
+
import com.facebook.react.bridge.Promise
|
|
10
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
11
11
|
import com.stripe.android.googlepaylauncher.GooglePayEnvironment
|
|
12
12
|
import com.stripe.android.googlepaylauncher.GooglePayLauncher
|
|
13
13
|
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
|
|
14
14
|
|
|
15
|
-
class GooglePayFragment : Fragment() {
|
|
15
|
+
class GooglePayFragment(private val initPromise: Promise) : Fragment() {
|
|
16
16
|
private var googlePayLauncher: GooglePayLauncher? = null
|
|
17
17
|
private var googlePayMethodLauncher: GooglePayPaymentMethodLauncher? = null
|
|
18
18
|
private var isGooglePayMethodLauncherReady: Boolean = false
|
|
19
19
|
private var isGooglePayLauncherReady: Boolean = false
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
private fun onGooglePayMethodLauncherReady(isReady: Boolean) {
|
|
23
|
-
isGooglePayMethodLauncherReady = true
|
|
24
|
-
if (isGooglePayLauncherReady) {
|
|
25
|
-
onGooglePayReady(isReady)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private fun onGooglePayLauncherReady(isReady: Boolean) {
|
|
30
|
-
isGooglePayLauncherReady = true
|
|
31
|
-
if (isGooglePayMethodLauncherReady) {
|
|
32
|
-
onGooglePayReady(isReady)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
20
|
+
private var presentPromise: Promise? = null
|
|
21
|
+
private var createPaymentMethodPromise: Promise? = null
|
|
35
22
|
|
|
36
23
|
override fun onCreateView(
|
|
37
24
|
inflater: LayoutInflater,
|
|
38
25
|
container: ViewGroup?,
|
|
39
26
|
savedInstanceState: Bundle?
|
|
40
27
|
): View {
|
|
41
|
-
localBroadcastManager = LocalBroadcastManager.getInstance(requireContext())
|
|
42
28
|
return FrameLayout(requireActivity()).also {
|
|
43
29
|
it.visibility = View.GONE
|
|
44
30
|
}
|
|
@@ -89,74 +75,104 @@ class GooglePayFragment : Fragment() {
|
|
|
89
75
|
)
|
|
90
76
|
}
|
|
91
77
|
|
|
92
|
-
fun
|
|
78
|
+
private fun onGooglePayMethodLauncherReady(isReady: Boolean) {
|
|
79
|
+
isGooglePayMethodLauncherReady = true
|
|
80
|
+
if (isGooglePayLauncherReady) {
|
|
81
|
+
onGooglePayReady(isReady)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private fun onGooglePayLauncherReady(isReady: Boolean) {
|
|
86
|
+
isGooglePayLauncherReady = true
|
|
87
|
+
if (isGooglePayMethodLauncherReady) {
|
|
88
|
+
onGooglePayReady(isReady)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private fun onGooglePayReady(isReady: Boolean) {
|
|
93
|
+
if (isReady) {
|
|
94
|
+
initPromise.resolve(WritableNativeMap())
|
|
95
|
+
} else {
|
|
96
|
+
initPromise.resolve(
|
|
97
|
+
createError(
|
|
98
|
+
GooglePayErrorType.Failed.toString(),
|
|
99
|
+
"Google Pay is not available on this device. You can use isGooglePaySupported to preemptively check for Google Pay support."
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fun presentForPaymentIntent(clientSecret: String, promise: Promise) {
|
|
93
106
|
val launcher = googlePayLauncher ?: run {
|
|
94
|
-
|
|
95
|
-
intent.putExtra("error", "GooglePayLauncher is not initialized.")
|
|
96
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
107
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), "GooglePay is not initialized."))
|
|
97
108
|
return
|
|
98
109
|
}
|
|
99
110
|
runCatching {
|
|
111
|
+
presentPromise = promise
|
|
100
112
|
launcher.presentForPaymentIntent(clientSecret)
|
|
101
113
|
}.onFailure {
|
|
102
|
-
|
|
103
|
-
intent.putExtra("error", it.localizedMessage)
|
|
104
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
114
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), it))
|
|
105
115
|
}
|
|
106
116
|
}
|
|
107
117
|
|
|
108
|
-
fun presentForSetupIntent(clientSecret: String, currencyCode: String) {
|
|
118
|
+
fun presentForSetupIntent(clientSecret: String, currencyCode: String, promise: Promise) {
|
|
109
119
|
val launcher = googlePayLauncher ?: run {
|
|
110
|
-
|
|
111
|
-
intent.putExtra("error", "GooglePayLauncher is not initialized.")
|
|
112
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
120
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), "GooglePay is not initialized."))
|
|
113
121
|
return
|
|
114
122
|
}
|
|
115
123
|
runCatching {
|
|
124
|
+
presentPromise = promise
|
|
116
125
|
launcher.presentForSetupIntent(clientSecret, currencyCode)
|
|
117
126
|
}.onFailure {
|
|
118
|
-
|
|
119
|
-
intent.putExtra("error", it.localizedMessage)
|
|
120
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
127
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), it))
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
fun createPaymentMethod(currencyCode: String, amount: Int) {
|
|
131
|
+
fun createPaymentMethod(currencyCode: String, amount: Int, promise: Promise) {
|
|
125
132
|
val launcher = googlePayMethodLauncher ?: run {
|
|
126
|
-
|
|
127
|
-
intent.putExtra("error", "GooglePayPaymentMethodLauncher is not initialized.")
|
|
128
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
133
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), "GooglePayPaymentMethodLauncher is not initialized."))
|
|
129
134
|
return
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
runCatching {
|
|
138
|
+
createPaymentMethodPromise = promise
|
|
133
139
|
launcher.present(
|
|
134
140
|
currencyCode = currencyCode,
|
|
135
141
|
amount = amount
|
|
136
142
|
)
|
|
137
143
|
}.onFailure {
|
|
138
|
-
|
|
139
|
-
intent.putExtra("error", it.localizedMessage)
|
|
140
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
144
|
+
promise.resolve(createError(GooglePayErrorType.Failed.toString(), it))
|
|
141
145
|
}
|
|
142
146
|
}
|
|
143
147
|
|
|
144
|
-
private fun onGooglePayReady(isReady: Boolean) {
|
|
145
|
-
val intent = Intent(ON_INIT_GOOGLE_PAY)
|
|
146
|
-
intent.putExtra("isReady", isReady)
|
|
147
|
-
localBroadcastManager.sendBroadcast(intent)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
148
|
private fun onGooglePayResult(result: GooglePayLauncher.Result) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
when (result) {
|
|
150
|
+
GooglePayLauncher.Result.Completed -> {
|
|
151
|
+
presentPromise?.resolve(WritableNativeMap())
|
|
152
|
+
}
|
|
153
|
+
GooglePayLauncher.Result.Canceled -> {
|
|
154
|
+
presentPromise?.resolve(createError(GooglePayErrorType.Canceled.toString(), "Google Pay has been canceled"))
|
|
155
|
+
}
|
|
156
|
+
is GooglePayLauncher.Result.Failed -> {
|
|
157
|
+
presentPromise?.resolve(createError(GooglePayErrorType.Failed.toString(), result.error))
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
presentPromise = null
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
private fun onGooglePayResult(result: GooglePayPaymentMethodLauncher.Result) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
when (result) {
|
|
165
|
+
is GooglePayPaymentMethodLauncher.Result.Completed -> {
|
|
166
|
+
createPaymentMethodPromise?.resolve(createResult("paymentMethod", mapFromPaymentMethod(result.paymentMethod)))
|
|
167
|
+
}
|
|
168
|
+
GooglePayPaymentMethodLauncher.Result.Canceled -> {
|
|
169
|
+
createPaymentMethodPromise?.resolve(createError(GooglePayErrorType.Canceled.toString(), "Google Pay has been canceled"))
|
|
170
|
+
}
|
|
171
|
+
is GooglePayPaymentMethodLauncher.Result.Failed -> {
|
|
172
|
+
createPaymentMethodPromise?.resolve(createError(GooglePayErrorType.Failed.toString(), result.error))
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
createPaymentMethodPromise = null
|
|
160
176
|
}
|
|
161
177
|
|
|
162
178
|
private fun mapToGooglePayLauncherBillingAddressConfig(formatString: String, isRequired: Boolean, isPhoneNumberRequired: Boolean): GooglePayLauncher.BillingAddressConfig {
|
|
@@ -402,14 +402,13 @@ internal fun mapFromPaymentIntentResult(paymentIntent: PaymentIntent): WritableM
|
|
|
402
402
|
|
|
403
403
|
paymentIntent.lastPaymentError?.let {
|
|
404
404
|
val paymentError: WritableMap = WritableNativeMap()
|
|
405
|
-
|
|
406
|
-
paymentIntent.lastPaymentError?.paymentMethod?.let { paymentMethod ->
|
|
407
|
-
paymentError.putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
408
|
-
}
|
|
409
|
-
|
|
410
405
|
paymentError.putString("code", it.code)
|
|
411
406
|
paymentError.putString("message", it.message)
|
|
412
407
|
paymentError.putString("type", mapFromPaymentIntentLastErrorType(it.type))
|
|
408
|
+
paymentError.putString("declineCode", it.declineCode)
|
|
409
|
+
paymentIntent.lastPaymentError?.paymentMethod?.let { paymentMethod ->
|
|
410
|
+
paymentError.putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
411
|
+
}
|
|
413
412
|
|
|
414
413
|
map.putMap("lastPaymentError", paymentError)
|
|
415
414
|
}
|
|
@@ -775,11 +774,10 @@ internal fun mapFromSetupIntentResult(setupIntent: SetupIntent): WritableMap {
|
|
|
775
774
|
setupError.putString("code", it.code)
|
|
776
775
|
setupError.putString("message", it.message)
|
|
777
776
|
setupError.putString("type", mapFromSetupIntentLastErrorType(it.type))
|
|
778
|
-
|
|
777
|
+
setupError.putString("declineCode", it.declineCode)
|
|
779
778
|
setupIntent.lastSetupError?.paymentMethod?.let { paymentMethod ->
|
|
780
779
|
setupError.putMap("paymentMethod", mapFromPaymentMethod(paymentMethod))
|
|
781
780
|
}
|
|
782
|
-
|
|
783
781
|
map.putMap("lastSetupError", setupError)
|
|
784
782
|
}
|
|
785
783
|
|