@stripe/stripe-react-native 0.12.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +2 -2
  3. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +15 -6
  4. package/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt +5 -0
  5. package/android/src/main/java/com/reactnativestripesdk/CardFormView.kt +8 -0
  6. package/android/src/main/java/com/reactnativestripesdk/CardFormViewManager.kt +5 -0
  7. package/android/src/main/java/com/reactnativestripesdk/Mappers.kt +5 -7
  8. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +3 -2
  9. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +18 -0
  10. package/ios/CardFieldManager.m +1 -0
  11. package/ios/CardFieldView.swift +6 -0
  12. package/ios/Mappers.swift +8 -9
  13. package/ios/StripeSdk.swift +133 -112
  14. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  15. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  16. package/lib/commonjs/components/ApplePayButton.js +1 -1
  17. package/lib/commonjs/components/ApplePayButton.js.map +1 -1
  18. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  19. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  20. package/lib/commonjs/components/CardField.js +1 -1
  21. package/lib/commonjs/components/CardField.js.map +1 -1
  22. package/lib/commonjs/components/CardForm.js +1 -1
  23. package/lib/commonjs/components/CardForm.js.map +1 -1
  24. package/lib/commonjs/components/GooglePayButton.js +1 -1
  25. package/lib/commonjs/components/GooglePayButton.js.map +1 -1
  26. package/lib/commonjs/components/StripeContainer.js +1 -1
  27. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  28. package/lib/commonjs/functions.js.map +1 -1
  29. package/lib/commonjs/types/components/CardFieldInput.js.map +1 -1
  30. package/lib/commonjs/types/index.js.map +1 -1
  31. package/lib/module/components/AddToWalletButton.js +1 -1
  32. package/lib/module/components/AddToWalletButton.js.map +1 -1
  33. package/lib/module/components/ApplePayButton.js +1 -1
  34. package/lib/module/components/ApplePayButton.js.map +1 -1
  35. package/lib/module/components/AuBECSDebitForm.js +1 -1
  36. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  37. package/lib/module/components/CardField.js +1 -1
  38. package/lib/module/components/CardField.js.map +1 -1
  39. package/lib/module/components/CardForm.js +1 -1
  40. package/lib/module/components/CardForm.js.map +1 -1
  41. package/lib/module/components/GooglePayButton.js +1 -1
  42. package/lib/module/components/GooglePayButton.js.map +1 -1
  43. package/lib/module/components/StripeContainer.js +1 -1
  44. package/lib/module/components/StripeContainer.js.map +1 -1
  45. package/lib/module/functions.js.map +1 -1
  46. package/lib/module/types/components/CardFieldInput.js.map +1 -1
  47. package/lib/module/types/index.js.map +1 -1
  48. package/lib/typescript/src/components/CardField.d.ts +3 -0
  49. package/lib/typescript/src/components/CardForm.d.ts +2 -0
  50. package/lib/typescript/src/types/Token.d.ts +9 -1
  51. package/lib/typescript/src/types/components/CardFieldInput.d.ts +1 -0
  52. package/lib/typescript/src/types/components/CardFormView.d.ts +6 -0
  53. package/lib/typescript/src/types/index.d.ts +1 -4
  54. package/package.json +1 -1
  55. package/src/components/CardField.tsx +5 -0
  56. package/src/components/CardForm.tsx +6 -0
  57. package/src/functions.ts +1 -1
  58. package/src/types/Token.ts +13 -1
  59. package/src/types/components/CardFieldInput.ts +1 -0
  60. package/src/types/components/CardFormView.ts +7 -0
  61. package/src/types/index.ts +1 -5
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
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
+
5
21
  ## 0.12.0
6
22
 
7
23
  ### 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/modules.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.
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
 
@@ -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/modules.html#stripeprovider).
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
 
@@ -8,6 +8,7 @@ import android.text.Editable
8
8
  import android.text.TextWatcher
9
9
  import android.util.Log
10
10
  import android.widget.FrameLayout
11
+ import androidx.core.os.LocaleListCompat
11
12
  import com.facebook.react.bridge.ReadableMap
12
13
  import com.facebook.react.uimanager.ThemedReactContext
13
14
  import com.facebook.react.uimanager.UIManagerModule
@@ -15,6 +16,8 @@ import com.facebook.react.uimanager.events.EventDispatcher
15
16
  import com.google.android.material.shape.CornerFamily
16
17
  import com.google.android.material.shape.MaterialShapeDrawable
17
18
  import com.google.android.material.shape.ShapeAppearanceModel
19
+ import com.stripe.android.core.model.CountryCode
20
+ import com.stripe.android.core.model.CountryUtils
18
21
  import com.stripe.android.databinding.CardInputWidgetBinding
19
22
  import com.stripe.android.model.Address
20
23
  import com.stripe.android.model.PaymentMethodCreateParams
@@ -33,6 +36,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
33
36
  private var mEventDispatcher: EventDispatcher? = context.getNativeModule(UIManagerModule::class.java)?.eventDispatcher
34
37
  private var dangerouslyGetFullCardDetails: Boolean = false
