Skip to content

Commit 8db562d

Browse files
wcastandSkalakid
andauthored
feat: add expo plugin and example (#49)
Co-authored-by: Michał Skałka <michal.skalka@swmansion.com>
1 parent a17cde7 commit 8db562d

98 files changed

Lines changed: 26206 additions & 6989 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
# Output of the build process & scripts
88
lib/**/*
9+
plugin/build/**/*
910
scripts/**/*
1011

1112
babel.config.js
@@ -14,3 +15,4 @@ react-native.config.js
1415
jest.config.js
1516
webpack.config.js
1617
.eslintrc.js
18+
app.plugin.js

.eslintrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module.exports = {
2929
},
3030
},
3131
root: true,
32+
ignorePatterns: ['plugins/build/**'],
3233
rules: {
3334
'rulesdir/prefer-underscore-method': 'off',
3435
'rulesdir/prefer-import-module-contents': 'off',
@@ -66,5 +67,11 @@ module.exports = {
6667
'@typescript-eslint/array-type': ['error', {default: 'array-simple'}],
6768
'@typescript-eslint/consistent-type-definitions': 'off',
6869
'curly': ['error', 'all'],
70+
'@lwc/lwc/no-async-await': 'off',
71+
'no-return-await': 'off',
72+
'no-else-return': 'off',
73+
'import/prefer-default-export': 'off',
74+
'no-restricted-imports': 'off',
75+
'react/destructuring-assignment': 'off',
6976
},
7077
};

.github/workflows/typescript.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ jobs:
3232
- name: Typecheck library
3333
run: npm run typecheck -- --project tsconfig.json
3434

35-
- name: Typecheck example app
36-
run: npm run typecheck -- --project example/tsconfig.json
35+
- name: Typecheck common app
36+
run: npm run typecheck -- --project apps/common-app/tsconfig.json

.gitignore

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ android.iml
3939

4040
# Cocoapods
4141
#
42-
example/ios/Pods
42+
apps/basic-example/ios/Pods
4343

4444
# Ruby
45-
example/vendor/
45+
apps/basic-example/vendor/
4646

4747
# node.js
4848
#
@@ -66,6 +66,10 @@ ios/generated
6666
android/generated
6767

6868
# Android libs (Google Tap And Pay SDK)
69-
example/android/libs
69+
apps/basic-example/android/libs
7070

7171
.kotlin/
72+
73+
# expo plugin build
74+
plugin/build/
75+
*.tsbuildinfo

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node-linker=hoisted

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CODE_OF_CONDUCT.md
66
.well-known
77
desktop/dist/**/*.js
88
dist/**/*.js
9+
plugin/build/**/*.js
910
assets/animations
1011
android
1112
ios

README.md

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
- ♻️ Universal solution (Apple Wallet and Google Wallet)
66
- 💳 Easy and secure addition of payment cards from your app directly
77
- 💰 Supports Visa, MasterCard, Amex and Discover payment cards
8+
- 🎉 Expo support (expo-plugin)
89

910
## Getting started
1011

11-
Using the `react-native-wallet` Push Provisioning features requires proper configuration and access from both Google and Apple.
12+
Using the `react-native-wallet` Push Provisioning features requires proper configuration and access from both Google and Apple.
1213
Please follow the instructions below before installing the library:
1314

