@stripe/stripe-react-native 0.12.0 → 0.14.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 (116) hide show
  1. package/CHANGELOG.md +51 -9
  2. package/README.md +2 -2
  3. package/android/.DS_Store +0 -0
  4. package/android/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  5. package/android/.gradle/7.1/dependencies-accessors/gc.properties +0 -0
  6. package/android/.gradle/7.1/fileChanges/last-build.bin +0 -0
  7. package/android/.gradle/7.1/fileHashes/fileHashes.lock +0 -0
  8. package/android/.gradle/7.1/gc.properties +0 -0
  9. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  10. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  11. package/android/.gradle/checksums/checksums.lock +0 -0
  12. package/android/.gradle/vcs-1/gc.properties +0 -0
  13. package/android/.idea/.gitignore +3 -0
  14. package/android/.idea/gradle.xml +13 -0
  15. package/android/.idea/misc.xml +9 -0
  16. package/android/.idea/modules/android.iml +18 -0
  17. package/android/.idea/modules.xml +8 -0
  18. package/android/.idea/vcs.xml +6 -0
  19. package/android/.idea/workspace.xml +52 -0
  20. package/android/build.gradle +11 -0
  21. package/android/local.properties +8 -0
  22. package/android/src/.DS_Store +0 -0
  23. package/android/src/androidTest/.DS_Store +0 -0
  24. package/android/src/androidTest/java/com/reactnativestripesdk/pushprovisioning/PushProvisioningProxyTest.kt +35 -0
  25. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +21 -6
  26. package/android/src/main/java/com/reactnativestripesdk/CardFieldViewManager.kt +5 -0
  27. package/android/src/main/java/com/reactnativestripesdk/CardFormView.kt +8 -0
  28. package/android/src/main/java/com/reactnativestripesdk/CardFormViewManager.kt +5 -0
  29. package/android/src/main/java/com/reactnativestripesdk/Mappers.kt +21 -7
  30. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +9 -3
  31. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +59 -2
  32. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt +0 -1
  33. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/PushProvisioningProxy.kt +19 -7
  34. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/TapAndPayProxy.kt +45 -38
  35. package/ios/.DS_Store +0 -0
  36. package/ios/CardFieldManager.m +1 -0
  37. package/ios/CardFieldView.swift +17 -8
  38. package/ios/Mappers.swift +8 -9
  39. package/ios/StripeSdk.m +5 -0
  40. package/ios/StripeSdk.swift +151 -119
  41. package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  42. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  43. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/charliecruzan.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  44. package/ios/StripeSdk.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +52 -0
  45. package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +22 -0
  46. package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
  47. package/ios/Tests/PushProvisioningTests.swift +49 -0
  48. package/ios/pushprovisioning/AddToWalletButtonView.swift +1 -5
  49. package/ios/pushprovisioning/PushProvisioningUtils.swift +64 -0
  50. package/lib/commonjs/NativeStripeSdk.js.map +1 -1
  51. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  52. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  53. package/lib/commonjs/components/ApplePayButton.js +1 -1
  54. package/lib/commonjs/components/ApplePayButton.js.map +1 -1
  55. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  56. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  57. package/lib/commonjs/components/CardField.js +1 -1
  58. package/lib/commonjs/components/CardField.js.map +1 -1
  59. package/lib/commonjs/components/CardForm.js +1 -1
  60. package/lib/commonjs/components/CardForm.js.map +1 -1
  61. package/lib/commonjs/components/GooglePayButton.js +1 -1
  62. package/lib/commonjs/components/GooglePayButton.js.map +1 -1
  63. package/lib/commonjs/components/StripeContainer.js +1 -1
  64. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  65. package/lib/commonjs/functions.js +1 -1
  66. package/lib/commonjs/functions.js.map +1 -1
  67. package/lib/commonjs/hooks/useStripe.js +1 -1
  68. package/lib/commonjs/hooks/useStripe.js.map +1 -1
  69. package/lib/commonjs/types/components/CardFieldInput.js.map +1 -1
  70. package/lib/commonjs/types/index.js.map +1 -1
  71. package/lib/module/NativeStripeSdk.js.map +1 -1
  72. package/lib/module/components/AddToWalletButton.js +1 -1
  73. package/lib/module/components/AddToWalletButton.js.map +1 -1
  74. package/lib/module/components/ApplePayButton.js +1 -1
  75. package/lib/module/components/ApplePayButton.js.map +1 -1
  76. package/lib/module/components/AuBECSDebitForm.js +1 -1
  77. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  78. package/lib/module/components/CardField.js +1 -1
  79. package/lib/module/components/CardField.js.map +1 -1
  80. package/lib/module/components/CardForm.js +1 -1
  81. package/lib/module/components/CardForm.js.map +1 -1
  82. package/lib/module/components/GooglePayButton.js +1 -1
  83. package/lib/module/components/GooglePayButton.js.map +1 -1
  84. package/lib/module/components/StripeContainer.js +1 -1
  85. package/lib/module/components/StripeContainer.js.map +1 -1
  86. package/lib/module/functions.js +1 -1
  87. package/lib/module/functions.js.map +1 -1
  88. package/lib/module/hooks/useStripe.js +1 -1
  89. package/lib/module/hooks/useStripe.js.map +1 -1
  90. package/lib/module/types/components/CardFieldInput.js.map +1 -1
  91. package/lib/module/types/index.js.map +1 -1
  92. package/lib/typescript/e2e/screenObject/BasicPaymentScreen.d.ts +1 -2
  93. package/lib/typescript/src/NativeStripeSdk.d.ts +2 -1
  94. package/lib/typescript/src/components/AddToWalletButton.d.ts +1 -1
  95. package/lib/typescript/src/components/CardField.d.ts +3 -0
  96. package/lib/typescript/src/components/CardForm.d.ts +2 -0
  97. package/lib/typescript/src/functions.d.ts +2 -1
  98. package/lib/typescript/src/hooks/useStripe.d.ts +2 -1
  99. package/lib/typescript/src/types/PaymentSheet.d.ts +2 -1
  100. package/lib/typescript/src/types/Token.d.ts +9 -1
  101. package/lib/typescript/src/types/components/CardFieldInput.d.ts +1 -0
  102. package/lib/typescript/src/types/components/CardFormView.d.ts +6 -0
  103. package/lib/typescript/src/types/index.d.ts +21 -4
  104. package/package.json +6 -4
  105. package/src/NativeStripeSdk.tsx +5 -0
  106. package/src/components/AddToWalletButton.tsx +1 -1
  107. package/src/components/CardField.tsx +5 -0
  108. package/src/components/CardForm.tsx +6 -0
  109. package/src/functions.ts +26 -1
  110. package/src/hooks/useStripe.tsx +13 -0
  111. package/src/types/PaymentSheet.ts +2 -1
  112. package/src/types/Token.ts +13 -1
  113. package/src/types/components/CardFieldInput.ts +1 -0
  114. package/src/types/components/CardFormView.ts +7 -0
  115. package/src/types/index.ts +28 -5
  116. package/stripe-react-native.podspec +6 -1