35
38
  private var currentFocusedField: String? = null
39
+ private var isCardValid = false
36
40
 
37
41
  init {
38
42
  cardInputWidgetBinding.container.isFocusable = true
@@ -197,6 +201,14 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
197
201
  mCardWidget.postalCodeEnabled = isEnabled
198
202
  }
199
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
+
200
212
  fun getValue(): MutableMap<String, Any?> {
201
213
  return cardDetails
202
214
  }
@@ -224,7 +236,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
224
236
 
225
237
  private fun sendCardDetailsEvent() {
226
238
  mEventDispatcher?.dispatchEvent(
227
- CardChangedEvent(id, cardDetails, mCardWidget.postalCodeEnabled, cardParams != null, dangerouslyGetFullCardDetails))
239
+ CardChangedEvent(id, cardDetails, mCardWidget.postalCodeEnabled, isCardValid, dangerouslyGetFullCardDetails))
228
240
  }
229
241
 
230
242
  private fun setListeners() {
@@ -246,6 +258,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
246
258
  }
247
259
 
248
260
  mCardWidget.setCardValidCallback { isValid, invalidFields ->
261
+ isCardValid = isValid
249
262
  fun getCardValidationState(field: CardValidCallback.Fields, editTextField: StripeEditText): String {
250
263
  if (invalidFields.contains(field)) {
251
264
  return if (editTextField.shouldShowError) "Invalid"
@@ -263,6 +276,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
263
276
  } else {
264
277
  cardParams = null
265
278
  cardAddress = null
279
+ sendCardDetailsEvent()
266
280
  }
267
281
  }
268
282
 
@@ -284,8 +298,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
284
298
  if (splitText.size == 2) {
285
299
  cardDetails["expiryYear"] = var1.toString().split("/")[1].toIntOrNull()
286
300
  }
287
-
288
- sendCardDetailsEvent()
289
301
  }
290
302
  })
291
303
 
@@ -294,7 +306,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
294
306
  override fun afterTextChanged(p0: Editable?) {}
295
307
  override fun onTextChanged(var1: CharSequence?, var2: Int, var3: Int, var4: Int) {
296
308
  cardDetails["postalCode"] = var1.toString()
297
- sendCardDetailsEvent()
298
309
  }
299
310
  })
300
311
 
@@ -305,7 +316,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
305
316
  if (dangerouslyGetFullCardDetails) {
306
317
  cardDetails["number"] = var1.toString().replace(" ", "")
307
318
  }
308
- sendCardDetailsEvent()
309
319
  }
310
320
  })
311
321
 
@@ -316,7 +326,6 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
316
326
  if (dangerouslyGetFullCardDetails) {
317
327
  cardDetails["cvc"] = var1.toString()
318
328
  }
319
- sendCardDetailsEvent()
320
329
  }
321
330
  })
322
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)
@@ -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)
@@ -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
 
@@ -74,14 +74,15 @@ class PaymentSheetFragment(
74
74
  option.putString("label", paymentOption.label)
75
75
  option.putString("image", imageString)
76
76
  presentPromise?.resolve(createResult("paymentOption", option))
77
+ } else {
78
+ presentPromise?.resolve(createError(PaymentSheetErrorType.Canceled.toString(), "The payment option selection flow has been canceled"))
77
79
  }
78
- presentPromise?.resolve(WritableNativeMap())
79
80
  }
80
81
 
