├── .circleci
└── config.yml
├── .detoxrc.json
├── .editorconfig
├── .gitattributes
├── .github
├── pull_request_template.md
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── .husky
├── .npmignore
├── commit-msg
└── pre-commit
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── android
├── build.gradle
├── gradle.properties
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── stripeidentityreactnative
│ ├── Mappers.kt
│ ├── StripeIdentityReactNativeModule.kt
│ ├── StripeIdentityReactNativePackage.kt
│ └── StripeIdentityVerificationSheetFragment.kt
├── babel.config.js
├── docs
├── api-reference
│ ├── .nojekyll
│ ├── assets
│ │ ├── highlight.css
│ │ ├── icons.css
│ │ ├── icons.png
│ │ ├── icons@2x.png
│ │ ├── main.js
│ │ ├── search.js
│ │ ├── style.css
│ │ ├── widgets.png
│ │ └── widgets@2x.png
│ ├── index.html
│ └── modules.html
└── index.html
├── e2e
├── app.e2e.js
├── config.json
├── environment.js
└── utils.js
├── example
├── android
│ ├── app
│ │ ├── build.gradle
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── stripeidentityreactnative
│ │ │ │ └── ReactNativeFlipper.java
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── stripeidentityreactnative
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── MainApplication.java
│ │ │ │ └── newarchitecture
│ │ │ │ ├── MainApplicationReactNativeHost.java
│ │ │ │ ├── components
│ │ │ │ └── MainComponentsRegistry.java
│ │ │ │ └── modules
│ │ │ │ └── MainApplicationTurboModuleManagerDelegate.java
│ │ │ ├── jni
│ │ │ ├── Android.mk
│ │ │ ├── MainApplicationModuleProvider.cpp
│ │ │ ├── MainApplicationModuleProvider.h
│ │ │ ├── MainApplicationTurboModuleManagerDelegate.cpp
│ │ │ ├── MainApplicationTurboModuleManagerDelegate.h
│ │ │ ├── MainComponentsRegistry.cpp
│ │ │ ├── MainComponentsRegistry.h
│ │ │ └── OnLoad.cpp
│ │ │ └── res
│ │ │ ├── drawable
│ │ │ └── rn_edit_text_material.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── app.json
├── babel.config.js
├── index.js
├── ios
│ ├── File.swift
│ ├── Podfile
│ ├── Podfile.lock
│ ├── StripeIdentityReactNativeExample-Bridging-Header.h
│ ├── StripeIdentityReactNativeExample.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── StripeIdentityReactNativeExample.xcscheme
│ ├── StripeIdentityReactNativeExample.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── StripeIdentityReactNativeExample
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.mm
│ │ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── LaunchScreen.storyboard
│ │ └── main.m
├── metro.config.js
├── package-lock.json
├── package.json
├── src
│ ├── App.tsx
│ ├── assets
│ │ ├── RocketRides.png
│ │ ├── RocketRides@2x.png
│ │ └── RocketRides@3x.png
│ ├── components
│ │ ├── Identity.tsx
│ │ ├── Option.tsx
│ │ └── Options.tsx
│ ├── global.d.ts
│ ├── screens
│ │ └── HomeScreen.tsx
│ ├── types.ts
│ └── utils
│ │ └── api.ts
└── yarn.lock
├── ios
├── StripeIdentityReactNative-Bridging-Header.h
├── StripeIdentityReactNative.m
├── StripeIdentityReactNative.swift
└── StripeIdentityReactNative.xcodeproj
│ └── project.pbxproj
├── package.json
├── scripts
└── publish
├── src
├── StripeIdentitySdk.tsx
├── __tests__
│ └── index.test.tsx
├── functions.ts
├── hooks
│ └── useStripeIdentity.tsx
├── index.ts
└── types.ts
├── stripe-identity-react-native.podspec
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | rn: react-native-community/react-native@5.6.2
5 |
6 | commands:
7 | attach_project:
8 | steps:
9 | - attach_workspace:
10 | at: ~/project
11 |
12 | jobs:
13 | install-dependencies:
14 | executor: rn/linux_js
15 | steps:
16 | - checkout
17 | - attach_project
18 | - restore_cache:
19 | keys:
20 | - dependencies-{{ checksum "package.json" }}
21 | - dependencies-
22 | - restore_cache:
23 | keys:
24 | - dependencies-example-{{ checksum "example/package.json" }}
25 | - dependencies-example-
26 | - run:
27 | name: Install dependencies
28 | command: |
29 | yarn install --cwd example --frozen-lockfile
30 | yarn install --frozen-lockfile
31 | - save_cache:
32 | key: dependencies-{{ checksum "package.json" }}
33 | paths: [node_modules]
34 | - save_cache:
35 | key: dependencies-example-{{ checksum "example/package.json" }}
36 | paths: [example/node_modules]
37 | - persist_to_workspace:
38 | root: .
39 | paths: [.]
40 |
41 | lint:
42 | executor: rn/linux_js
43 | steps:
44 | - attach_project
45 | - run:
46 | name: Lint files
47 | command: |
48 | yarn lint
49 |
50 | typescript:
51 | executor: rn/linux_js
52 | steps:
53 | - attach_project
54 | - run:
55 | name: Typecheck files
56 | command: |
57 | yarn typescript
58 |
59 | test:
60 | executor: rn/linux_js
61 | steps:
62 | - attach_project
63 | - run:
64 | name: Integration tests
65 | command: |
66 | yarn test
67 |
68 | e2e-ios:
69 | executor:
70 | name: rn/macos
71 | xcode_version: '12.4.0'
72 | steps:
73 | - attach_workspace:
74 | at: .
75 | - rn/setup_macos_executor:
76 | node_version: '14.15.0'
77 | - rn/ios_simulator_start:
78 | device: 'iPhone 11'
79 | - run:
80 | command: yarn install --frozen-lockfile
81 | name: yarn install
82 | - rn/pod_install:
83 | pod_install_directory: 'example/ios'
84 | - run:
85 | command: yarn e2e:build:ios:release
86 | name: build for detox
87 | - run:
88 | command: yarn e2e:test:ios:release
89 | name: test detox
90 | - store_artifacts:
91 | path: ./artifacts
92 |
93 | e2e-android:
94 | executor:
95 | name: rn/macos
96 | xcode_version: '12.4.0'
97 | steps:
98 | - attach_workspace:
99 | at: .
100 | - rn/setup_macos_executor:
101 | node_version: '14.15.0'
102 | - run:
103 | command: yarn install --frozen-lockfile
104 | name: yarn install
105 | - rn/android_emulator_start:
106 | logcat_grep: 'com.example.stripeterminalreactnative'
107 | platform_version: android-28
108 | - run:
109 | command: yarn e2e:build:android:release
110 | name: build for detox
111 | - run:
112 | no_output_timeout: 60m
113 | command: yarn e2e:test:android:release
114 | name: test detox
115 | - store_artifacts:
116 | path: ./artifacts
117 |
118 | workflows:
119 | build-and-test:
120 | jobs:
121 | - install-dependencies
122 | - lint:
123 | requires:
124 | - install-dependencies
125 | - typescript:
126 | requires:
127 | - install-dependencies
128 | - test:
129 | requires:
130 | - install-dependencies
131 | - e2e-android:
132 | requires:
133 | - install-dependencies
134 | - e2e-ios:
135 | requires:
136 | - install-dependencies
137 |
--------------------------------------------------------------------------------
/.detoxrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "testRunner": "jest",
3 | "runnerConfig": "e2e/config.json",
4 | "apps": {
5 | "ios.debug": {
6 | "type": "ios.app",
7 | "binaryPath": "example/ios/build/Build/Products/Debug-iphonesimulator/StripeIdentityReactNativeExample.app",
8 | "build": "xcodebuild -workspace example/ios/StripeIdentityReactNativeExample.xcworkspace -configuration Debug -scheme StripeIdentityReactNativeExample -destination 'platform=iOS Simulator,name=iPhone 11' -derivedDataPath example/ios/build"
9 | },
10 | "ios.release": {
11 | "type": "ios.app",
12 | "binaryPath": "example/ios/build/Build/Products/Release-iphonesimulator/StripeIdentityReactNativeExample.app",
13 | "build": "export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace example/ios/StripeIdentityReactNativeExample.xcworkspace -configuration Release -scheme StripeIdentityReactNativeExample -destination 'platform=iOS Simulator,name=iPhone 11' -derivedDataPath example/ios/build"
14 | },
15 | "android.debug": {
16 | "type": "android.apk",
17 | "binaryPath": "example/android/app/build/outputs/apk/debug/app-debug.apk",
18 | "build": "cd example/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug ; cd -"
19 | },
20 | "android.release": {
21 | "type": "android.apk",
22 | "binaryPath": "example/android/app/build/outputs/apk/release/app-release.apk",
23 | "build": "export RCT_NO_LAUNCH_PACKAGER=true && (cd example/android; ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release ; cd -)"
24 | }
25 | },
26 | "devices": {
27 | "simulator": {
28 | "type": "ios.simulator",
29 | "device": {
30 | "type": "iPhone 11"
31 | }
32 | },
33 | "emulator": {
34 | "type": "android.emulator",
35 | "device": {
36 | "avdName": "Nexus_6_API_29_2",
37 | "utilBinaryPaths": ["./test-butler-app.apk"]
38 | }
39 | },
40 | "ci-emulator": {
41 | "type": "android.emulator",
42 | "device": {
43 | "avdName": "TestingAVD"
44 | },
45 | "utilBinaryPaths": ["./test-butler-app.apk"]
46 | }
47 | },
48 | "configurations": {
49 | "ios": {
50 | "device": "simulator",
51 | "app": "ios.debug"
52 | },
53 | "ios.sim.release": {
54 | "device": "simulator",
55 | "app": "ios.release"
56 | },
57 | "android": {
58 | "device": "emulator",
59 | "app": "android.debug"
60 | },
61 | "android.emu.release": {
62 | "device": "ci-emulator",
63 | "app": "android.release"
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | indent_style = space
10 | indent_size = 2
11 |
12 | end_of_line = lf
13 | charset = utf-8
14 | trim_trailing_whitespace = true
15 | insert_final_newline = true
16 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 | # specific for windows script files
3 | *.bat text eol=crlf
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 |
4 | # Motivation
5 |
6 |
7 | # Testing
8 |
9 | - [ ] Added tests
10 | - [ ] Modified tests
11 | - [ ] Manually verified
12 |
13 | # Screenshots
14 | | Before | After |
15 | | ------------- | ------------- |
16 | | *before screenshot* | *after screenshot* |
17 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '37 19 * * 3'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript']
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
52 |
53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54 | # If this step fails, then you should remove it and run the build manually (see below)
55 | - name: Autobuild
56 | uses: github/codeql-action/autobuild@v2
57 |
58 | # ℹ️ Command-line programs to run using the OS shell.
59 | # 📚 https://git.io/JvXDl
60 |
61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62 | # and modify them (or add more) to build your code if your project
63 | # uses a compiled language
64 |
65 | #- run: |
66 | # make bootstrap
67 | # make release
68 |
69 | - name: Perform CodeQL Analysis
70 | uses: github/codeql-action/analyze@v2
71 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # XDE
6 | .expo/
7 |
8 | # VSCode
9 | .vscode/
10 | jsconfig.json
11 |
12 | # Xcode
13 | #
14 | build/
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata
24 | *.xccheckout
25 | *.moved-aside
26 | DerivedData
27 | *.hmap
28 | *.ipa
29 | *.xcuserstate
30 | project.xcworkspace
31 |
32 | # Android/IJ
33 | #
34 | .classpath
35 | .cxx
36 | .gradle
37 | .idea
38 | .project
39 | .settings
40 | local.properties
41 | android.iml
42 |
43 | # Cocoapods
44 | #
45 | example/ios/Pods
46 |
47 | # node.js
48 | #
49 | node_modules/
50 | npm-debug.log
51 | yarn-debug.log
52 | yarn-error.log
53 |
54 | # BUCK
55 | buck-out/
56 | \.buckd/
57 | android/app/libs
58 | android/keystores/debug.keystore
59 |
60 | # Expo
61 | .expo/*
62 |
63 | # generated by bob
64 | lib/
65 |
66 | artifacts/
67 |
--------------------------------------------------------------------------------
/.husky/.npmignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn commitlint -E HUSKY_GIT_PARAMS
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn lint && yarn typescript
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [v0.3.7](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.7) - 6 May 2025
2 |
3 | ### Changed
4 |
5 | - Updated `stripe-ios` to 24.13.1
6 |
7 | # [v0.3.6](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.6) - 6 May 2025
8 |
9 | ### Changed
10 |
11 | - Updated `stripe-ios` to 24.13.0
12 |
13 | # [v0.3.5](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.4) - 5 May 2025
14 |
15 | ### Changed
16 |
17 | - Updated `stripe-ios` to 24.12.1
18 | - [Fixed] Fixed an issue where identity verification may fail due to stale model cache.
19 |
20 | # [v0.3.4](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.4) - 29 Apr 2025
21 |
22 | ### Changed
23 |
24 | - Updated `stripe-ios` to 24.12.\*
25 |
26 |
27 |
28 | # [v0.3.3](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.3) - 28 Apr 2025
29 |
30 | ### Changed
31 |
32 | - Updated `stripe-ios` to 24.11.\*
33 |
34 |
35 |
36 | # [v0.3.2](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.2) - 25 Apr 2025
37 |
38 | ### Changed
39 |
40 | - Updated `stripe-ios` to 24.10.\*
41 |
42 |
43 |
44 | # [v0.3.1](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.1) - 28 Mar 2025
45 |
46 | ### Changed
47 |
48 | - Updated `stripe-ios` to 24.9.\*
49 |
50 |
51 |
52 | # [v0.3.0](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.3.0) - 24 Mar 2025
53 |
54 | ### Changed
55 |
56 | - Updated `stripe-ios` to 24.8.\*
57 |
58 |
59 |
60 | # [v0.2.18](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.2.18) - 11 Mar 2025
61 |
62 | ### Changed
63 |
64 | - Replaced unreliable boost dependency url
65 |
66 |
67 |
68 | # [v0.2.17](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.2.17) - 10 Mar 2025
69 |
70 | ### Changed
71 |
72 | - Updated `stripe-ios` to 24.7.\*
73 |
74 |
75 |
76 | # [v0.2.16](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.2.16) - 24 Jan 2025
77 |
78 | ### Changed
79 |
80 | - Updated `stripe-ios` to 24.4.\*
81 |
82 |
83 |
84 | # [v0.2.14](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.2.14) - 02 December 2024
85 |
86 | ### Changed
87 |
88 | - Updated `stripe-ios` to 24.1.\*
89 | - Updated `stripe-android` to 20.52.\*
90 |
91 |
92 |
93 | # [v0.2.13](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.2.13) - 19 July 2024
94 |
95 | ### Changed
96 |
97 | - Updated `stripe-ios` to 23.28.\*
98 | - Updated `stripe-android` to 20.48.\*
99 |
100 |
101 |
102 | # [v0.1.8](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.8) - 15 May 2023
103 |
104 | ### Changed
105 |
106 | - Update Android to 20.25.+ and iOS to 23.8.+
107 |
108 | [Changes][v0.1.8]
109 |
110 |
111 |
112 | # [v0.1.7](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.7) - 03 May 2023
113 |
114 |
115 |
116 |
117 | > Note: This version is compatible with `stripe-react-native` [0.27.1](https://github.com/stripe/stripe-react-native/releases/tag/v0.27.1) if your app uses both SDKs
118 |
119 | ### New features
120 |
121 | - Support test mode in iOS and Android
122 |
123 | [Changes][v0.1.7]
124 |
125 |
126 |
127 | # [v0.1.6](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.6) - 27 Apr 2023
128 |
129 | [Changes][v0.1.6]
130 |
131 |
132 |
133 | # [v0.1.5](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.5) - 25 Mar 2023
134 |
135 | Bump up iOS native SDK version to `~> 23.5.0`
136 |
137 | [Changes][v0.1.5]
138 |
139 |
140 |
141 | # [v0.1.4](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.4) - 09 Mar 2023
142 |
143 | - Support [ID](https://stripe.com/docs/identity/verification-checks?type=id-number) & [Address](https://stripe.com/docs/identity/verification-checks?type=address) verification.
144 | - Use latest native iOS SDK from version 23.4.2
145 | - Update Android Kotlin version to 1.8.0 and agp to 7.2.2
146 |
147 | [Changes][v0.1.4]
148 |
149 |
150 |
151 | # [v0.1.2](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.2) - 13 Jan 2023
152 |
153 | Use latest native iOS SDK from version 23.3.0
154 |
155 | ### Fixes
156 |
157 | [96](https://github.com/stripe/stripe-identity-react-native/pull/96) use the latest native iOS
158 |
159 | [Changes][v0.1.2]
160 |
161 |
162 |
163 | # [v0.1.1](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.1) - 14 Sep 2022
164 |
165 | Fixing an Android bug when StripeIdentityReactNativeModule is registered but not used.
166 |
167 | ### Fixes
168 |
169 | [88](https://https://github.com/stripe/stripe-identity-react-native/pull/88) Null check encapsulated fragment for StripeIdentityReactNativeModule for Android
170 |
171 | [Changes][v0.1.1]
172 |
173 |
174 |
175 | # [Initial release stripe-identity-react-native (v0.1.0)](https://github.com/stripe/stripe-identity-react-native/releases/tag/v0.1.0) - 19 Apr 2022
176 |
177 | Initial release for version `v0.1.0`
178 |
179 | [Changes][v0.1.0]
180 |
181 | [v0.1.8]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.7...v0.1.8
182 | [v0.1.7]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.6...v0.1.7
183 | [v0.1.6]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.5...v0.1.6
184 | [v0.1.5]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.4...v0.1.5
185 | [v0.1.4]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.2...v0.1.4
186 | [v0.1.2]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.1...v0.1.2
187 | [v0.1.1]: https://github.com/stripe/stripe-identity-react-native/compare/v0.1.0...v0.1.1
188 | [v0.1.0]: https://github.com/stripe/stripe-identity-react-native/tree/v0.1.0
189 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project.
4 |
5 | ## Development workflow
6 |
7 | To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
8 |
9 | ```sh
10 | yarn
11 | ```
12 |
13 | > While it's possible to use [`npm`](https://github.com/npm/cli), the tooling is built around [`yarn`](https://classic.yarnpkg.com/), so you'll have an easier time if you use `yarn` for development.
14 |
15 | While developing, you can run the [example app](/example/) to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app.
16 |
17 | To start the packager:
18 |
19 | ```sh
20 | yarn example start
21 | ```
22 |
23 | To run the example app on Android:
24 |
25 | ```sh
26 | yarn example android
27 | ```
28 |
29 | To run the example app on iOS:
30 |
31 | ```sh
32 | yarn example ios
33 | ```
34 |
35 | Make sure your code passes TypeScript and ESLint. Run the following to verify:
36 |
37 | ```sh
38 | yarn typescript
39 | yarn lint
40 | ```
41 |
42 | To fix formatting errors, run the following:
43 |
44 | ```sh
45 | yarn lint --fix
46 | ```
47 |
48 | Remember to add tests for your change if possible. Run the unit tests by:
49 |
50 | ```sh
51 | yarn test
52 | ```
53 |
54 | To edit the Objective-C files, open `example/ios/StripeIdentityReactNativeExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > stripe-identity-react-native`.
55 |
56 | To edit the Kotlin files, open `example/android` in Android studio and find the source files at `stripeidentityreactnative` under `Android`.
57 |
58 | ### Commit message convention
59 |
60 | We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
61 |
62 | - `fix`: bug fixes, e.g. fix crash due to deprecated method.
63 | - `feat`: new features, e.g. add new method to the module.
64 | - `refactor`: code refactor, e.g. migrate from class components to hooks.
65 | - `docs`: changes into documentation, e.g. add usage example for the module..
66 | - `test`: adding or updating tests, e.g. add integration tests using detox.
67 | - `chore`: tooling changes, e.g. change CI config.
68 |
69 | Our pre-commit hooks verify that your commit message matches this format when committing.
70 |
71 | ### Linting and tests
72 |
73 | [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/)
74 |
75 | We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
76 |
77 | Our pre-commit hooks verify that the linter and tests pass when committing.
78 |
79 | ### Scripts
80 |
81 | The `package.json` file contains various scripts for common tasks:
82 |
83 | - `yarn typescript`: type-check files with TypeScript.
84 | - `yarn lint`: lint files with ESLint.
85 | - `yarn test`: run unit tests with Jest.
86 | - `yarn example start`: start the Metro server for the example app.
87 | - `yarn example android`: run the example app on Android.
88 | - `yarn example ios`: run the example app on iOS.
89 |
90 | ### Sending a pull request
91 |
92 | > **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).
93 |
94 | When you're sending a pull request:
95 |
96 | - Prefer small pull requests focused on one change.
97 | - Verify that linters and tests are passing.
98 | - Review the documentation to make sure it looks good.
99 | - Follow the pull request template when opening a pull request.
100 | - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.
101 |
102 | ## Code of Conduct
103 |
104 | ### Our Pledge
105 |
106 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
107 |
108 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
109 |
110 | ### Our Standards
111 |
112 | Examples of behavior that contributes to a positive environment for our community include:
113 |
114 | - Demonstrating empathy and kindness toward other people
115 | - Being respectful of differing opinions, viewpoints, and experiences
116 | - Giving and gracefully accepting constructive feedback
117 | - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
118 | - Focusing on what is best not just for us as individuals, but for the overall community
119 |
120 | Examples of unacceptable behavior include:
121 |
122 | - The use of sexualized language or imagery, and sexual attention or
123 | advances of any kind
124 | - Trolling, insulting or derogatory comments, and personal or political attacks
125 | - Public or private harassment
126 | - Publishing others' private information, such as a physical or email
127 | address, without their explicit permission
128 | - Other conduct which could reasonably be considered inappropriate in a
129 | professional setting
130 |
131 | ### Enforcement Responsibilities
132 |
133 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
134 |
135 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
136 |
137 | ### Scope
138 |
139 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
140 |
141 | ### Enforcement
142 |
143 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly.
144 |
145 | All community leaders are obligated to respect the privacy and security of the reporter of any incident.
146 |
147 | ### Enforcement Guidelines
148 |
149 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
150 |
151 | #### 1. Correction
152 |
153 | **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
154 |
155 | **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
156 |
157 | #### 2. Warning
158 |
159 | **Community Impact**: A violation through a single incident or series of actions.
160 |
161 | **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
162 |
163 | #### 3. Temporary Ban
164 |
165 | **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
166 |
167 | **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
168 |
169 | #### 4. Permanent Ban
170 |
171 | **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
172 |
173 | **Consequence**: A permanent ban from any sort of public interaction within the community.
174 |
175 | ### Attribution
176 |
177 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
178 | available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
179 |
180 | Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
181 |
182 | [homepage]: https://www.contributor-covenant.org
183 |
184 | For answers to common questions about this code of conduct, see the FAQ at
185 | https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
186 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Mateusz Skwierczyński
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stripe Identity React Native SDK
2 |
3 | Stripe Identity enables online businesses to securely verify the identities of users around the world. Robust identity verification helps prevent fraud, simplify compliance, and increase trust. Stripe will use biometric technology (on images of you and your IDs) and other data sources. With the Stripe Identity React Native SDK, you can confidently verify the authenticity of ID documents from over 33 countries in your React Native application.
4 |
5 | > To get access to the Identity React Native SDK, visit the [Identity Settings](https://dashboard.stripe.com/settings/identity) page and click **Enable**.
6 |
7 | ## Getting started
8 |
9 | Get started with our [📚 integration guides](https://stripe.com/docs/identity/verify-identity-documents?platform=react-native) and [example project](#run-the-example-app).
10 |
11 | > Updating to a newer version of the SDK? See our [changelog](https://github.com/stripe/stripe-identity-react-native/blob/main/CHANGELOG.md).
12 |
13 | ## Features
14 |
15 | **Simplified security**: We've made it simple for you to securely collect your user's personally identifiable information (PII) such as identity document images. Sensitive PII data is sent directly to Stripe Identity instead of passing through your server. For more information, see our [integration security guide](https://stripe.com/docs/security).
16 |
17 | **Automatic document capture**: We automatically capture images of the front and back of government-issued photo ID to ensure a clear and readable image.
18 |
19 | **Prebuilt UI**: We provide [`IdentityVerificationSheet`](https://stripe.dev/stripe-ios/stripe-identity/Classes/IdentityVerificationSheet.html), a prebuilt UI that combines all the steps required to collect ID documents, selfies, and ID numbers into a single sheet that displays on top of your app.
20 |
21 | **Automated verification**: Stripe Identity's automated verification technology looks for patterns to help determine if an ID document is real or fake and uses distinctive physiological characteristics of faces to match your users' selfies to photos on their ID document. Collected identity information is checked against a global set of databases to confirm that it exists. Learn more about the [verification checks supported by Stripe Identity](https://stripe.com/docs/identity/verification-checks), [accessing verification results](https://stripe.com/docs/identity/access-verification-results), or our integration guide on [handling verification outcomes](https://stripe.com/docs/identity/handle-verification-outcomes).
22 |
23 | ### Requirements
24 |
25 | The SDK uses TypeScript features available in Babel version `7.9.0` and above.
26 | Alternatively use the `plugin-transform-typescript` plugin in your project.
27 |
28 | #### Android
29 | - Compatible with Android 5.0 (API level 21) and above.
30 | - Stripe Identity requires the hosting activity to use material theme. To enable material theme:
31 | - Open your project's `app/src/main/AndroidManifest.xml`.
32 | - Make sure the `android:theme` applied to the `application` is a child of one of the material themes(e.g `Theme.MaterialComponents.DayNight`).
33 | > See more details about material theme [here](https://material.io/develop/android/theming/dark).
34 |
35 | #### iOS
36 | > Note: [Xcode 13 is no longer supported by Apple](https://developer.apple.com/news/upcoming-requirements/). Please upgrade to Xcode 14.1 or later.
37 |
38 | - Compatible with apps targeting iOS 13.0 or above.
39 | - Run `pod install` in your `ios` directory to ensure that you also install the required native dependencies.
40 | - Stripe Identity requires access to the device’s camera to capture identity documents. To enable your app to request camera permissions:
41 | - Open your project’s `Info.plist`.
42 | - Add the `NSCameraUsageDescription` key.
43 | - Add a string value that explains to your users why your app requires camera permissions(e.g `This app uses the camera to take a picture of your identity documents.`).
44 |
45 | ## Usage example
46 |
47 | Get started with our [📚 integration guides](https://stripe.com/docs/identity/verify-identity-documents?platform=react-native) and [example project](#run-the-example-app), or [📘 browse the SDK reference](https://stripe.dev/stripe-identity-react-native).
48 |
49 | To initialize Stripe Identity SDK in your React Native app, use the `useStripeIdentity` hook in the screen where you want to use it.
50 |
51 | First you need a server-side endpoint to [create the VerificationSession](https://stripe.com/docs/api/identity/verification_sessions/create) and ephemeral key secret, then you can send a POST request to create verification session:
52 |
53 | ```ts
54 | const fetchVerificationSessionParams = async () => {
55 | try {
56 | const data = await fetch(
57 | `${YOUR_SERVER_BASE_URL}/create-verification-session`,
58 | {
59 | method: 'POST',
60 | headers: {
61 | 'Content-Type': 'application/json',
62 | },
63 | body: {},
64 | }
65 | );
66 | const json = await data.json();
67 | return json;
68 | } catch (e) {
69 | return {};
70 | }
71 | };
72 | ```
73 |
74 | Once you get options you can use `useStripeIdentity` passing fetchOptions to it.
75 |
76 | ```tsx
77 | // HomeScreen.tsx
78 | import { useStripeIdentity } from '@stripe/stripe-identity-react-native';
79 | import logo from './assets/logo.png';
80 |
81 | function HomeScreen() {
82 | const fetchOptions = async () => {
83 | const response = await fetchVerificationSessionParams();
84 |
85 | return {
86 | sessionId: response.id,
87 | ephemeralKeySecret: response.ephemeral_key_secret,
88 | brandLogo: Image.resolveAssetSource(logo),
89 | };
90 | };
91 |
92 | const { status, present, loading } = useStripeIdentity(fetchOptions);
93 |
94 | const handlePress = useCallback(() => {
95 | present();
96 | }, [present]);
97 |
98 | const renderButton = useCallback(() => {
99 | if (loading) {
100 | return ;
101 | }
102 | return ;
103 | }, [loading, handlePress]);
104 |
105 | return (
106 |
107 | {renderButton()}
108 | Status: {status}
109 |
110 | );
111 | }
112 | ```
113 |
114 | Or if you don't want to use `useStripeIdentity` hook, you can also use this method to create your own implementation:
115 |
116 | ```tsx
117 | // HomeScreen.tsx
118 | import { useState } from 'react';
119 | import { presentIdentityVerificationSheet } from '@stripe/stripe-identity-react-native';
120 | import logo from './assets/logo.png';
121 |
122 | function HomeScreen() {
123 | const [loading, setLoading] = useState(false);
124 | const [status, setStatus] = useState<
125 | IdentityVerificationSheetStatus | undefined
126 | >();
127 | const [error, setError] = useState();
128 |
129 | const fetchOptions = async () => {
130 | const response = await fetchVerificationSessionParams();
131 |
132 | return {
133 | sessionId: response.id,
134 | ephemeralKeySecret: response.ephemeral_key_secret,
135 | brandLogo: Image.resolveAssetSource(logo),
136 | };
137 | };
138 |
139 | const present = async () => {
140 | setLoading(true);
141 | const options = await fetchOptions();
142 | setLoading(false);
143 | const { status, error } = await presentIdentityVerificationSheet(options);
144 | setStatus(status);
145 | setError(error);
146 | };
147 |
148 | const handlePress = useCallback(() => {
149 | present();
150 | }, [present]);
151 |
152 | const renderButton = useCallback(() => {
153 | if (loading) {
154 | return ;
155 | }
156 | return ;
157 | }, [loading, handlePress]);
158 |
159 | return (
160 |
161 | {renderButton()}
162 | Status: {status}
163 |
164 | );
165 | }
166 | ```
167 |
168 | There are two types available: StripeError and IdentityVerificationSheetStatus, you can import these in your TypeScript project directly from Stripe Identity React Native SDK:
169 |
170 | ```tsx
171 | import type {
172 | StripeError,
173 | IdentityVerificationSheetStatus,
174 | } from '@stripe/stripe-identity-react-native';
175 | ```
176 |
177 | ## Run the example app
178 |
179 | - Run this command from root folder
180 | - `cd example && yarn`
181 | - Install pods for iOS and update StripeIdentity
182 | - `cd ios && pod install && pod update StripeIdentity`
183 | - Run example app on a specific simulator/emulator from root folder
184 | - `yarn example ios`
185 | - or
186 | - `yarn example android`
187 | - Or from example folder
188 | - `yarn ios`
189 | - or
190 | - `yarn android`
191 |
192 | ## Contributing
193 |
194 | See the [contributor guidelines](CONTRIBUTING.md) to learn how to contribute to the repository.
195 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | // Buildscript is evaluated before everything else so we can't use getExtOrDefault
3 | def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['StripeIdentityReactNative_kotlinVersion']
4 |
5 | repositories {
6 | mavenLocal()
7 | google()
8 | mavenCentral()
9 | jcenter()
10 | }
11 |
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:7.2.2'
14 | // noinspection DifferentKotlinGradleVersion
15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
16 | }
17 | }
18 |
19 | apply plugin: 'com.android.library'
20 | apply plugin: 'kotlin-android'
21 |
22 | def getExtOrDefault(name) {
23 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['StripeIdentityReactNative_' + name]
24 | }
25 |
26 | def getExtOrIntegerDefault(name) {
27 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['StripeIdentityReactNative_' + name]).toInteger()
28 | }
29 |
30 | android {
31 | compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
32 | defaultConfig {
33 | minSdkVersion 16
34 | targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
35 | versionCode 1
36 | versionName "1.0"
37 |
38 | }
39 |
40 | buildTypes {
41 | release {
42 | minifyEnabled false
43 | }
44 | }
45 | lintOptions {
46 | disable 'GradleCompatible'
47 | }
48 | compileOptions {
49 | sourceCompatibility JavaVersion.VERSION_1_8
50 | targetCompatibility JavaVersion.VERSION_1_8
51 | }
52 | }
53 |
54 | repositories {
55 | mavenLocal()
56 | mavenCentral()
57 | jcenter()
58 | google()
59 |
60 | def found = false
61 | def defaultDir = null
62 | def androidSourcesName = 'React Native sources'
63 |
64 | if (rootProject.ext.has('reactNativeAndroidRoot')) {
65 | defaultDir = rootProject.ext.get('reactNativeAndroidRoot')
66 | } else {
67 | defaultDir = new File(
68 | projectDir,
69 | '/../../../node_modules/react-native/android'
70 | )
71 | }
72 |
73 | if (defaultDir.exists()) {
74 | maven {
75 | url defaultDir.toString()
76 | name androidSourcesName
77 | }
78 |
79 | logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
80 | found = true
81 | } else {
82 | def parentDir = rootProject.projectDir
83 |
84 | 1.upto(5, {
85 | if (found) return true
86 | parentDir = parentDir.parentFile
87 |
88 | def androidSourcesDir = new File(
89 | parentDir,
90 | 'node_modules/react-native'
91 | )
92 |
93 | def androidPrebuiltBinaryDir = new File(
94 | parentDir,
95 | 'node_modules/react-native/android'
96 | )
97 |
98 | if (androidPrebuiltBinaryDir.exists()) {
99 | maven {
100 | url androidPrebuiltBinaryDir.toString()
101 | name androidSourcesName
102 | }
103 |
104 | logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
105 | found = true
106 | } else if (androidSourcesDir.exists()) {
107 | maven {
108 | url androidSourcesDir.toString()
109 | name androidSourcesName
110 | }
111 |
112 | logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
113 | found = true
114 | }
115 | })
116 | }
117 |
118 | if (!found) {
119 | throw new GradleException(
120 | "${project.name}: unable to locate React Native android sources. " +
121 | "Ensure you have you installed React Native as a dependency in your project and try again."
122 | )
123 | }
124 | }
125 |
126 | def kotlin_version = getExtOrDefault('kotlinVersion')
127 | def stripe_version = getExtOrDefault('stripeVersion')
128 |
129 | dependencies {
130 | // noinspection GradleDynamicVersion
131 | api 'com.facebook.react:react-native:+'
132 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
133 | implementation("com.stripe:identity:$stripe_version") {
134 | exclude group: 'androidx.emoji2', module: 'emoji2'
135 | }
136 | implementation('androidx.emoji2:emoji2:1.3.0').force // Avoid using 1.4.0 since that requires targetSdkVersion 34
137 | }
138 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # When StripeIdentityReactNative_kotlinVersion and StripeIdentityReactNative_stripeVersion is updated, also need to update StripeSdk_kotlinVersion and StripeSdk_stripeVersion in https://github.com/stripe/stripe-react-native/blob/master/android/gradle.properties
2 | StripeIdentityReactNative_kotlinVersion=1.8.0
3 | StripeIdentityReactNative_stripeVersion=20.52.+
4 | StripeIdentityReactNative_compileSdkVersion=34
5 | StripeIdentityReactNative_targetSdkVersion=34
6 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stripeidentityreactnative/Mappers.kt:
--------------------------------------------------------------------------------
1 | package com.stripeidentityreactnative
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import com.facebook.react.bridge.ReadableMap
6 | import com.facebook.react.bridge.ReadableType
7 |
8 | internal fun toBundleObject(readableMap: ReadableMap?): Bundle? {
9 | val result = Bundle()
10 | if (readableMap == null) {
11 | return result
12 | }
13 | val iterator = readableMap.keySetIterator()
14 | while (iterator.hasNextKey()) {
15 | val key = iterator.nextKey()
16 | when (readableMap.getType(key)) {
17 | ReadableType.Null -> result.putString(key, null)
18 | ReadableType.Boolean -> result.putBoolean(key, readableMap.getBoolean(key))
19 | ReadableType.Number -> try {
20 | result.putInt(key, readableMap.getInt(key))
21 | } catch (e: Exception) {
22 | result.putDouble(key, readableMap.getDouble(key))
23 | }
24 | ReadableType.String -> result.putString(key, readableMap.getString(key))
25 | ReadableType.Map -> result.putBundle(key, toBundleObject(readableMap.getMap(key)))
26 | ReadableType.Array -> Log.e("toBundleException", "Cannot put arrays of objects into bundles. Failed on: $key.")
27 | else -> Log.e("toBundleException", "Could not convert object with key: $key.")
28 | }
29 | }
30 | return result
31 | }
32 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stripeidentityreactnative/StripeIdentityReactNativeModule.kt:
--------------------------------------------------------------------------------
1 | package com.stripeidentityreactnative
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import androidx.appcompat.app.AppCompatActivity
6 | import com.facebook.react.bridge.*
7 |
8 | class StripeIdentityReactNativeModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
9 |
10 | override fun getName(): String {
11 | return "StripeIdentityReactNative"
12 | }
13 |
14 | private var stripeIdentityVerificationSheetFragment: StripeIdentityVerificationSheetFragment? = null
15 | private var initialized = false
16 |
17 | private val mActivityEventListener = object : BaseActivityEventListener() {
18 | override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
19 | if (initialized) {
20 | initialized = false
21 | stripeIdentityVerificationSheetFragment?.activity?.activityResultRegistry?.dispatchResult(requestCode, resultCode, data)
22 | }
23 | }
24 | }
25 |
26 | init {
27 | reactContext.addActivityEventListener(mActivityEventListener)
28 | }
29 |
30 | @ReactMethod
31 | fun initIdentityVerificationSheet(options: ReadableMap, promise: Promise) {
32 | initialized = true
33 | val activity = currentActivity as AppCompatActivity? ?: return
34 |
35 | // If a fragment was already initialized, we want to remove it first
36 | stripeIdentityVerificationSheetFragment?.let {
37 | runCatching {
38 | activity.supportFragmentManager.beginTransaction().remove(it).commitAllowingStateLoss()
39 | }
40 | }
41 | stripeIdentityVerificationSheetFragment = StripeIdentityVerificationSheetFragment().also {
42 | val bundle = toBundleObject(options)
43 | it.arguments = bundle
44 | }
45 |
46 | activity.supportFragmentManager.beginTransaction()
47 | .add(requireNotNull(stripeIdentityVerificationSheetFragment), "identity_sheet_launch_fragment")
48 | .commit()
49 |
50 | promise.resolve(null)
51 | }
52 |
53 | @ReactMethod
54 | fun presentIdentityVerificationSheet(promise: Promise) {
55 | stripeIdentityVerificationSheetFragment?.present(promise)
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stripeidentityreactnative/StripeIdentityReactNativePackage.kt:
--------------------------------------------------------------------------------
1 | package com.stripeidentityreactnative
2 |
3 | import com.facebook.react.ReactPackage
4 | import com.facebook.react.bridge.NativeModule
5 | import com.facebook.react.bridge.ReactApplicationContext
6 | import com.facebook.react.uimanager.ViewManager
7 |
8 |
9 | class StripeIdentityReactNativePackage : ReactPackage {
10 | override fun createNativeModules(reactContext: ReactApplicationContext): List {
11 | return listOf(StripeIdentityReactNativeModule(reactContext))
12 | }
13 |
14 | override fun createViewManagers(reactContext: ReactApplicationContext): List> {
15 | return emptyList()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/android/src/main/java/com/stripeidentityreactnative/StripeIdentityVerificationSheetFragment.kt:
--------------------------------------------------------------------------------
1 | package com.stripeidentityreactnative
2 |
3 | import android.content.ContentResolver
4 | import android.net.Uri
5 | import android.os.Bundle
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.webkit.URLUtil
10 | import android.widget.FrameLayout
11 | import androidx.fragment.app.Fragment
12 | import com.facebook.react.bridge.Promise
13 | import com.facebook.react.bridge.WritableNativeMap
14 | import com.stripe.android.identity.IdentityVerificationSheet
15 | import com.stripe.android.identity.IdentityVerificationSheet.VerificationFlowResult
16 |
17 | class StripeIdentityVerificationSheetFragment : Fragment() {
18 |
19 | private lateinit var identityVerificationSheet: IdentityVerificationSheet
20 | private lateinit var verificationSessionId: String
21 | private lateinit var ephemeralKeySecret: String
22 |
23 | private var promise: Promise? = null
24 |
25 | override fun onCreateView(
26 | inflater: LayoutInflater,
27 | container: ViewGroup?,
28 | savedInstanceState: Bundle?
29 | ): View {
30 | identityVerificationSheet = createIdentityVerificationSheet()
31 | return FrameLayout(requireActivity()).also {
32 | it.visibility = View.GONE
33 | }
34 | }
35 |
36 | private fun createIdentityVerificationSheet(): IdentityVerificationSheet {
37 | verificationSessionId = arguments?.getString("sessionId").orEmpty()
38 | ephemeralKeySecret = arguments?.getString("ephemeralKeySecret").orEmpty()
39 | val imageUriString = arguments?.getBundle("brandLogo")?.getString("uri").orEmpty()
40 | return IdentityVerificationSheet.create(this, IdentityVerificationSheet.Configuration
41 | (brandLogo = getUrlOrResourceId(imageUriString))) {
42 | promise?.let { currentPromise ->
43 | val result = WritableNativeMap()
44 | when (it) {
45 | VerificationFlowResult.Completed -> result.putString("status", "FlowCompleted")
46 | VerificationFlowResult.Canceled -> result.putString("status", "FlowCanceled")
47 | else -> result.putString("status", "FlowFailed")
48 | }
49 | currentPromise.resolve(result)
50 | } ?: run {
51 | throw Exception("No promise is set to handle results")
52 | }
53 |
54 | }
55 | }
56 |
57 | private fun getUrlOrResourceId(uriString: String?): Uri {
58 | return uriString?.let {
59 | if (URLUtil.isValidUrl(it)) {
60 | // Debug mode, Image.resolveAssetSource resolves to local http:// URL
61 | Uri.parse(it)
62 | } else {
63 | // Release mode, Image.resolveAssetSource resolves to a drawable resource
64 | val brandLogoId = resources.getIdentifier(it, "drawable", context?.packageName) // int
65 | Uri.Builder()
66 | .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
67 | .authority(resources.getResourcePackageName(brandLogoId))
68 | .appendPath(resources.getResourceTypeName(brandLogoId))
69 | .appendPath(resources.getResourceEntryName(brandLogoId))
70 | .build()
71 |
72 | }
73 | } ?: Uri.parse("")
74 | }
75 |
76 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
77 | super.onViewCreated(view, savedInstanceState)
78 |
79 | identityVerificationSheet.present(
80 | verificationSessionId = verificationSessionId,
81 | ephemeralKeySecret = ephemeralKeySecret
82 | )
83 | }
84 |
85 | fun present(promise: Promise) {
86 | this.promise = promise
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/docs/api-reference/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/api-reference/assets/highlight.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --light-hl-0: #0000FF;
3 | --dark-hl-0: #569CD6;
4 | --light-hl-1: #000000;
5 | --dark-hl-1: #D4D4D4;
6 | --light-hl-2: #795E26;
7 | --dark-hl-2: #DCDCAA;
8 | --light-hl-3: #0070C1;
9 | --dark-hl-3: #4FC1FF;
10 | --light-hl-4: #AF00DB;
11 | --dark-hl-4: #C586C0;
12 | --light-hl-5: #A31515;
13 | --dark-hl-5: #CE9178;
14 | --light-hl-6: #001080;
15 | --dark-hl-6: #9CDCFE;
16 | --light-hl-7: #008000;
17 | --dark-hl-7: #6A9955;
18 | --light-hl-8: #800000;
19 | --dark-hl-8: #808080;
20 | --light-hl-9: #267F99;
21 | --dark-hl-9: #4EC9B0;
22 | --light-hl-10: #FF0000;
23 | --dark-hl-10: #9CDCFE;
24 | --light-hl-11: #000000FF;
25 | --dark-hl-11: #D4D4D4;
26 | --light-code-background: #F5F5F5;
27 | --dark-code-background: #1E1E1E;
28 | }
29 |
30 | @media (prefers-color-scheme: light) { :root {
31 | --hl-0: var(--light-hl-0);
32 | --hl-1: var(--light-hl-1);
33 | --hl-2: var(--light-hl-2);
34 | --hl-3: var(--light-hl-3);
35 | --hl-4: var(--light-hl-4);
36 | --hl-5: var(--light-hl-5);
37 | --hl-6: var(--light-hl-6);
38 | --hl-7: var(--light-hl-7);
39 | --hl-8: var(--light-hl-8);
40 | --hl-9: var(--light-hl-9);
41 | --hl-10: var(--light-hl-10);
42 | --hl-11: var(--light-hl-11);
43 | --code-background: var(--light-code-background);
44 | } }
45 |
46 | @media (prefers-color-scheme: dark) { :root {
47 | --hl-0: var(--dark-hl-0);
48 | --hl-1: var(--dark-hl-1);
49 | --hl-2: var(--dark-hl-2);
50 | --hl-3: var(--dark-hl-3);
51 | --hl-4: var(--dark-hl-4);
52 | --hl-5: var(--dark-hl-5);
53 | --hl-6: var(--dark-hl-6);
54 | --hl-7: var(--dark-hl-7);
55 | --hl-8: var(--dark-hl-8);
56 | --hl-9: var(--dark-hl-9);
57 | --hl-10: var(--dark-hl-10);
58 | --hl-11: var(--dark-hl-11);
59 | --code-background: var(--dark-code-background);
60 | } }
61 |
62 | body.light {
63 | --hl-0: var(--light-hl-0);
64 | --hl-1: var(--light-hl-1);
65 | --hl-2: var(--light-hl-2);
66 | --hl-3: var(--light-hl-3);
67 | --hl-4: var(--light-hl-4);
68 | --hl-5: var(--light-hl-5);
69 | --hl-6: var(--light-hl-6);
70 | --hl-7: var(--light-hl-7);
71 | --hl-8: var(--light-hl-8);
72 | --hl-9: var(--light-hl-9);
73 | --hl-10: var(--light-hl-10);
74 | --hl-11: var(--light-hl-11);
75 | --code-background: var(--light-code-background);
76 | }
77 |
78 | body.dark {
79 | --hl-0: var(--dark-hl-0);
80 | --hl-1: var(--dark-hl-1);
81 | --hl-2: var(--dark-hl-2);
82 | --hl-3: var(--dark-hl-3);
83 | --hl-4: var(--dark-hl-4);
84 | --hl-5: var(--dark-hl-5);
85 | --hl-6: var(--dark-hl-6);
86 | --hl-7: var(--dark-hl-7);
87 | --hl-8: var(--dark-hl-8);
88 | --hl-9: var(--dark-hl-9);
89 | --hl-10: var(--dark-hl-10);
90 | --hl-11: var(--dark-hl-11);
91 | --code-background: var(--dark-code-background);
92 | }
93 |
94 | .hl-0 { color: var(--hl-0); }
95 | .hl-1 { color: var(--hl-1); }
96 | .hl-2 { color: var(--hl-2); }
97 | .hl-3 { color: var(--hl-3); }
98 | .hl-4 { color: var(--hl-4); }
99 | .hl-5 { color: var(--hl-5); }
100 | .hl-6 { color: var(--hl-6); }
101 | .hl-7 { color: var(--hl-7); }
102 | .hl-8 { color: var(--hl-8); }
103 | .hl-9 { color: var(--hl-9); }
104 | .hl-10 { color: var(--hl-10); }
105 | .hl-11 { color: var(--hl-11); }
106 | pre, code { background: var(--code-background); }
107 |
--------------------------------------------------------------------------------
/docs/api-reference/assets/icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stripe/stripe-identity-react-native/dbd6cc538d55aed9e21c5feac14cdbadebfcf891/docs/api-reference/assets/icons.png
--------------------------------------------------------------------------------
/docs/api-reference/assets/icons@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stripe/stripe-identity-react-native/dbd6cc538d55aed9e21c5feac14cdbadebfcf891/docs/api-reference/assets/icons@2x.png
--------------------------------------------------------------------------------
/docs/api-reference/assets/search.js:
--------------------------------------------------------------------------------
1 | window.searchData = JSON.parse("{\"kinds\":{\"64\":\"Function\",\"1024\":\"Property\",\"65536\":\"Type literal\",\"4194304\":\"Type alias\"},\"rows\":[{\"id\":0,\"kind\":64,\"name\":\"useStripeIdentity\",\"url\":\"modules.html#useStripeIdentity\",\"classes\":\"tsd-kind-function\"},{\"id\":1,\"kind\":64,\"name\":\"presentIdentityVerificationSheet\",\"url\":\"modules.html#presentIdentityVerificationSheet\",\"classes\":\"tsd-kind-function\"},{\"id\":2,\"kind\":4194304,\"name\":\"IdentityVerificationSheetOptions\",\"url\":\"modules.html#IdentityVerificationSheetOptions\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":3,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#IdentityVerificationSheetOptions.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"IdentityVerificationSheetOptions\"},{\"id\":4,\"kind\":1024,\"name\":\"sessionId\",\"url\":\"modules.html#IdentityVerificationSheetOptions.__type.sessionId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IdentityVerificationSheetOptions.__type\"},{\"id\":5,\"kind\":1024,\"name\":\"ephemeralKeySecret\",\"url\":\"modules.html#IdentityVerificationSheetOptions.__type.ephemeralKeySecret\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IdentityVerificationSheetOptions.__type\"},{\"id\":6,\"kind\":1024,\"name\":\"brandLogo\",\"url\":\"modules.html#IdentityVerificationSheetOptions.__type.brandLogo\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IdentityVerificationSheetOptions.__type\"},{\"id\":7,\"kind\":4194304,\"name\":\"IdentityVerificationSheetResult\",\"url\":\"modules.html#IdentityVerificationSheetResult\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":8,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#IdentityVerificationSheetResult.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"IdentityVerificationSheetResult\"},{\"id\":9,\"kind\":1024,\"name\":\"status\",\"url\":\"modules.html#IdentityVerificationSheetResult.__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IdentityVerificationSheetResult.__type\"},{\"id\":10,\"kind\":1024,\"name\":\"error\",\"url\":\"modules.html#IdentityVerificationSheetResult.__type.error\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"IdentityVerificationSheetResult.__type\"},{\"id\":11,\"kind\":4194304,\"name\":\"IdentityVerificationSheetStatus\",\"url\":\"modules.html#IdentityVerificationSheetStatus\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":12,\"kind\":4194304,\"name\":\"StripeError\",\"url\":\"modules.html#StripeError\",\"classes\":\"tsd-kind-type-alias\"},{\"id\":13,\"kind\":65536,\"name\":\"__type\",\"url\":\"modules.html#StripeError.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"StripeError\"},{\"id\":14,\"kind\":1024,\"name\":\"code\",\"url\":\"modules.html#StripeError.__type.code\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":15,\"kind\":1024,\"name\":\"message\",\"url\":\"modules.html#StripeError.__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":16,\"kind\":1024,\"name\":\"localizedMessage\",\"url\":\"modules.html#StripeError.__type.localizedMessage\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":17,\"kind\":1024,\"name\":\"declineCode\",\"url\":\"modules.html#StripeError.__type.declineCode\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":18,\"kind\":1024,\"name\":\"stripeErrorCode\",\"url\":\"modules.html#StripeError.__type.stripeErrorCode\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":19,\"kind\":1024,\"name\":\"type\",\"url\":\"modules.html#StripeError.__type.type\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"StripeError.__type\"},{\"id\":20,\"kind\":4194304,\"name\":\"ErrorType\",\"url\":\"modules.html#ErrorType\",\"classes\":\"tsd-kind-type-alias\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"parent\"],\"fieldVectors\":[[\"name/0\",[0,26.856]],[\"parent/0\",[]],[\"name/1\",[1,26.856]],[\"parent/1\",[]],[\"name/2\",[2,21.748]],[\"parent/2\",[]],[\"name/3\",[3,18.383]],[\"parent/3\",[2,1.805]],[\"name/4\",[4,26.856]],[\"parent/4\",[5,1.526]],[\"name/5\",[6,26.856]],[\"parent/5\",[5,1.526]],[\"name/6\",[7,26.856]],[\"parent/6\",[5,1.526]],[\"name/7\",[8,21.748]],[\"parent/7\",[]],[\"name/8\",[3,18.383]],[\"parent/8\",[8,1.805]],[\"name/9\",[9,26.856]],[\"parent/9\",[10,1.805]],[\"name/10\",[11,26.856]],[\"parent/10\",[10,1.805]],[\"name/11\",[12,26.856]],[\"parent/11\",[]],[\"name/12\",[13,21.748]],[\"parent/12\",[]],[\"name/13\",[3,18.383]],[\"parent/13\",[13,1.805]],[\"name/14\",[14,26.856]],[\"parent/14\",[15,1.012]],[\"name/15\",[16,26.856]],[\"parent/15\",[15,1.012]],[\"name/16\",[17,26.856]],[\"parent/16\",[15,1.012]],[\"name/17\",[18,26.856]],[\"parent/17\",[15,1.012]],[\"name/18\",[19,26.856]],[\"parent/18\",[15,1.012]],[\"name/19\",[20,26.856]],[\"parent/19\",[15,1.012]],[\"name/20\",[21,26.856]],[\"parent/20\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":3,\"name\":{\"3\":{},\"8\":{},\"13\":{}},\"parent\":{}}],[\"brandlogo\",{\"_index\":7,\"name\":{\"6\":{}},\"parent\":{}}],[\"code\",{\"_index\":14,\"name\":{\"14\":{}},\"parent\":{}}],[\"declinecode\",{\"_index\":18,\"name\":{\"17\":{}},\"parent\":{}}],[\"ephemeralkeysecret\",{\"_index\":6,\"name\":{\"5\":{}},\"parent\":{}}],[\"error\",{\"_index\":11,\"name\":{\"10\":{}},\"parent\":{}}],[\"errortype\",{\"_index\":21,\"name\":{\"20\":{}},\"parent\":{}}],[\"identityverificationsheetoptions\",{\"_index\":2,\"name\":{\"2\":{}},\"parent\":{\"3\":{}}}],[\"identityverificationsheetoptions.__type\",{\"_index\":5,\"name\":{},\"parent\":{\"4\":{},\"5\":{},\"6\":{}}}],[\"identityverificationsheetresult\",{\"_index\":8,\"name\":{\"7\":{}},\"parent\":{\"8\":{}}}],[\"identityverificationsheetresult.__type\",{\"_index\":10,\"name\":{},\"parent\":{\"9\":{},\"10\":{}}}],[\"identityverificationsheetstatus\",{\"_index\":12,\"name\":{\"11\":{}},\"parent\":{}}],[\"localizedmessage\",{\"_index\":17,\"name\":{\"16\":{}},\"parent\":{}}],[\"message\",{\"_index\":16,\"name\":{\"15\":{}},\"parent\":{}}],[\"presentidentityverificationsheet\",{\"_index\":1,\"name\":{\"1\":{}},\"parent\":{}}],[\"sessionid\",{\"_index\":4,\"name\":{\"4\":{}},\"parent\":{}}],[\"status\",{\"_index\":9,\"name\":{\"9\":{}},\"parent\":{}}],[\"stripeerror\",{\"_index\":13,\"name\":{\"12\":{}},\"parent\":{\"13\":{}}}],[\"stripeerror.__type\",{\"_index\":15,\"name\":{},\"parent\":{\"14\":{},\"15\":{},\"16\":{},\"17\":{},\"18\":{},\"19\":{}}}],[\"stripeerrorcode\",{\"_index\":19,\"name\":{\"18\":{}},\"parent\":{}}],[\"type\",{\"_index\":20,\"name\":{\"19\":{}},\"parent\":{}}],[\"usestripeidentity\",{\"_index\":0,\"name\":{\"0\":{}},\"parent\":{}}]],\"pipeline\":[]}}");
--------------------------------------------------------------------------------
/docs/api-reference/assets/widgets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stripe/stripe-identity-react-native/dbd6cc538d55aed9e21c5feac14cdbadebfcf891/docs/api-reference/assets/widgets.png
--------------------------------------------------------------------------------
/docs/api-reference/assets/widgets@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stripe/stripe-identity-react-native/dbd6cc538d55aed9e21c5feac14cdbadebfcf891/docs/api-reference/assets/widgets@2x.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Stripe Identity React Native SDK
5 |
10 |
11 |
12 | Redirecting ...
13 |
14 |
15 |
--------------------------------------------------------------------------------
/e2e/app.e2e.js:
--------------------------------------------------------------------------------
1 | /* eslint-env detox/detox, jest */
2 | /* eslint-disable */
3 |
4 | import { getStatusText, pressBack, setupDevice } from './utils';
5 |
6 | describe('Identity', () => {
7 | it('Verify', async () => {
8 | await setupDevice();
9 |
10 | const identityButton = element(by.id('verify-btn'));
11 | await waitFor(identityButton).toBeVisible();
12 | const statusText = await getStatusText('Undefined');
13 | await expect(statusText).toBeVisible();
14 | await identityButton.tap();
15 |
16 | const loadingSpinner = element(by.id('loading-spinner'));
17 |
18 | await expect(loadingSpinner).toNotExist();
19 | await expect(identityButton).toNotExist();
20 | });
21 | it('Cancel', async () => {
22 | await setupDevice();
23 |
24 | const identityButton = element(by.id('verify-btn'));
25 | await waitFor(identityButton).toBeVisible();
26 | await identityButton.tap();
27 | const consentView = await element(
28 | by.id('StripeIdentity.BiometricConsentView')
29 | );
30 | await waitFor(consentView).toBeVisible();
31 | await pressBack();
32 | const statusText = await getStatusText('FlowCanceled');
33 | await expect(statusText).toBeVisible();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/e2e/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "testEnvironment": "./environment",
3 | "testRunner": "jest-circus/runner",
4 | "testTimeout": 480000,
5 | "testRegex": "\\.e2e\\.js$",
6 | "reporters": ["detox/runners/jest/streamlineReporter"],
7 | "verbose": true
8 | }
--------------------------------------------------------------------------------
/e2e/environment.js:
--------------------------------------------------------------------------------
1 | const {
2 | DetoxCircusEnvironment,
3 | SpecReporter,
4 | WorkerAssignReporter,
5 | } = require('detox/runners/jest-circus');
6 |
7 | class CustomDetoxEnvironment extends DetoxCircusEnvironment {
8 | constructor(config, context) {
9 | super(config, context);
10 |
11 | this.initTimeout = 300000;
12 |
13 | this.registerListeners({
14 | SpecReporter,
15 | WorkerAssignReporter,
16 | });
17 | }
18 | }
19 |
20 | module.exports = CustomDetoxEnvironment;
21 |
--------------------------------------------------------------------------------
/e2e/utils.js:
--------------------------------------------------------------------------------
1 | /* eslint-env detox/detox, jest */
2 | /* eslint-disable */
3 |
4 | export const setupDevice = async () => {
5 | await device.launchApp({
6 | newInstance: true,
7 | permissions: { camera: 'YES' },
8 | });
9 |
10 | await device.reloadReactNative();
11 | };
12 | export const pressBack = async () => {
13 | if (device.getPlatform() === 'android') {
14 | await device.pressBack(); // Android only
15 | } else {
16 | await element(by.traits(['button']))
17 | .atIndex(0)
18 | .tap();
19 | }
20 | };
21 |
22 | export const getStatusText = async (status) => {
23 | return element(by.text(`Status: ${status}`));
24 | };
25 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation
19 | * entryFile: "index.android.js",
20 | *
21 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
22 | * bundleCommand: "ram-bundle",
23 | *
24 | * // whether to bundle JS and assets in debug mode
25 | * bundleInDebug: false,
26 | *
27 | * // whether to bundle JS and assets in release mode
28 | * bundleInRelease: true,
29 | *
30 | * // whether to bundle JS and assets in another build variant (if configured).
31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
32 | * // The configuration property can be in the following formats
33 | * // 'bundleIn${productFlavor}${buildType}'
34 | * // 'bundleIn${buildType}'
35 | * // bundleInFreeDebug: true,
36 | * // bundleInPaidRelease: true,
37 | * // bundleInBeta: true,
38 | *
39 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
40 | * // for StripeIdentityReactNativeExample: to disable dev mode in the staging build type (if configured)
41 | * devDisabledInStaging: true,
42 | * // The configuration property can be in the following formats
43 | * // 'devDisabledIn${productFlavor}${buildType}'
44 | * // 'devDisabledIn${buildType}'
45 | *
46 | * // the root of your project, i.e. where "package.json" lives
47 | * root: "../../",
48 | *
49 | * // where to put the JS bundle asset in debug mode
50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
51 | *
52 | * // where to put the JS bundle asset in release mode
53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
54 | *
55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
56 | * // require('./image.png')), in debug mode
57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
58 | *
59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
60 | * // require('./image.png')), in release mode
61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
62 | *
63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
67 | * // for StripeIdentityReactNativeExample, you might want to remove it from here.
68 | * inputExcludes: ["android/**", "ios/**"],
69 | *
70 | * // override which node gets called and with what additional arguments
71 | * nodeExecutableAndArgs: ["node"],
72 | *
73 | * // supply additional arguments to the packager
74 | * extraPackagerArgs: []
75 | * ]
76 | */
77 |
78 | project.ext.react = [
79 | enableHermes: false, // clean and rebuild if changing
80 | entryFile: "index.js",
81 | ]
82 |
83 | apply from: "../../node_modules/react-native/react.gradle"
84 |
85 | /**
86 | * Set this to true to create two separate APKs instead of one:
87 | * - An APK that only works on ARM devices
88 | * - An APK that only works on x86 devices
89 | * The advantage is the size of the APK is reduced by about 4MB.
90 | * Upload all the APKs to the Play Store and people will download
91 | * the correct one based on the CPU architecture of their device.
92 | */
93 | def enableSeparateBuildPerCPUArchitecture = false
94 |
95 | /**
96 | * Run Proguard to shrink the Java bytecode in release builds.
97 | */
98 | def enableProguardInReleaseBuilds = false
99 |
100 | /**
101 | * The preferred build flavor of JavaScriptCore.
102 | *
103 | * For StripeIdentityReactNativeExample, to use the international variant, you can use:
104 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
105 | *
106 | * The international variant includes ICU i18n library and necessary data
107 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
108 | * give correct results when using with locales other than en-US. Note that
109 | * this variant is about 6MiB larger per architecture than default.
110 | */
111 | def jscFlavor = 'org.webkit:android-jsc:+'
112 |
113 | /**
114 | * Whether to enable the Hermes VM.
115 | *
116 | * This should be set on project.ext.react and that value will be read here. If it is not set
117 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
118 | * and the benefits of using Hermes will therefore be sharply reduced.
119 | */
120 | def enableHermes = project.ext.react.get("enableHermes", false);
121 |
122 | /**
123 | * Architectures to build native code for.
124 | */
125 | def reactNativeArchitectures() {
126 | def value = project.getProperties().get("reactNativeArchitectures")
127 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
128 | }
129 |
130 | android {
131 | ndkVersion rootProject.ext.ndkVersion
132 | compileSdkVersion rootProject.ext.compileSdkVersion
133 |
134 | dexOptions {
135 | javaMaxHeapSize "4G"
136 | }
137 |
138 | defaultConfig {
139 | applicationId "com.example.stripeidentityreactnative"
140 | minSdkVersion rootProject.ext.minSdkVersion
141 | targetSdkVersion rootProject.ext.targetSdkVersion
142 | versionCode 1
143 | versionName "1.0"
144 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
145 | if (isNewArchitectureEnabled()) {
146 | // We configure the NDK build only if you decide to opt-in for the New Architecture.
147 | externalNativeBuild {
148 | ndkBuild {
149 | arguments "APP_PLATFORM=android-21",
150 | "APP_STL=c++_shared",
151 | "NDK_TOOLCHAIN_VERSION=clang",
152 | "GENERATED_SRC_DIR=$buildDir/generated/source",
153 | "PROJECT_BUILD_DIR=$buildDir",
154 | "REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
155 | "REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
156 | "NODE_MODULES_DIR=$rootDir/../node_modules"
157 | cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
158 | cppFlags "-std=c++17"
159 | // Make sure this target name is the same you specify inside the
160 | // src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
161 | targets "stripeidentityreactnative_appmodules"
162 | }
163 | }
164 | if (!enableSeparateBuildPerCPUArchitecture) {
165 | ndk {
166 | abiFilters (*reactNativeArchitectures())
167 | }
168 | }
169 | }
170 | }
171 |
172 | if (isNewArchitectureEnabled()) {
173 | // We configure the NDK build only if you decide to opt-in for the New Architecture.
174 | externalNativeBuild {
175 | ndkBuild {
176 | path "$projectDir/src/main/jni/Android.mk"
177 | }
178 | }
179 | def reactAndroidProjectDir = project(':ReactAndroid').projectDir
180 | def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
181 | dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
182 | from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
183 | into("$buildDir/react-ndk/exported")
184 | }
185 | def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
186 | dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
187 | from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
188 | into("$buildDir/react-ndk/exported")
189 | }
190 | afterEvaluate {
191 | // If you wish to add a custom TurboModule or component locally,
192 | // you should uncomment this line.
193 | // preBuild.dependsOn("generateCodegenArtifactsFromSchema")
194 | preDebugBuild.dependsOn(packageReactNdkDebugLibs)
195 | preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
196 | // Due to a bug inside AGP, we have to explicitly set a dependency
197 | // between configureNdkBuild* tasks and the preBuild tasks.
198 | // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
199 | configureNdkBuildRelease.dependsOn(preReleaseBuild)
200 | configureNdkBuildDebug.dependsOn(preDebugBuild)
201 | reactNativeArchitectures().each { architecture ->
202 | tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
203 | dependsOn("preDebugBuild")
204 | }
205 | tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
206 | dependsOn("preReleaseBuild")
207 | }
208 | }
209 | }
210 | }
211 |
212 | splits {
213 | abi {
214 | reset()
215 | enable enableSeparateBuildPerCPUArchitecture
216 | universalApk false // If true, also generate a universal APK
217 | include (*reactNativeArchitectures())
218 | }
219 | }
220 | signingConfigs {
221 | debug {
222 | storeFile file('debug.keystore')
223 | storePassword 'android'
224 | keyAlias 'androiddebugkey'
225 | keyPassword 'android'
226 | }
227 | }
228 | buildTypes {
229 | debug {
230 | signingConfig signingConfigs.debug
231 | }
232 | release {
233 | // Caution! In production, you need to generate your own keystore file.
234 | // see https://reactnative.dev/docs/signed-apk-android.
235 | signingConfig signingConfigs.debug
236 | minifyEnabled enableProguardInReleaseBuilds
237 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
238 | }
239 | }
240 | // applicationVariants are e.g. debug, release
241 | applicationVariants.all { variant ->
242 | variant.outputs.each { output ->
243 | // For each separate APK per architecture, set a unique version code as described here:
244 | // https://developer.android.com/studio/build/configure-apk-splits.html
245 | // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
246 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
247 | def abi = output.getFilter(OutputFile.ABI)
248 | if (abi != null) { // null for the universal-debug, universal-release variants
249 | output.versionCodeOverride =
250 | defaultConfig.versionCode * 1000 + versionCodes.get(abi)
251 | }
252 |
253 | }
254 | }
255 | }
256 |
257 | dependencies {
258 | implementation fileTree(dir: "libs", include: ["*.jar"])
259 | //noinspection GradleDynamicVersion
260 | implementation "com.facebook.react:react-native:+" // From node_modules
261 | implementation 'com.google.android.material:material:1.7.0'
262 |
263 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
264 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
265 | exclude group:'com.facebook.fbjni'
266 | }
267 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
268 | exclude group:'com.facebook.flipper'
269 | exclude group:'com.squareup.okhttp3', module:'okhttp'
270 | }
271 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
272 | exclude group:'com.facebook.flipper'
273 | }
274 |
275 | if (enableHermes) {
276 | //noinspection GradleDynamicVersion
277 | implementation("com.facebook.react:hermes-engine:+") { // From node_modules
278 | exclude group:'com.facebook.fbjni'
279 | }
280 | } else {
281 | implementation jscFlavor
282 | }
283 |
284 | implementation project(':stripeidentityreactnative')
285 | }
286 |
287 | if (isNewArchitectureEnabled()) {
288 | // If new architecture is enabled, we let you build RN from source
289 | // Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
290 | // This will be applied to all the imported transtitive dependency.
291 | configurations.all {
292 | resolutionStrategy.dependencySubstitution {
293 | substitute(module("com.facebook.react:react-native"))
294 | .using(project(":ReactAndroid"))
295 | .because("On New Architecture we're building React Native from source")
296 | substitute(module("com.facebook.react:hermes-engine"))
297 | .using(project(":ReactAndroid:hermes-engine"))
298 | .because("On New Architecture we're building Hermes from source")
299 | }
300 | }
301 | }
302 |
303 | // Run this once to be able to run the application with BUCK
304 | // puts all compile dependencies into folder libs for BUCK to use
305 | task copyDownloadableDepsToLibs(type: Copy) {
306 | from configurations.implementation
307 | into 'libs'
308 | }
309 |
310 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
311 |
312 | def isNewArchitectureEnabled() {
313 | // To opt-in for the New Architecture, you can either:
314 | // - Set `newArchEnabled` to true inside the `gradle.properties` file
315 | // - Invoke gradle with `-newArchEnabled=true`
316 | // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
317 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
318 | }
319 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stripe/stripe-identity-react-native/dbd6cc538d55aed9e21c5feac14cdbadebfcf891/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/example/stripeidentityreactnative/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | *
This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.example.stripeidentityreactnative;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceEventListener;
23 | import com.facebook.react.ReactInstanceManager;
24 | import com.facebook.react.bridge.ReactContext;
25 | import com.facebook.react.modules.network.NetworkingModule;
26 | import okhttp3.OkHttpClient;
27 |
28 | public class ReactNativeFlipper {
29 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
30 | if (FlipperUtils.shouldEnableFlipper(context)) {
31 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
33 | client.addPlugin(new ReactFlipperPlugin());
34 | client.addPlugin(new DatabasesFlipperPlugin(context));
35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
36 | client.addPlugin(CrashReporterPlugin.getInstance());
37 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
38 | NetworkingModule.setCustomClientBuilder(
39 | new NetworkingModule.CustomClientBuilder() {
40 | @Override
41 | public void apply(OkHttpClient.Builder builder) {
42 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
43 | }
44 | });
45 | client.addPlugin(networkFlipperPlugin);
46 | client.start();
47 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
48 | // Hence we run if after all native modules have been initialized
49 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
50 | if (reactContext == null) {
51 | reactInstanceManager.addReactInstanceEventListener(
52 | new ReactInstanceEventListener() {
53 | @Override
54 | public void onReactContextInitialized(ReactContext reactContext) {
55 | reactInstanceManager.removeReactInstanceEventListener(this);
56 | reactContext.runOnNativeModulesQueueThread(
57 | new Runnable() {
58 | @Override
59 | public void run() {
60 | client.addPlugin(new FrescoFlipperPlugin());
61 | }
62 | });
63 | }
64 | });
65 | } else {
66 | client.addPlugin(new FrescoFlipperPlugin());
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/stripeidentityreactnative/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.stripeidentityreactnative;
2 |
3 | import android.os.Bundle;
4 | import com.facebook.react.ReactActivity;
5 | import com.facebook.react.ReactActivityDelegate;
6 | import com.facebook.react.ReactRootView;
7 |
8 | public class MainActivity extends ReactActivity {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | @Override
15 | protected String getMainComponentName() {
16 | return "StripeIdentityReactNativeExample";
17 | }
18 |
19 | /**
20 | * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
21 | * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
22 | * (Paper).
23 | */
24 | @Override
25 | protected ReactActivityDelegate createReactActivityDelegate() {
26 | return new MainActivityDelegate(this, getMainComponentName());
27 | }
28 | public static class MainActivityDelegate extends ReactActivityDelegate {
29 | public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
30 | super(activity, mainComponentName);
31 | }
32 | @Override
33 | protected ReactRootView createRootView() {
34 | ReactRootView reactRootView = new ReactRootView(getContext());
35 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
36 | reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
37 | return reactRootView;
38 | }
39 | @Override
40 | protected boolean isConcurrentRootEnabled() {
41 | // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
42 | // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
43 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
44 | }
45 | }
46 |
47 | @Override
48 | protected void onCreate(Bundle savedInstanceState) {
49 | super.onCreate(null);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/stripeidentityreactnative/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.stripeidentityreactnative;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.config.ReactFeatureFlags;
10 | import com.facebook.react.ReactInstanceManager;
11 | import com.facebook.soloader.SoLoader;
12 | import com.example.stripeidentityreactnative.newarchitecture.MainApplicationReactNativeHost;
13 | import java.lang.reflect.InvocationTargetException;
14 | import java.util.List;
15 | import com.stripeidentityreactnative.StripeIdentityReactNativePackage;
16 |
17 | public class MainApplication extends Application implements ReactApplication {
18 |
19 | private final ReactNativeHost mReactNativeHost =
20 | new ReactNativeHost(this) {
21 | @Override
22 | public boolean getUseDeveloperSupport() {
23 | return BuildConfig.DEBUG;
24 | }
25 |
26 | @Override
27 | protected List getPackages() {
28 | @SuppressWarnings("UnnecessaryLocalVariable")
29 | List packages = new PackageList(this).getPackages();
30 | // Packages that cannot be autolinked yet can be added manually here, for StripeIdentityReactNativeExample:
31 | // packages.add(new MyReactNativePackage());
32 | packages.add(new StripeIdentityReactNativePackage());
33 | return packages;
34 | }
35 |
36 | @Override
37 | protected String getJSMainModuleName() {
38 | return "index";
39 | }
40 | };
41 |
42 | private final ReactNativeHost mNewArchitectureNativeHost =
43 | new MainApplicationReactNativeHost(this);
44 |
45 | @Override
46 | public ReactNativeHost getReactNativeHost() {
47 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
48 | return mNewArchitectureNativeHost;
49 | } else {
50 | return mReactNativeHost;
51 | }
52 | }
53 |
54 | @Override
55 | public void onCreate() {
56 | super.onCreate();
57 | // If you opted-in for the New Architecture, we enable the TurboModule system
58 | ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
59 | SoLoader.init(this, /* native exopackage */ false);
60 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); // Remove this line if you don't want Flipper enabled
61 | }
62 |
63 | /**
64 | * Loads Flipper in React Native templates.
65 | *
66 | * @param context
67 | */
68 | private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
69 | if (BuildConfig.DEBUG) {
70 | try {
71 | /*
72 | We use reflection here to pick up the class that initializes Flipper,
73 | since Flipper library is not available in release mode
74 | */
75 | Class> aClass = Class.forName("com.example.stripeidentityreactnative.ReactNativeFlipper");
76 | aClass
77 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
78 | .invoke(null, context, reactInstanceManager);
79 | } catch (ClassNotFoundException e) {
80 | e.printStackTrace();
81 | } catch (NoSuchMethodException e) {
82 | e.printStackTrace();
83 | } catch (IllegalAccessException e) {
84 | e.printStackTrace();
85 | } catch (InvocationTargetException e) {
86 | e.printStackTrace();
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/stripeidentityreactnative/newarchitecture/MainApplicationReactNativeHost.java:
--------------------------------------------------------------------------------
1 | package com.example.stripeidentityreactnative.newarchitecture;
2 |
3 | import android.app.Application;
4 | import androidx.annotation.NonNull;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactInstanceManager;
7 | import com.facebook.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
10 | import com.facebook.react.bridge.JSIModulePackage;
11 | import com.facebook.react.bridge.JSIModuleProvider;
12 | import com.facebook.react.bridge.JSIModuleSpec;
13 | import com.facebook.react.bridge.JSIModuleType;
14 | import com.facebook.react.bridge.JavaScriptContextHolder;
15 | import com.facebook.react.bridge.ReactApplicationContext;
16 | import com.facebook.react.bridge.UIManager;
17 | import com.facebook.react.fabric.ComponentFactory;
18 | import com.facebook.react.fabric.CoreComponentsRegistry;
19 | import com.facebook.react.fabric.FabricJSIModuleProvider;
20 | import com.facebook.react.fabric.ReactNativeConfig;
21 | import com.facebook.react.uimanager.ViewManagerRegistry;
22 | import com.example.stripeidentityreactnative.BuildConfig;
23 | import com.example.stripeidentityreactnative.newarchitecture.components.MainComponentsRegistry;
24 | import com.example.stripeidentityreactnative.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 | /**
28 | * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
29 | * TurboModule delegates and the Fabric Renderer.
30 | *
31 | *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
32 | * `newArchEnabled` property). Is ignored otherwise.
33 | */
34 | public class MainApplicationReactNativeHost extends ReactNativeHost {
35 | public MainApplicationReactNativeHost(Application application) {
36 | super(application);
37 | }
38 | @Override
39 | public boolean getUseDeveloperSupport() {
40 | return BuildConfig.DEBUG;
41 | }
42 | @Override
43 | protected List getPackages() {
44 | List packages = new PackageList(this).getPackages();
45 | // Packages that cannot be autolinked yet can be added manually here, for example:
46 | // packages.add(new MyReactNativePackage());
47 | // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
48 | // packages.add(new TurboReactPackage() { ... });
49 | // If you have custom Fabric Components, their ViewManagers should also be loaded here
50 | // inside a ReactPackage.
51 | return packages;
52 | }
53 | @Override
54 | protected String getJSMainModuleName() {
55 | return "index";
56 | }
57 | @NonNull
58 | @Override
59 | protected ReactPackageTurboModuleManagerDelegate.Builder
60 | getReactPackageTurboModuleManagerDelegateBuilder() {
61 | // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
62 | // for the new architecture and to use TurboModules correctly.
63 | return new MainApplicationTurboModuleManagerDelegate.Builder();
64 | }
65 | @Override
66 | protected JSIModulePackage getJSIModulePackage() {
67 | return new JSIModulePackage() {
68 | @Override
69 | public List getJSIModules(
70 | final ReactApplicationContext reactApplicationContext,
71 | final JavaScriptContextHolder jsContext) {
72 | final List specs = new ArrayList<>();
73 | // Here we provide a new JSIModuleSpec that will be responsible of providing the
74 | // custom Fabric Components.
75 | specs.add(
76 | new JSIModuleSpec() {
77 | @Override
78 | public JSIModuleType getJSIModuleType() {
79 | return JSIModuleType.UIManager;
80 | }
81 | @Override
82 | public JSIModuleProvider getJSIModuleProvider() {
83 | final ComponentFactory componentFactory = new ComponentFactory();
84 | CoreComponentsRegistry.register(componentFactory);
85 | // Here we register a Components Registry.
86 | // The one that is generated with the template contains no components
87 | // and just provides you the one from React Native core.
88 | MainComponentsRegistry.register(componentFactory);
89 | final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
90 | ViewManagerRegistry viewManagerRegistry =
91 | new ViewManagerRegistry(
92 | reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
93 | return new FabricJSIModuleProvider(
94 | reactApplicationContext,
95 | componentFactory,
96 | ReactNativeConfig.DEFAULT_CONFIG,
97 | viewManagerRegistry);
98 | }
99 | });
100 | return specs;
101 | }
102 | };
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/stripeidentityreactnative/newarchitecture/components/MainComponentsRegistry.java:
--------------------------------------------------------------------------------
1 | package com.example.stripeidentityreactnative.newarchitecture.components;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.proguard.annotations.DoNotStrip;
5 | import com.facebook.react.fabric.ComponentFactory;
6 | import com.facebook.soloader.SoLoader;
7 | /**
8 | * Class responsible to load the custom Fabric Components. This class has native methods and needs a
9 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
10 | * folder for you).
11 | *
12 | *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
13 | * `newArchEnabled` property). Is ignored otherwise.
14 | */
15 | @DoNotStrip
16 | public class MainComponentsRegistry {
17 | static {
18 | SoLoader.loadLibrary("fabricjni");
19 | }
20 | @DoNotStrip private final HybridData mHybridData;
21 | @DoNotStrip
22 | private native HybridData initHybrid(ComponentFactory componentFactory);
23 | @DoNotStrip
24 | private MainComponentsRegistry(ComponentFactory componentFactory) {
25 | mHybridData = initHybrid(componentFactory);
26 | }
27 | @DoNotStrip
28 | public static MainComponentsRegistry register(ComponentFactory componentFactory) {
29 | return new MainComponentsRegistry(componentFactory);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/stripeidentityreactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java:
--------------------------------------------------------------------------------
1 | package com.example.stripeidentityreactnative.newarchitecture.modules;
2 |
3 | import com.facebook.jni.HybridData;
4 | import com.facebook.react.ReactPackage;
5 | import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.soloader.SoLoader;
8 | import java.util.List;
9 | /**
10 | * Class responsible to load the TurboModules. This class has native methods and needs a
11 | * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
12 | * folder for you).
13 | *
14 | *