@@ -7,9 +7,10 @@ import android.util.Log
7
7
  import androidx.appcompat.app.AppCompatActivity
8
8
  import com.facebook.react.bridge.*
9
9
  import com.facebook.react.module.annotations.ReactModule
10
+ import com.reactnativestripesdk.pushprovisioning.PushProvisioningProxy
10
11
  import com.stripe.android.*
11
- import com.stripe.android.core.AppInfo
12
12
  import com.stripe.android.core.ApiVersion
13
+ import com.stripe.android.core.AppInfo
13
14
  import com.stripe.android.model.*
14
15
  import com.stripe.android.payments.bankaccount.CollectBankAccountConfiguration
15
16
  import com.stripe.android.view.AddPaymentMethodActivityStarter
@@ -17,6 +18,7 @@ import kotlinx.coroutines.CoroutineScope
17
18
  import kotlinx.coroutines.Dispatchers
18
19
  import kotlinx.coroutines.launch
19
20
 
21
+
20
22
  @ReactModule(name = StripeSdkModule.NAME)
21
23
  class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
22
24
  override fun getName(): String {
@@ -116,6 +118,10 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
116
118
  @ReactMethod
117
119
  fun initPaymentSheet(params: ReadableMap, promise: Promise) {
118
120
  getCurrentActivityOrResolveWithError(promise)?.let { activity ->
121
+ paymentSheetFragment?.let {
122
+ // If a payment sheet was already initialized, we want to remove its fragment first
123
+ activity.supportFragmentManager.beginTransaction().remove(it).commitAllowingStateLoss()
124
+ }
119
125
  paymentSheetFragment = PaymentSheetFragment(reactApplicationContext, promise).also {
120
126
  val bundle = toBundleObject(params)
121
127
  it.arguments = bundle
@@ -222,12 +228,30 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
222
228
  "Card" -> {
223
229
  createTokenFromCard(params, promise)
224
230
  }
231
+ "Pii" -> {
232
+ createTokenFromPii(params, promise)
233
+ }
225
234
  else -> {
226
235
  promise.resolve(createError(CreateTokenErrorType.Failed.toString(), "$type type is not supported yet"))
227
236
  }
228
237
  }
229
238
  }
230
239
 
240
+ private fun createTokenFromPii(params: ReadableMap, promise: Promise) {
241
+ getValOr(params, "personalId", null)?.let {
242
+ CoroutineScope(Dispatchers.IO).launch {
243
+ runCatching {
244
+ val token = stripe.createPiiToken(it, null, stripeAccountId)
245
+ promise.resolve(createResult("token", mapFromToken(token)))
246
+ }.onFailure {
247
+ promise.resolve(createError(CreateTokenErrorType.Failed.toString(), it.message))
248
+ }
249
+ }
250
+ } ?: run {
251
+ promise.resolve(createError(CreateTokenErrorType.Failed.toString(), "personalId parameter is required"))
252
+ }
253
+ }
254
+
231
255
  private fun createTokenFromBankAccount(params: ReadableMap, promise: Promise) {
232
256
  val accountHolderName = getValOr(params, "accountHolderName", null)
233
257
  val accountHolderType = getValOr(params, "accountHolderType", null)
@@ -507,6 +531,30 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
507
531
  googlePayFragment?.createPaymentMethod(currencyCode, amount, promise)
508
532
  }
509
533
 
534
+ @ReactMethod
535
+ fun canAddCardToWallet(params: ReadableMap, promise: Promise) {
536
+ val last4 = getValOr(params, "cardLastFour", null) ?: run {
537
+ promise.resolve(createError("Failed", "You must provide cardLastFour"))
538
+ return
539
+ }
540
+
541
+ if (!PushProvisioningProxy.isNFCEnabled(reactApplicationContext)) {
542
+ promise.resolve(createCanAddCardResult(false, "UNSUPPORTED_DEVICE"))
543
+ return
544
+ }
545
+
546
+ getCurrentActivityOrResolveWithError(promise)?.let {
547
+ PushProvisioningProxy.isCardInWallet(it, last4) { isCardInWallet, token, error ->
548
+ if (error != null) {
549
+ promise.resolve(createCanAddCardResult(false, "MISSING_CONFIGURATION", null))
550
+ } else {
551
+ val status = if (isCardInWallet) "CARD_ALREADY_EXISTS" else null
552
+ promise.resolve(createCanAddCardResult(!isCardInWallet, status, token))
553
+ }
554
+ }
555
+ }
556
+ }
557
+
510
558
  @ReactMethod
511
559
  fun isCardInWallet(params: ReadableMap, promise: Promise) {
512
560
  val last4 = getValOr(params, "cardLastFour", null) ?: run {
@@ -514,7 +562,16 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
514
562
  return
515
563
  }
516
564
  getCurrentActivityOrResolveWithError(promise)?.let {
517
- PushProvisioningProxy.isCardInWallet(it, last4, promise)
565
+ PushProvisioningProxy.isCardInWallet(it, last4) { isCardInWallet, token, error ->
566
+ if (error != null) {
567
+ promise.resolve(error)
568
+ } else {
569
+ val result = WritableNativeMap()
570
+ result.putBoolean("isInWallet", isCardInWallet)
571
+ result.putMap("token", token)
572
+ promise.resolve(result)
573
+ }
574
+ }
518
575
  }
519
576
  }
520
577
 
@@ -17,7 +17,6 @@ import com.facebook.react.bridge.WritableMap
17
17
  import com.facebook.react.uimanager.ThemedReactContext
18
18
  import com.facebook.react.uimanager.UIManagerModule
19
19
  import com.facebook.react.uimanager.events.EventDispatcher
20
- import com.reactnativestripesdk.PushProvisioningProxy
21
20
  import com.reactnativestripesdk.createError
22
21
 
23
22
 
@@ -1,13 +1,16 @@
1
- package com.reactnativestripesdk
1
+ package com.reactnativestripesdk.pushprovisioning
2
2
 
3
3
  import android.app.Activity
4
4
  import android.app.Activity.RESULT_OK
5
5
  import android.content.Intent
6
+ import android.content.pm.PackageManager
7
+ import android.nfc.NfcAdapter
6
8
  import android.util.Log
7
- import com.facebook.react.bridge.*
8
- import com.reactnativestripesdk.pushprovisioning.AddToWalletButtonView
9
- import com.reactnativestripesdk.pushprovisioning.EphemeralKeyProvider
10
- import com.reactnativestripesdk.pushprovisioning.TapAndPayProxy
9
+ import com.facebook.react.bridge.BaseActivityEventListener
10
+ import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReadableMap
12
+ import com.reactnativestripesdk.createError
13
+ import com.reactnativestripesdk.mapError
11
14
  import com.stripe.android.pushProvisioning.PushProvisioningActivity
12
15
  import com.stripe.android.pushProvisioning.PushProvisioningActivityStarter
13
16
 
@@ -27,6 +30,15 @@ object PushProvisioningProxy {
27
30
  }
28
31
  }
29
32
 
33
+ fun isNFCEnabled(context: ReactApplicationContext): Boolean {
34
+ return if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
35
+ val adapter = NfcAdapter.getDefaultAdapter(context)
36
+ adapter.isEnabled
37
+ } else {
38
+ false
39
+ }
40
+ }
41
+
30
42
  fun invoke(
31
43
  context: ReactApplicationContext,
32
44
  view: AddToWalletButtonView,
@@ -57,8 +69,8 @@ object PushProvisioningProxy {
57
69
  }
58
70
  }
