@stripe/stripe-react-native 0.13.1 → 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 (98) hide show
  1. package/CHANGELOG.md +27 -11
  2. package/android/.DS_Store +0 -0
  3. package/android/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  4. package/android/.gradle/7.1/dependencies-accessors/gc.properties +0 -0
  5. package/android/.gradle/7.1/fileChanges/last-build.bin +0 -0
  6. package/android/.gradle/7.1/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/7.1/gc.properties +0 -0
  8. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  9. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  10. package/android/.gradle/checksums/checksums.lock +0 -0
  11. package/android/.gradle/vcs-1/gc.properties +0 -0
  12. package/android/.idea/.gitignore +3 -0
  13. package/android/.idea/gradle.xml +13 -0
  14. package/android/.idea/misc.xml +9 -0
  15. package/android/.idea/modules/android.iml +18 -0
  16. package/android/.idea/modules.xml +8 -0
  17. package/android/.idea/vcs.xml +6 -0
  18. package/android/.idea/workspace.xml +52 -0
  19. package/android/build.gradle +11 -0
  20. package/android/local.properties +8 -0
  21. package/android/src/.DS_Store +0 -0
  22. package/android/src/androidTest/.DS_Store +0 -0
  23. package/android/src/androidTest/java/com/reactnativestripesdk/pushprovisioning/PushProvisioningProxyTest.kt +35 -0
  24. package/android/src/main/java/com/reactnativestripesdk/CardFieldView.kt +1 -0
  25. package/android/src/main/java/com/reactnativestripesdk/Mappers.kt +16 -0
  26. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +6 -1
  27. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +41 -2
  28. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/AddToWalletButtonView.kt +0 -1
  29. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/PushProvisioningProxy.kt +19 -7
  30. package/android/src/main/java/com/reactnativestripesdk/pushprovisioning/TapAndPayProxy.kt +45 -38
  31. package/ios/.DS_Store +0 -0
  32. package/ios/CardFieldView.swift +11 -8
  33. package/ios/StripeSdk.m +5 -0
  34. package/ios/StripeSdk.swift +21 -10
  35. package/ios/StripeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  36. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  37. package/ios/StripeSdk.xcodeproj/project.xcworkspace/xcuserdata/charliecruzan.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  38. package/ios/StripeSdk.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +52 -0
  39. package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +22 -0
  40. package/ios/StripeSdk.xcodeproj/xcuserdata/charliecruzan.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
  41. package/ios/Tests/PushProvisioningTests.swift +49 -0
  42. package/ios/pushprovisioning/AddToWalletButtonView.swift +1 -5
  43. package/ios/pushprovisioning/PushProvisioningUtils.swift +64 -0
  44. package/lib/commonjs/NativeStripeSdk.js.map +1 -1
  45. package/lib/commonjs/components/AddToWalletButton.js +1 -1
  46. package/lib/commonjs/components/AddToWalletButton.js.map +1 -1
  47. package/lib/commonjs/components/ApplePayButton.js +1 -1
  48. package/lib/commonjs/components/ApplePayButton.js.map +1 -1
  49. package/lib/commonjs/components/AuBECSDebitForm.js +1 -1
  50. package/lib/commonjs/components/AuBECSDebitForm.js.map +1 -1
  51. package/lib/commonjs/components/CardField.js +1 -1
  52. package/lib/commonjs/components/CardField.js.map +1 -1
  53. package/lib/commonjs/components/CardForm.js +1 -1
  54. package/lib/commonjs/components/CardForm.js.map +1 -1
  55. package/lib/commonjs/components/GooglePayButton.js +1 -1
  56. package/lib/commonjs/components/GooglePayButton.js.map +1 -1
  57. package/lib/commonjs/components/StripeContainer.js +1 -1
  58. package/lib/commonjs/components/StripeContainer.js.map +1 -1
  59. package/lib/commonjs/functions.js +1 -1
  60. package/lib/commonjs/functions.js.map +1 -1
  61. package/lib/commonjs/hooks/useStripe.js +1 -1
  62. package/lib/commonjs/hooks/useStripe.js.map +1 -1
  63. package/lib/commonjs/types/index.js.map +1 -1
  64. package/lib/module/NativeStripeSdk.js.map +1 -1
  65. package/lib/module/components/AddToWalletButton.js +1 -1
  66. package/lib/module/components/AddToWalletButton.js.map +1 -1
  67. package/lib/module/components/ApplePayButton.js +1 -1
  68. package/lib/module/components/ApplePayButton.js.map +1 -1
  69. package/lib/module/components/AuBECSDebitForm.js +1 -1
  70. package/lib/module/components/AuBECSDebitForm.js.map +1 -1
  71. package/lib/module/components/CardField.js +1 -1
  72. package/lib/module/components/CardField.js.map +1 -1
  73. package/lib/module/components/CardForm.js +1 -1
  74. package/lib/module/components/CardForm.js.map +1 -1
  75. package/lib/module/components/GooglePayButton.js +1 -1
  76. package/lib/module/components/GooglePayButton.js.map +1 -1
  77. package/lib/module/components/StripeContainer.js +1 -1
  78. package/lib/module/components/StripeContainer.js.map +1 -1
  79. package/lib/module/functions.js +1 -1
  80. package/lib/module/functions.js.map +1 -1
  81. package/lib/module/hooks/useStripe.js +1 -1
  82. package/lib/module/hooks/useStripe.js.map +1 -1
  83. package/lib/module/types/index.js.map +1 -1
  84. package/lib/typescript/e2e/screenObject/BasicPaymentScreen.d.ts +1 -2
  85. package/lib/typescript/src/NativeStripeSdk.d.ts +2 -1
  86. package/lib/typescript/src/components/AddToWalletButton.d.ts +1 -1
  87. package/lib/typescript/src/functions.d.ts +2 -1
  88. package/lib/typescript/src/hooks/useStripe.d.ts +2 -1
  89. package/lib/typescript/src/types/PaymentSheet.d.ts +2 -1
  90. package/lib/typescript/src/types/index.d.ts +20 -0
  91. package/package.json +6 -4
  92. package/src/NativeStripeSdk.tsx +5 -0
  93. package/src/components/AddToWalletButton.tsx +1 -1
  94. package/src/functions.ts +25 -0
  95. package/src/hooks/useStripe.tsx +13 -0
  96. package/src/types/PaymentSheet.ts +2 -1
  97. package/src/types/index.ts +27 -0
  98. package/stripe-react-native.podspec +6 -1