1415
### Android
@@ -20,10 +21,10 @@ To be able to interact with the Google Wallet on the Android please make sure to
2021
1. Visit [the Google Pay Android Push Provisioning API documentation](https://developers.google.com/pay/issuers/apis/push-provisioning/android/) and request access to it.
2122

2223
2. Once getting an approval from the Google team
23-
1. Download the [TapAndPay SDK](https://developers.google.com/pay/issuers/apis/push-provisioning/android/releases).
24-
2. Unzip it and extract the SDK into the `/android/libs` folder in your React Native project (if there is no `libs` folder, create one).
24+
1. Download the [TapAndPay SDK](https://developers.google.com/pay/issuers/apis/push-provisioning/android/releases).
25+
2. Unzip it and extract the SDK into the `/android/libs` folder in your React Native project (if there is no `libs` folder, create one).
2526
3. Add `/android/libs` to `.gitignore`.
26-
27+
2728
3. Then connect the SDK to your project in `build.gradle`, for example like in [example/android/build.gradle](https://github.com/Expensify/react-native-wallet/blob/main/example/android/build.gradle):
2829

2930
```groovy
@@ -37,7 +38,7 @@ allprojects {
3738

3839
#### Step 2: Whitelist your app for SDK use.
3940

40-
To use the Google SDK in your app, you will need to whitelist your app details. Without it, calling some functions will result in a `Not verified` error.
41+
To use the Google SDK in your app, you will need to whitelist your app details. Without it, calling some functions will result in a `Not verified` error.
4142
To resolve it, please follow the instructions from [the official Google documentation](https://developers.google.com/pay/issuers/apis/push-provisioning/android/allowlist).
4243

4344
For your builds, you will need to prepare your app's `package name` and `fingerprint` following [these steps](https://developers.google.com/pay/issuers/apis/push-provisioning/android/allowlist#how_to_get_your_apps_fingerprint). The values should, for example, look like this:
@@ -72,13 +73,13 @@ Make sure to familiarize yourself with that document before deploying your app.
7273

7374
### Step 2: Activate the entitlement
7475

75-
After getting a positive response from Apple, open the developer portal panel and search `Certificates, Identifiers & Profiles` -> `Profiles` -> `Our distribution profile` -> `Edit` and add the `ApplePay In-App Provisioning Distribution` entitlement.
76+
After getting a positive response from Apple, open the developer portal panel and search `Certificates, Identifiers & Profiles` -> `Profiles` -> `Our distribution profile` -> `Edit` and add the `ApplePay In-App Provisioning Distribution` entitlement.
7677
It’s available only for the production environment so your QA must work with physical devices and cards.
7778

7879

7980
### Step 3: Add the entitlement to your project
8081

81-
Add `com.apple.developer.payment-pass-provisioning` entitlement to your project. Find or create `.entitlements` file in your project and add the entitlement like below (similarly to [WalletExample.entitlements](https://github.com/Expensify/react-native-wallet/blob/main/example/ios/WalletExample/WalletExample.entitlements)):
82+
Add `com.apple.developer.payment-pass-provisioning` entitlement to your project. Find or create `.entitlements` file in your project and add the entitlement like below (similarly to [WalletExample.entitlements](https://github.com/Expensify/react-native-wallet/blob/main/example/ios/WalletExample/WalletExample.entitlements)):
8283

8384
```xml
8485
<?xml version="1.0" encoding="UTF-8"?>
@@ -105,14 +106,44 @@ or
105106
yarn add @expensify/react-native-wallet
106107
```
107108

109+
### Expo plugin
110+
111+
To use `@expensify/react-native-wallet` with expo, you will need to use the expo-plugin.
112+
113+
In your `app.json` file, add the following configuration:
114+
115+
```json
116+
{
117+
"expo": {
118+
"plugins": [
119+
[
120+
"@expensify/react-native-wallet",
121+
{
122+
enableApplePayProvisioning: true,
123+
googleTapAndPaySdkPath: "./libs/tapandpay-v18.7.0.zip", // path to the Google Tap & Pay SDK zip file
124+
},
125+
],
126+
]
127+
}
128+
}
129+
```
108130

131+
You will need to rebuild your app after that since the lib has native files.
132+
133+
```bash
134+
npx expo prebuild --clean
135+
npx expo run:ios
136+
npx expo run:android
137+
```
109138

110-
## Required data
139+
140+
141+
## Required data
111142
Here you can find data elements used in the library, essential to work with Google Wallet and Apple Wallet APIs.
112143

113144
### Android
114145
- **Opaque Payment Card** (OPC) - a binary blob of information Google Pay receives from the issuer app that could be presented to TSP to receive a token.
115-
- **Token Service Provider** (TSP) - a service that enhances payment security by replacing a credit card number during transactions with a unique digital identifier - token. The TSP specifies the tokenization service used to create a given token e.g. Visa, MasterCard, American Express.
146+
- **Token Service Provider** (TSP) - a service that enhances payment security by replacing a credit card number during transactions with a unique digital identifier - token. The TSP specifies the tokenization service used to create a given token e.g. Visa, MasterCard, American Express.
116147
- **Token Reference ID** - a unique identifying number to refer to a DPAN (Dynamic Personal Account Number). Token Providers will assign each DPAN an issuer token ID at the time of tokenization.
117148

118149
### iOS
@@ -170,10 +201,10 @@ The library offers seven functions for seamless integration and use of the Apple
170201
### `AddToWalletButton`
171202

172203
A ready-to-use component that simplifies the addition of payment cards to Google Wallet and Apple Wallet. The button automatically adapts its appearance according to the platform and language specified.
173-
It uses official assets provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) in their Wallet-related branding guidelines.
204+
It uses official assets provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) in their Wallet-related branding guidelines.
174205

175206
> [!IMPORTANT]
176-
> Please bear in mind the brand rules provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) when adding this component to your application.
207+
> Please bear in mind the brand rules provided by [Google](https://developers.google.com/wallet/generic/resources/brand-guidelines) and [Apple](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/) when adding this component to your application.
177208
178209
Adhering to these guidelines is crucial not only to comply with legal requirements but also to reassure users of the authenticity and security of your application.
179210

@@ -204,6 +235,40 @@ Adhering to these guidelines is crucial not only to comply with legal requiremen
204235
|:----:|:---------------:|
205236
| <img src="./assets/buttons/android_button.svg" height="50" /> | <img src="./assets/buttons/ios_button.svg" height="50" /> |
206237

238+
# Hex Encoding
239+
240+
This library use base64 encoding to encode the data. Yours might use hex encoding.
241+
242+
If that is the case, you will need to convert the data in the proper format.
243+
244+
This is an example of how to convert data to hex format:
245+
246+
```ts
247+
import { Buffer } from "buffer"
248+
const base64ToHex = (base64: string): string => Buffer.from(base64, "base64").toString("hex")
249+
250+
[...]
251+
252+
const issuerEncryptPayloadCallback = async (
253+
nonce: string,
254+
nonceSignature: string,
255+
certificate: string[],
256+
): Promise<IOSEncryptPayload> => {
257+
try {
258+
const payload = {
259+
encryptionDetails: {
260+
nonce: base64ToHex(nonce),
261+
nonceSignature: base64ToHex(nonceSignature),
262+
wspCertificates: certificate,
263+
},
264+
serialNumber,
265+
wspId: "APPLE" as const,
266+
}
267+
[...]
268+
```
269+
270+
This will depend on the implementation of your backend/issuer so make sure to check with them otherwise IOS might fail to provision the card.
271+
207272
# Publishing your app
208273
209274
To successfully publish your app, you will need to navigate through a series of mandatory test cases on both platforms.
@@ -214,14 +279,14 @@ Before deploying your app to the Google Play Store, make sure you have taken car
214279
215280
The latest information about deploying apps with Google TapAndPay SDK can be found in the [pre-launch process](https://developers.google.com/pay/issuers/apis/push-provisioning/android/launch-process#step_3_issuer_app_product_review) and [beta tests](https://developers.google.com/pay/issuers/apis/push-provisioning/android/beta-testing) sections in Google documentation. Make sure to complete all of the steps specified by Google connected to the __Google's branding__, __API safety__, and __app stability__.
216281
217-
The app will need to be reviewed by Google. During this process, it will need to pass 4 mandatory test cases that are specified [here](https://developers.google.com/pay/issuers/apis/push-provisioning/android/test-cases). They verify how your app handles card state tracking in different scenarios.
282+
The app will need to be reviewed by Google. During this process, it will need to pass 4 mandatory test cases that are specified [here](https://developers.google.com/pay/issuers/apis/push-provisioning/android/test-cases). They verify how your app handles card state tracking in different scenarios.
218283
219284
> [!NOTE]
220285
>Please make sure to hide the `Add to Google Wallet` buttons when cards are already added to the wallet.
221286
222287
### iOS
223288
224-
When implementing the In-App Push Provisioning feature in your App make sure that your app follows Apple's [branding guidelines connected to Apple Wallet](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/). Remember that you must not create your own buttons or your app could be rejected at revision. You can use the[ AddWalletButton component](#components) instead!
289+
When implementing the In-App Push Provisioning feature in your App make sure that your app follows Apple's [branding guidelines connected to Apple Wallet](https://developer.apple.com/wallet/add-to-apple-wallet-guidelines/). Remember that you must not create your own buttons or your app could be rejected at revision. You can use the[ AddWalletButton component](#components) instead!
225290
When the pass is already provisioned, make sure to hide this button and replace it with text like `Added to Apple Wallet`. The card is fully provisioned once it added to your main device (user's iPhone) and all linked devices (for example Apple Watch).
226291
227292
Next to branding guidelines, please follow the instructions and best practices from [the In-App provisioning documentation]((#ios)) provided by Apple.
@@ -246,7 +311,6 @@ Additionally, when submitting your app to the App Store, you must include:
246311
247312
`@expensify/react-native-wallet` is compatible with the five latest minor releases of React Native (≥0.76.0) and works exclusively with the new architecture.
248313
249-
250314
# Contributing
251315
252316
Contributions to this library are done under [https://github.com/Expensify/App](https://github.com/Expensify/App). Please refer to that repo and all its guidelines for contributing.

app.plugin.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// This file configures the entry file for your plugin.
2+
module.exports = require('./plugins/build');

0 commit comments

Comments
 (0)