59
71
 
60
- fun isCardInWallet(activity: Activity, cardLastFour: String, promise: Promise) {
61
- TapAndPayProxy.invoke(activity, cardLastFour, promise)
72
+ fun isCardInWallet(activity: Activity, cardLastFour: String, callback: TokenCheckHandler) {
73
+ TapAndPayProxy.findExistingToken(activity, cardLastFour, callback)
62
74
  }
63
75
 
64
76
  private fun createActivityEventListener(context: ReactApplicationContext, view: AddToWalletButtonView) {
@@ -2,54 +2,68 @@ package com.reactnativestripesdk.pushprovisioning
2
2
 
3
3
  import android.app.Activity
4
4
  import android.util.Log
5
- import com.facebook.react.bridge.Promise
6
5
  import com.facebook.react.bridge.ReadableMap
7
6
  import com.facebook.react.bridge.WritableMap
8
7
  import com.facebook.react.bridge.WritableNativeMap
9
8
  import com.reactnativestripesdk.createError
10
9
  import com.google.android.gms.tasks.Task
11
10
 
11
+ typealias TokenCheckHandler = (isCardInWallet: Boolean, token: WritableMap?, error: WritableMap?) -> Unit
12
+
12
13
  object TapAndPayProxy {
13
14
  private const val TAG = "StripeTapAndPay"
14
15
  private var tapAndPayClient: Any? = null
15
16
  const val REQUEST_CODE_TOKENIZE = 90909
16
17
 
17
- fun invoke(activity: Activity, newCardLastFour: String, promise: Promise) {
18
- try {
18
+ private fun getTapandPayTokens(activity: Activity): Task<List<Any>>? {
19
+ return try {
19
20
  val tapAndPayClass = Class.forName("com.google.android.gms.tapandpay.TapAndPay")
20
- val getClientMethod = tapAndPayClass.getMethod("getClient", Activity::class.java)
21
+ val getClientMethod = tapAndPayClass.getMethod(
22
+ "getClient",
23
+ Activity::class.java)
24
+ val client = getClientMethod.invoke(null, activity)
21
25
 
22
- tapAndPayClient = getClientMethod.invoke(null, activity).also {
23
- val tapAndPayClientClass = Class.forName("com.google.android.gms.tapandpay.TapAndPayClient")
24
- val listTokensMethod = tapAndPayClientClass.getMethod("listTokens")
26
+ val tapAndPayClientClass = Class.forName("com.google.android.gms.tapandpay.TapAndPayClient")
27
+ val listTokensMethod = tapAndPayClientClass.getMethod("listTokens")
25
28
 
26
- val tokens = listTokensMethod.invoke(it) as Task<List<Any>>
27
- tokens.addOnCompleteListener { task ->
28
- if (task.isSuccessful) {
29
- for (token in task.result) {
30
- try {
31
- val getFpanLastFourMethod = Class.forName("com.google.android.gms.tapandpay.issuer.TokenInfo").getMethod("getFpanLastFour")
32
- val existingFpanLastFour = getFpanLastFourMethod.invoke(token) as String
33
- if (existingFpanLastFour == newCardLastFour) {
34
- promise.resolve(
35
- createResult(
36
- true,
37
- token))
38
- return@addOnCompleteListener
39
- }
40
- } catch (e: Exception) {
41
- Log.e(TAG, "There was a problem finding the class com.google.android.gms.tapandpay.issuer.TokenInfo. Make sure you've included Google's TapAndPay dependency.")
42
- }
43
- }
44
- } else {
45
- Log.e(TAG, "Unable to fetch existing tokens from Google TapAndPay.")
29
+ listTokensMethod.invoke(client) as Task<List<Any>>
30
+ } catch (e: Exception) {
31
+ Log.e(TAG, "Google TapAndPay dependency not found")
32
+ null
33
+ }
34
+ }
35
+
36
+ internal fun isTokenInWallet(token: Any, newLastFour: String): Boolean {
37
+ return try {
38
+ val getFpanLastFourMethod = Class.forName("com.google.android.gms.tapandpay.issuer.TokenInfo").getMethod("getFpanLastFour")
39
+ val existingFpanLastFour = getFpanLastFourMethod.invoke(token) as String
40
+ existingFpanLastFour == newLastFour
41
+ } catch (e: Exception) {
42
+ Log.e(TAG, "There was a problem finding the class com.google.android.gms.tapandpay.issuer.TokenInfo. Make sure you've included Google's TapAndPay dependency.")
43
+ false
44
+ }
45
+ }
46
+
47
+
48
+ fun findExistingToken(activity: Activity, newCardLastFour: String, callback: TokenCheckHandler) {
49
+ val tokens = getTapandPayTokens(activity)
50
+ if (tokens == null) {
51
+ callback(false, null, createError("Failed", "Google TapAndPay dependency not found."))
52
+ return
53
+ }
54
+
55
+ tokens.addOnCompleteListener { task ->
56
+ if (task.isSuccessful) {
57
+ for (token in task.result) {
58
+ if (isTokenInWallet(token, newCardLastFour)) {
59
+ callback(true, mapFromTokenInfo(token), null)
60
+ return@addOnCompleteListener
46
61
  }
47
- promise.resolve(createResult(false))
48
62
  }
63
+ } else {
64
+ Log.e(TAG, "Unable to fetch existing tokens from Google TapAndPay.")
49
65
  }
50
- } catch (e: Exception) {
51
- Log.e(TAG, "Google TapAndPay dependency not found")
52
- promise.resolve(createError("Failed", "Google TapAndPay dependency not found."))
66
+ callback(false, null, null)
53
67
  }
54
68
  }
55
69
 
@@ -69,13 +83,6 @@ object TapAndPayProxy {
69
83
  }
70
84
  }
71
85
 
72
- private fun createResult(cardIsInWallet: Boolean, token: Any? = null): WritableMap {
73
- val result = WritableNativeMap()
74
- result.putBoolean("isInWallet", cardIsInWallet)
75
- result.putMap("token", mapFromTokenInfo(token))
76
- return result
77
- }
78
-
79
86
  private fun mapFromTokenInfo(token: Any?): WritableMap? {
80
87
  if (token == null) {
81
88
  return null
package/ios/.DS_Store ADDED
Binary file
@@ -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 {
@@ -126,13 +132,16 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate {
126
132
 
127
133
  func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {
128
134
  if onCardChange != nil {
129
- let brand = STPCardValidator.brand(forNumber: textField.cardParams.number ?? "")
130
- let validExpiryDate = STPCardValidator.validationState(forExpirationYear: textField.cardParams.expYear?.stringValue ?? "", inMonth: textField.cardParams.expMonth?.stringValue ?? "")
131
- let validCVC = STPCardValidator.validationState(forCVC: textField.cardParams.cvc ?? "", cardBrand: brand)
132
- let validNumber = STPCardValidator.validationState(forNumber: textField.cardParams.number ?? "", validatingCardBrand: true)
135
+ let brand = STPCardValidator.brand(forNumber: textField.cardNumber ?? "")
136
+ let validExpiryDate = STPCardValidator.validationState(
137
+ forExpirationYear: textField.formattedExpirationYear ?? "",
138
+ inMonth: textField.formattedExpirationMonth ?? ""
139
+ )
140
+ let validCVC = STPCardValidator.validationState(forCVC: textField.cvc ?? "", cardBrand: brand)
141
+ let validNumber = STPCardValidator.validationState(forNumber: textField.cardNumber ?? "", validatingCardBrand: true)
133
142
  var cardData: [String: Any?] = [
134
- "expiryMonth": textField.cardParams.expMonth ?? NSNull(),
135
- "expiryYear": textField.cardParams.expYear ?? NSNull(),
143
+ "expiryMonth": textField.expirationMonth,
144
+ "expiryYear": textField.expirationYear,
136
145
  "complete": textField.isValid,
137
146
  "brand": Mappers.mapFromCardBrand(brand) ?? NSNull(),
138
147
  "last4": textField.cardParams.last4 ?? "",
@@ -144,8 +153,8 @@ class CardFieldView: UIView, STPPaymentCardTextFieldDelegate {
144
153
  cardData["postalCode"] = textField.postalCode ?? ""
145
154
  }
146
155
  if (dangerouslyGetFullCardDetails) {
147
- cardData["number"] = textField.cardParams.number ?? ""
148
- cardData["cvc"] = textField.cardParams.cvc ?? ""
156
+ cardData["number"] = textField.cardNumber ?? ""
157
+ cardData["cvc"] = textField.cvc ?? ""
149
158
  }
150
159
  onCardChange!(cardData as [AnyHashable : Any])
151
160
  }
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
package/ios/StripeSdk.m CHANGED
@@ -121,6 +121,11 @@ RCT_EXTERN_METHOD(
121
121
  resolver: (RCTPromiseResolveBlock)resolve
122
122
  rejecter: (RCTPromiseRejectBlock)reject
123
123
  )
124
+ RCT_EXTERN_METHOD(
125
+ canAddCardToWallet:(NSDictionary *)params
126
+ resolver: (RCTPromiseResolveBlock)resolve
127
+ rejecter: (RCTPromiseRejectBlock)reject
128
+ )
124
129
  RCT_EXTERN_METHOD(
125
130
  isCardInWallet:(NSDictionary *)params
126
131
  resolver: (RCTPromiseResolveBlock)resolve