package/CHANGELOG.md CHANGED
@@ -2,7 +2,23 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 0.13.1
5
+ ## 0.14.0 - 2022-06-30
6
+
7
+ ### Breaking changes
8
+
9
+ ### New features
10
+
11
+ - Added the `canAddCardToWallet` method. [#986](https://github.com/stripe/stripe-react-native/pull/986).
12
+
13
+ ### Fixes
14
+
15
+ - Fix build errors on Xcode 14 beta 1 by upgrading `stripe-ios` to `~>22.5.1`. [#1011](https://github.com/stripe/stripe-react-native/pull/1011)
16
+ - Fixed an issue on Android where the `brand` field in `CardField`'s `onCardChange` callback wouldn't be set unless the card details were fully complete. [#1012](https://github.com/stripe/stripe-react-native/pull/1012)
17
+ - Fixed an issue where Payment Sheet would cause crashes on Android if `merchantDisplayName` wasn't provided. [#1015](https://github.com/stripe/stripe-react-native/pull/1015)
18
+ - Fixed a bug on Android where a crash could occur if the PaymentSheet was canceled and opened again. [#1014](https://github.com/stripe/stripe-react-native/pull/1014)
19
+ - Fixed an instance on iOS where `CardField`'s expiry date would remain marked as valid, even when it's invalid. [#1018](https://github.com/stripe/stripe-react-native/issues/1018)
20
+
21
+ ## 0.13.1 - 2022-06-16
6
22
 
7
23
  ### Breaking changes
8
24
 
@@ -12,7 +28,7 @@
12
28
 
13
29
  - Never show postal code input in `CardField` if `postalCodeEnabled=false` (regardless of `countryCode`). [#996](https://github.com/stripe/stripe-react-native/pull/996)
14
30
 
15
- ## 0.13.0
31
+ ## 0.13.0 - 2022-06-15
16
32
 
17
33
  ### Breaking changes
18
34
 
@@ -28,7 +44,7 @@
28
44
  - 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)
29
45
  - Make `SetupIntent.lastSetupError` and `PaymentIntent.lastPaymentError` object shape consistent on iOS and Android.[#990](https://github.com/stripe/stripe-react-native/pull/990)
30
46
 
31
- ## 0.12.0
47
+ ## 0.12.0 - 2022-06-02
32
48
 
33
49
  ### Breaking changes
34
50
 
@@ -44,7 +60,7 @@
44
60
  - 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)
45
61
  - 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)
46
62
 
47
- ## 0.11.0
63
+ ## 0.11.0 - 2022-05-24
48
64
 
49
65
  ### Breaking changes
50
66
 
@@ -60,7 +76,7 @@
60
76
  - 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)
61
77
  - Made Android card validation state consistent with iOS in the `CardField` `onCardChange` callback. [#958](https://github.com/stripe/stripe-react-native/pull/958)
62
78
 
63
- ## 0.10.0
79
+ ## 0.10.0 - 2022-05-19
64
80
 
65
81
  ### Breaking changes
66
82
 
@@ -72,7 +88,7 @@
72
88
 
73
89
  ### Fixes
74
90
 
75
- ## 0.9.0
91
+ ## 0.9.0 - 2022-05-10
76
92
 
77
93
  - [#913](https://github.com/stripe/stripe-react-native/pull/913) BREAKING CHANGE: Changed props for the `<AddToWalletButton />` component. Instead of passing `cardHolderName`, `cardLastFour`, `cardDescription`, and `cardBrand` directly as props, you will instead pass a `cardDetails` prop, which is an object containing the following fields:
78
94
  - `primaryAccountIdentifier`: The `wallet.primary_account_identifier` value from the issued card.
@@ -89,7 +105,7 @@
89
105
  - [#914](https://github.com/stripe/stripe-react-native/pull/914) fix: add `fingerprint` to Card result object on Android (already present on iOS)
90
106
  - [#912](https://github.com/stripe/stripe-react-native/pull/912) fix: allow for providing zip code straight from `CardField` component on Android
91
107
 
92
- ## 0.8.0
108
+ ## 0.8.0 - 2022-04-27
93
109
 
94
110
  - **Breaking: This version requires you use `react-native@0.64.0` or above**
95
111
  - [#902](https://github.com/stripe/stripe-react-native/pull/902) fix: create custom babel plugin for package.json imports in src/
@@ -99,7 +115,7 @@
99
115
  - [#849](https://github.com/stripe/stripe-react-native/pull/849) BREAKING CHANGE: Renamed `placeholder` prop on `<CardField />` and `<CardForm />` to `placeholders`.
100
116
  - [#849](https://github.com/stripe/stripe-react-native/pull/849) Feat: Added customized styling options to `<CardForm />` on Android.
101
117
 
102
- ## 0.7.0
118
+ ## 0.7.0 - 2022-04-19
103
119
 
104
120
  - [#894](https://github.com/stripe/stripe-react-native/pull/894) Fix: `<CardField />` `onBlur` callback will now be called appropriately on Android
105
121
  - [#846](https://github.com/stripe/stripe-react-native/pull/846) Fix: Avoid crashes when `currentActivity` is null
@@ -143,21 +159,21 @@
143
159
  - (Typescript) `GooglePay.IsGooglePaySupportedParams` is now `GooglePay.IsSupportedParams`
144
160
  - (Typescript) Removed `GooglePay.SetupIntentParams`
145
161
 
146
- ## 0.6.0
162
+ ## 0.6.0 - 2022-04-01
147
163
 
148
164
  - [#861](https://github.com/stripe/stripe-react-native/pull/861) BREAKING: This library now supports iOS 12 and up, due to `stripe-ios` increasing the deployment target. If you would like to build for iOS 11, please continue to use `@stripe/stripe-react-native@0.5.0`.
149
165
  - To upgrade your iOS deployment target to 12.0, you can either do so in Xcode under your `Build Settings`, or by modifying `IPHONEOS_DEPLOYMENT_TARGET` in your `project.pbxproj` directly. You will also need to update your Podfile to target `:ios, '12.0'`.
150
166
  - [#861](https://github.com/stripe/stripe-react-native/pull/861) Feat: Add support for ACHv2 payments **on iOS only**.
151
167
  - [#861](https://github.com/stripe/stripe-react-native/pull/861) Chore: Upgrade `stripe-ios` to 22.0.0.
152
168
 
153
- ## 0.5.0
169
+ ## 0.5.0 - 2022-03-29
154
170
 
155
171
  - [#863](https://github.com/stripe/stripe-react-native/pull/863) Feat: add card ID and bankAccount ID to token response
156
172
  - [#862](https://github.com/stripe/stripe-react-native/pull/862) Feat: Add support for setting a card's `currency` when creating a Token
157
173
  - [#854](https://github.com/stripe/stripe-react-native/pull/854) Chore: Upgrade `stripe-ios` to 21.13.0. Upgrade `stripe-android` to 19.3.0.
158
174
  - [#845](https://github.com/stripe/stripe-react-native/pull/845) Feat: Added support for `placeholderColor`, `textErrorColor `, `borderColor`, `borderRadius`, and `borderWidth` for `AuBECSDebitForm` on iOS
159
175
 
160
- ## 0.4.0
176
+ ## 0.4.0 - 2022-03-10
161
177
 
162
178
  - [#821](https://github.com/stripe/stripe-react-native/pull/821) Feat: Add support for Klarna
163
179
  - [#630](https://github.com/stripe/stripe-react-native/pull/630) Fix: card field focus jumps back to the card number field on Android
Binary file
File without changes
@@ -0,0 +1,2 @@
1
+ #Tue Jun 21 15:53:42 EDT 2022
2
+ gradle.version=7.1
File without changes
@@ -0,0 +1,3 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="GradleMigrationSettings" migrationVersion="1" />
4
+ <component name="GradleSettings">
5
+ <option name="linkedExternalProjectsSettings">
6
+ <GradleProjectSettings>
7
+ <option name="testRunner" value="GRADLE" />
8
+ <option name="distributionType" value="DEFAULT_WRAPPED" />
9
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
10
+ </GradleProjectSettings>
11
+ </option>
12
+ </component>
13
+ </project>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
4
+ <output url="file://$PROJECT_DIR$/build/classes" />
5
+ </component>
6
+ <component name="ProjectType">
7
+ <option name="id" value="Android" />
8
+ </component>
9
+ </project>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module external.linked.project.id=":" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
3
+ <component name="FacetManager">
4
+ <facet type="android-gradle" name="Android-Gradle">
5
+ <configuration>
6
+ <option name="GRADLE_PROJECT_PATH" value=":" />
7
+ <option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
8
+ <option name="LAST_KNOWN_AGP_VERSION" />
9
+ </configuration>
10
+ </facet>
11
+ </component>
12
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
13
+ <exclude-output />
14
+ <content url="file://$MODULE_DIR$/../.." />
15
+ <orderEntry type="inheritedJdk" />
16
+ <orderEntry type="sourceFolder" forTests="false" />
17
+ </component>
18
+ </module>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/modules/android.iml" filepath="$PROJECT_DIR$/.idea/modules/android.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,52 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AutoImportSettings">
4
+ <option name="autoReloadType" value="NONE" />
5
+ </component>
6
+ <component name="ChangeListManager">
7
+ <list default="true" id="6bd19f01-32d7-4d37-8b5e-6bd0f29ff270" name="Changes" comment="">
8
+ <change afterPath="$PROJECT_DIR$/src/androidTest/java/com/reactnativestripesdk/pushprovisioning/PushProvisioningProxyTest.kt" afterDir="false" />
9
+ <change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle" afterDir="false" />
10
+ <change beforePath="$PROJECT_DIR$/../ios/StripeSdk.xcodeproj/project.pbxproj" beforeDir="false" afterPath="$PROJECT_DIR$/../ios/StripeSdk.xcodeproj/project.pbxproj" afterDir="false" />
11
+ </list>
12
+ <option name="SHOW_DIALOG" value="false" />
13
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
14
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
15
+ <option name="LAST_RESOLUTION" value="IGNORE" />
16
+ </component>
17
+ <component name="Git.Settings">
18
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
19
+ </component>
20
+ <component name="ProjectId" id="2AtuQTRuDgWJsBWelsxPwKKLnTE" />
21
+ <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
22
+ <component name="ProjectViewState">
23
+ <option name="hideEmptyMiddlePackages" value="true" />
24
+ <option name="showLibraryContents" value="true" />
25
+ </component>
26
+ <component name="PropertiesComponent">
27
+ <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
28
+ <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
29
+ <property name="RunOnceActivity.cidr.known.project.marker" value="true" />
30
+ <property name="cidr.known.project.marker" value="true" />
31
+ <property name="last_opened_file_path" value="$PROJECT_DIR$" />
32
+ </component>
33
+ <component name="RecentsManager">
34
+ <key name="CreateTestDialog.Recents.Supers">
35
+ <recent name="" />
36
+ </key>
37
+ <key name="CreateTestDialog.RecentsKey">
38
+ <recent name="" />
39
+ </key>
40
+ </component>
41
+ <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
42
+ <component name="TaskManager">
43
+ <task active="true" id="Default" summary="Default task">
44
+ <changelist id="6bd19f01-32d7-4d37-8b5e-6bd0f29ff270" name="Changes" comment="" />
45
+ <created>1655841188103</created>
46
+ <option name="number" value="Default" />
47
+ <option name="presentableId" value="Default" />
48
+ <updated>1655841188103</updated>
49
+ </task>
50
+ <servers />
51
+ </component>
52
+ </project>
@@ -34,6 +34,7 @@ android {
34
34
  versionCode 1
35
35
  versionName "1.0"
36
36
  vectorDrawables.useSupportLibrary = true
37
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
37
38
  }
38
39
 
39
40
  buildTypes {
@@ -146,4 +147,14 @@ dependencies {
146
147
 
147
148
  // Users need to declare this dependency on their own, otherwise all methods are a no-op
148
149
  compileOnly 'com.stripe:stripe-android-issuing-push-provisioning:1.1.0'
150
+
151
+ androidTestImplementation "junit:junit:4.13"
152
+ androidTestImplementation "androidx.test:core:1.4.0"
153
+ androidTestImplementation 'androidx.test:runner:1.1.0'
154
+ androidTestImplementation "org.mockito:mockito-core:3.+"
155
+ }
156
+
157
+ configurations {
158
+ // We want to include all of our compileOnly libraries in our tests
159
+ androidTestImplementation.extendsFrom compileOnly
149
160
  }
@@ -0,0 +1,8 @@
1
+ ## This file must *NOT* be checked into Version Control Systems,
2
+ # as it contains information specific to your local configuration.
3
+ #
4
+ # Location of the SDK. This is only used by Gradle.
5
+ # For customization when using a Version Control System, please read the
6
+ # header note.
7
+ #Tue Jun 21 15:53:06 EDT 2022
8
+ sdk.dir=/Users/charliecruzan/Library/Android/sdk
Binary file
@@ -0,0 +1,35 @@
1
+ package com.reactnativestripesdk.pushprovisioning
2
+
3
+ import android.content.Context
4
+ import androidx.test.core.app.ApplicationProvider
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import org.junit.Assert.*
7
+ import org.junit.Test
8
+
9
+ class PushProvisioningProxyTest {
10
+ private val reactApplicationContext = ReactApplicationContext(
11
+ ApplicationProvider.getApplicationContext<Context>()
12
+ )
13
+
14
+ @Test
15
+ fun getApiVersion() {
16
+ // This value very rarely changes, so the test is hard coded
17
+ assertEquals(
18
+ "2019-09-09",
19
+ PushProvisioningProxy.getApiVersion()
20
+ )
21
+ }
22
+
23
+ @Test
24
+ fun isNFCEnabled() {
25
+ assertEquals(
26
+ false,
27
+ PushProvisioningProxy.isNFCEnabled(reactApplicationContext)
28
+ )
29
+ }
30
+
31
+ @Test
32
+ fun isTokenInWallet() {
33
+ assertEquals(TapAndPayProxy.isTokenInWallet({}, "4242"), false)
34
+ }
35
+ }
@@ -275,6 +275,7 @@ class CardFieldView(context: ThemedReactContext) : FrameLayout(context) {
275
275
  cardDetails["validNumber"] = getCardValidationState(CardValidCallback.Fields.Number, cardInputWidgetBinding.cardNumberEditText)
276
276
  cardDetails["validCVC"] = getCardValidationState(CardValidCallback.Fields.Cvc, cardInputWidgetBinding.cvcEditText)
277
277
  cardDetails["validExpiryDate"] = getCardValidationState(CardValidCallback.Fields.Expiry, cardInputWidgetBinding.expiryDateEditText)
278
+ cardDetails["brand"] = mapCardBrand(cardInputWidgetBinding.cardNumberEditText.cardBrand)
278
279
 
279
280
  if (isValid) {
280
281
  onValidCardChange()
@@ -14,6 +14,22 @@ internal fun createResult(key: String, value: WritableMap): WritableMap {
14
14
  return map
15
15
  }
16
16
 
17
+ internal fun createCanAddCardResult(canAddCard: Boolean, status: String? = null, token: WritableMap? = null): WritableNativeMap {
18
+ val result = WritableNativeMap()
19
+ val details = WritableNativeMap()
20
+ if (status != null) {
21
+ result.putBoolean("canAddCard", false)
22
+ details.putString("status", status)
23
+ } else {
24
+ result.putBoolean("canAddCard", canAddCard)
25
+ if (token != null) {
26
+ details.putMap("token", token)
27
+ }
28
+ }
29
+ result.putMap("details", details)
30
+ return result
31
+ }
32
+
17
33
  internal fun mapIntentStatus(status: StripeIntent.Status?): String {
18
34
  return when (status) {
19
35
  StripeIntent.Status.Succeeded -> "Succeeded"
@@ -49,6 +49,10 @@ class PaymentSheetFragment(
49
49
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
50
50
  super.onViewCreated(view, savedInstanceState)
51
51
  val merchantDisplayName = arguments?.getString("merchantDisplayName").orEmpty()
52
+ if (merchantDisplayName.isEmpty()) {
53
+ initPromise.resolve(createError(ErrorType.Failed.toString(), "merchantDisplayName cannot be empty or null."))
54
+ return
55
+ }
52
56
  val customerId = arguments?.getString("customerId").orEmpty()
53
57
  val customerEphemeralKeySecret = arguments?.getString("customerEphemeralKeySecret").orEmpty()
54
58
  val countryCode = arguments?.getString("merchantCountryCode").orEmpty()
@@ -98,9 +102,10 @@ class PaymentSheetFragment(
98
102
  confirmPromise?.resolve(WritableNativeMap()) ?: run {
99
103
  presentPromise?.resolve(WritableNativeMap())
100
104
  }
105
+ // Remove the fragment now, we can be sure it won't be needed again if an intent is successful
106
+ (context.currentActivity as? AppCompatActivity)?.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
101
107
  }
102
108
  }
103
- (context.currentActivity as? AppCompatActivity)?.supportFragmentManager?.beginTransaction()?.remove(this)?.commitAllowingStateLoss()
104
109
  }
105
110
 
106
111
  var defaultBillingDetails: PaymentSheet.BillingDetails? = null
@@ -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
@@ -525,6 +531,30 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
525
531
  googlePayFragment?.createPaymentMethod(currencyCode, amount, promise)
526
532
  }
527
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
+
528
558
  @ReactMethod
529
559
  fun isCardInWallet(params: ReadableMap, promise: Promise) {
530
560
  val last4 = getValOr(params, "cardLastFour", null) ?: run {
@@ -532,7 +562,16 @@ class StripeSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
532
562
  return
533
563
  }
534
564
  getCurrentActivityOrResolveWithError(promise)?.let {
535
- 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
+ }
536
575
  }
537
576
  }
538
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