81
82
  val paymentResultCallback = PaymentSheetResultCallback { paymentResult ->
82
83
  when (paymentResult) {
83
84
  is PaymentSheetResult.Canceled -> {
84
- val message = "The payment has been canceled"
85
+ val message = "The payment flow has been canceled"
85
86
  confirmPromise?.resolve(createError(PaymentSheetErrorType.Canceled.toString(), message))
86
87
  ?: run {
87
88
  presentPromise?.resolve(createError(PaymentSheetErrorType.Canceled.toString(), message))
@@ -222,12 +222,30 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
222
222
  "Card" -> {
223
223
  createTokenFromCard(params, promise)
224
224
  }
225
+ "Pii" -> {
226
+ createTokenFromPii(params, promise)
227
+ }
225
228
  else -> {
226
229
  promise.resolve(createError(CreateTokenErrorType.Failed.toString(), "$type type is not supported yet"))
227
230
  }
228
231
  }
229
232
  }
230
233
 
234
+ private fun createTokenFromPii(params: ReadableMap, promise: Promise) {
235
+ getValOr(params, "personalId", null)?.let {
236
+ CoroutineScope(Dispatchers.IO).launch {
237
+ runCatching {
238
+ val token = stripe.createPiiToken(it, null, stripeAccountId)
239
+ promise.resolve(createResult("token", mapFromToken(token)))
240
+ }.onFailure {
241
+ promise.resolve(createError(CreateTokenErrorType.Failed.toString(), it.message))
242
+ }
243
+ }
244
+ } ?: run {
245
+ promise.resolve(createError(CreateTokenErrorType.Failed.toString(), "personalId parameter is required"))
246
+ }
247
+ }
248
+
231
249
  private fun createTokenFromBankAccount(params: ReadableMap, promise: Promise) {
232
250
  val accountHolderName = getValOr(params, "accountHolderName", null)
233
251
  val accountHolderType = getValOr(params, "accountHolderType", null)
@@ -4,6 +4,7 @@
4
4
 
5
5
  @interface RCT_EXTERN_MODULE(CardFieldManager, RCTViewManager)
6
6
  RCT_EXPORT_VIEW_PROPERTY(postalCodeEnabled, BOOL)
7
+ RCT_EXPORT_VIEW_PROPERTY(countryCode, NSString)
7
8
  RCT_EXPORT_VIEW_PROPERTY(onCardChange, RCTDirectEventBlock)
8
9
  RCT_EXPORT_VIEW_PROPERTY(onFocusChange, RCTDirectEventBlock)
9
10
  RCT_EXPORT_VIEW_PROPERTY(cardStyle, NSDictionary)
@@ -18,6 +18,12 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate {
18
18
  }
19
19
  }
20
20
 
21
+ @objc var countryCode: String? {
22
+ didSet {
23
+ cardField.countryCode = countryCode
24
+ }
25
+ }
26
+
21
27
  @objc var placeholders: NSDictionary = NSDictionary() {
22
28
  didSet {
23
29
  if let numberPlaceholder = placeholders["number"] as? String {
package/ios/Mappers.swift CHANGED
@@ -157,7 +157,6 @@ class Mappers {
157
157
  "card": mapFromCard(token.card) ?? NSNull(),
158
158
  "livemode": token.livemode,
159
159
  "type": mapFromTokenType(token.type) ?? NSNull(),
160
-
161
160
  ]
162
161
 
163
162
  return tokenMap
@@ -498,7 +497,7 @@ class Mappers {
498
497
  billing.name = RCTConvert.nsString(billingDetails["name"])
499
498
 
500
499
  let address = STPPaymentMethodAddress()
501
-
500
+
502
501
  if let addressMap = billingDetails["address"] as? NSDictionary {
503
502
  address.city = RCTConvert.nsString(addressMap["city"])
504
503
  address.postalCode = RCTConvert.nsString(addressMap["postalCode"])
@@ -507,7 +506,7 @@ class Mappers {
507
506
  address.line2 = RCTConvert.nsString(addressMap["line2"])
508
507
  address.state = RCTConvert.nsString(addressMap["state"])
509
508
  }
510
-
509
+
511
510
  billing.address = address
512
511
 
513
512
  return billing
@@ -517,7 +516,7 @@ class Mappers {
517
516
  guard let shippingDetails = shippingDetails else {
518
517
  return nil
519
518
  }
520
-
519
+
521
520
  let shippingAddress = STPPaymentIntentShippingDetailsAddressParams(line1: "")
522
521
 
523
522
  if let addressMap = shippingDetails["address"] as? NSDictionary {
@@ -528,7 +527,7 @@ class Mappers {
528
527
  shippingAddress.line2 = addressMap["line2"] as? String
529
528
  shippingAddress.state = addressMap["state"] as? String
530
529
  }
531
-
530
+
532
531
  let shipping = STPPaymentIntentShippingDetailsParams(address: shippingAddress, name: shippingDetails["name"] as? String ?? "")
533
532
 
534
533
  return shipping
@@ -568,7 +567,7 @@ class Mappers {
568
567
  }
569
568
  return nil
570
569
  }
571
-
570
+
572
571
  class func mapToCardBrand(_ brand: String?) -> STPCardBrand {
573
572
  if let brand = brand {
574
573
  switch brand {
@@ -722,7 +721,7 @@ class Mappers {
722
721
  if let lastSetupError = setupIntent.lastSetupError {
723
722
  let setupError: NSMutableDictionary = [
724
723
  "code": lastSetupError.code ?? NSNull(),
725
- "message": lastSetupError.description,
724
+ "message": lastSetupError.message ?? NSNull(),
726
725
  "type": mapFromSetupIntentLastPaymentErrorType(lastSetupError.type) ?? NSNull(),
727
726
  "declineCode": lastSetupError.declineCode ?? NSNull(),
728
727
  "paymentMethod": mapFromPaymentMethod(lastSetupError.paymentMethod) ?? NSNull()
@@ -962,7 +961,7 @@ class Mappers {
962
961
  }
963
962
  return "Unknown"
964
963
  }
965
-
964
+
966
965
  class func mapToUSBankAccountHolderType(type: String?) -> STPPaymentMethodUSBankAccountHolderType {
967
966
  switch type {
968
967
  case "Company": return STPPaymentMethodUSBankAccountHolderType.company
@@ -981,7 +980,7 @@ class Mappers {
981
980
  }
982
981
  return "Unknown"
983
982
  }
984
-
983
+
985
984
  class func mapToUSBankAccountType(type: String?) -> STPPaymentMethodUSBankAccountType {
986
985
  switch type {
987
986
  case "Savings": return STPPaymentMethodUSBankAccountType.savings