Skip to content

Commit 46e06e1

Browse files
docs: update acbf4a6
0 parents  commit 46e06e1

370 files changed

Lines changed: 5461 additions & 0 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.

.nojekyll

Whitespace-only changes.

GooglePay.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These docs have moved
2+
3+
[You can find the Google Pay integration guide here](https://stripe.com/docs/google-pay?platform=react-native).

Platform-Pay-Migration.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# `isApplePaySupported` and `isGooglePaySupported`
2+
3+
`isApplePaySupported` and `isGooglePaySupported` have both been replaced by `isPlatformPaySupported`.
4+
5+
`isPlatformPaySupported` requires no parameters, but you _can_ optionally pass in the same parameter you passed in to `isGooglePaySupported`. However, this now belongs under the `googlePay` field. So the change would look like:
6+
7+
```diff
8+
- isGooglePaySupported(myParams);
9+
+ isPlatformPaySupported({googlePay: myParams});
10+
```
11+
12+
# `presentApplePay`, `confirmApplePayPayment`, `initGooglePay`, `presentGooglePay`, and `createGooglePayPaymentMethod`
13+
14+
`presentApplePay`, `confirmApplePayPayment`, `isGooglePaySupported`, `presentGooglePay`, and `createGooglePayPaymentMethod` have been replaced with:
15+
16+
- `confirmPlatformPaySetupIntent` if you were using them to confirm a setup intent
17+
- `confirmPlatformPayPayment` if you were using them to confirm a payment intent
18+
- `createPlatformPayPaymentMethod` if you were using them to create a payment method (this was impossible previously with Apple Pay, so it was only possible on Android).
19+
- `createPlatformPayToken` if you are migrating from Tipsi Stripe and your payments code still uses the legacy Tokens API.
20+
21+
# `updateApplePaySummaryItems`
22+
23+
`updateApplePaySummaryItems` has been replaced with `updatePlatformPaySheet`.
24+
25+
`updatePlatformPaySheet` accepts an object with the `applePay` key. Under that key, you can pass an object containing your `summaryItems`, `shippingMethods`, and `errors` to be displayed in the Apple Pay sheet so your customer can take action during checkout.
26+
27+
# `useGooglePay` and `useApplePay`
28+
29+
`useGooglePay` and `useApplePay` have both been replaced by the `usePlatformPay` hook. The callbacks passed to the `useApplePay` hook are now set via props on the `<PlatformPayButton />` component.
30+
31+
# `<GooglePayButton />` and `<ApplePayButton />`
32+
33+
The `<GooglePayButton />` and `<ApplePayButton />` components have been replaced with `<PlatformPayButton />`.

accept-a-payment-multiline-card.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# Accept a payment - classic
2+
3+
Collecting payments in your React Native app consists of three steps. Creating an object to track payment on your server, collecting card information in your app, and submitting the payment to Stripe for processing.
4+
5+
Stripe uses this payment object, called a `PaymentIntent`, to track and handle all the states of the payment until it’s completed—even when the bank requires customer intervention, like two-factor authentication.
6+
7+
## Setup Stripe
8+
9+
### Client side
10+
11+
The [React Native SDK](https://github.com/stripe/stripe-react-native) is open source and fully documented. Internally, it makes use of [native iOS](https://github.com/stripe/stripe-ios) and [Android](https://github.com/stripe/stripe-android) SDKs. Install the SDK by running:
12+
13+
```sh
14+
yarn add react-native-stripe-sdk
15+
```
16+
17+
For iOS, run `pod install` in the `ios` directory to ensure that you also install the required native dependencies. Android doesn’t require any additional steps.
18+
19+
When your app starts, configure the SDK with your Stripe [publishable key](https://stripe.com/dashboard.stripe.com/account/apikeys) so it can make requests to the Stripe API:
20+
21+
```tsx
22+
import { StripeProvider } from '@stripe/stripe-react-native';
23+
24+
function App() {
25+
return (
26+
<StripeProvider
27+
publishableKey="pk_test_51AROWSJX9HHJ5bycpEUP9dK39tXufyuWogSUdeweyZEXy3LC7M8yc5d9NlQ96fRCVL0BlAu7Nqt4V7N5xZjJnrkp005fDiTMIr"
28+
urlScheme="your-url-scheme" // required for 3D Secure and bank redirects
29+
merchantIdentifier="merchant.com.{{YOUR_APP_NAME}}" // required for Apple Pay
30+
>
31+
// Your app code here
32+
</StripeProvider>
33+
);
34+
}
35+
```
36+
37+
## Create your checkout page
38+
39+
Securely collect card information on the client with `CardForm` component.
40+
41+
Add `CardForm` component to your payment screen. To collect card details you can use `onFormComplete` prop and save received data in component state..
42+
43+
```tsx
44+
function PaymentScreen() {
45+
const [card, setCard] = useState<CardFormView.Details>();
46+
47+
// ...
48+
49+
return (
50+
<View>
51+
<CardForm
52+
cardStyle={{
53+
backgroundColor: '#FFFFFF',
54+
}}
55+
style={{
56+
width: '100%',
57+
height: 300,
58+
}}
59+
onFormComplete={(cardDetails) => {
60+
setCard(cardDetails);
61+
}}
62+
/>
63+
</View>
64+
);
65+
}
66+
```
67+
68+
## Create a PaymentIntent
69+
70+
Stripe uses a [PaymentIntent](https://stripe.com/docs/api/payment_intents) object to represent your intent to collect payment from a customer, tracking your charge attempts and payment state changes throughout the process.
71+
72+
### Client side
73+
74+
On the client, request a PaymentIntent from your server and store its [client secret](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret):
75+
76+
```tsx
77+
function PaymentScreen() {
78+
// ...
79+
80+
const fetchPaymentIntentClientSecret = useCallback(async () => {
81+
const response = await fetch(`${API_URL}/create-payment-intent`, {
82+
method: 'POST',
83+
headers: {
84+
'Content-Type': 'application/json',
85+
},
86+
body: JSON.stringify({
87+
currency: 'usd',
88+
items: ['id-1'],
89+
}),
90+
});
91+
const { clientSecret } = await response.json();
92+
93+
return clientSecret;
94+
}, []);
95+
96+
const handlePayPress = useCallback(async () => {
97+
if (!card) {
98+
return;
99+
}
100+
101+
try {
102+
// Fetch Intent Client Secret from backend
103+
const clientSecret = await fetchPaymentIntentClientSecret();
104+
105+
// ...
106+
} catch (e) {
107+
// ...
108+
}
109+
}, [card, fetchPaymentIntentClientSecret]);
110+
111+
return (
112+
<View>
113+
<CardForm
114+
onFormComplete={(cardDetails) => {
115+
setCardDetails(cardDetails);
116+
}}
117+
/>
118+
119+
<Button onPress={handlePayPress} title="Pay" disabled={loading} />
120+
</View>
121+
);
122+
}
123+
```
124+
125+
## Submit the payment to Stripe
126+
127+
When the customer taps **Pay**, confirm the `PaymentIntent` to complete the payment.
128+
129+
Rather than sending the entire PaymentIntent object to the client, use its [client secret](https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret). This is different from your API keys that authenticate Stripe API requests. The client secret should be handled carefully because it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer.
130+
131+
Pass the customer card details and client secret to `confirmPayment`, which you can access with the `useConfirmPayment` hook. The hook also returns a loading value to indicate the state of the asynchronous action:
132+
133+
```tsx
134+
function PaymentScreen() {
135+
const { confirmPayment, loading } = useConfirmPayment();
136+
137+
// ...
138+
139+
const handlePayPress = async () => {
140+
// Gather the customer's billing information (e.g., email)
141+
const billingDetails: BillingDetails = {
142+
email: 'jenny.rosen@example.com',
143+
};
144+
145+
// Fetch the intent client secret from the backend
146+
const clientSecret = await fetchPaymentIntentClientSecret();
147+
148+
// Confirm the payment with the card details
149+
const { paymentIntent, error } = await confirmPayment(clientSecret, {
150+
paymentMethodType: 'Card',
151+
paymentMethodData: {
152+
billingDetails,
153+
},
154+
});
155+
156+
if (error) {
157+
console.log('Payment confirmation error', error);
158+
} else if (paymentIntent) {
159+
console.log('Success from promise', paymentIntent);
160+
}
161+
};
162+
163+
return <View />;
164+
}
165+
```
166+
167+
If authentication is required by regulation (e.g., Strong Customer Authentication), additional actions are presented to the customer to complete the payment process. See [Card authentication and 3D Secure](https://stripe.com/docs/payments/3d-secure) for more details.
168+
169+
When the payment completes successfully, the value of the returned PaymentIntent’s `status` property is `succeeded`. Check the status of a PaymentIntent in the [Dashboard](https://dashboard.stripe.com/test/payments) or by inspecting the `status` property on the object. If the payment isn’t successful, inspect the returned `error` to determine the cause.
170+
171+
## Test the integration
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## The problem
2+
3+
You're likely running into the same problem from https://github.com/stripe/stripe-react-native/issues/355 where a Chrome custom tab (web browser) is launched from your app's Stripe flow, like to perform 3DSecure confirmation, and if the app is backgrounded, that web browser gets killed.
4+
5+
## The solution
6+
7+
If your Android `launchMode` is set to `singleTask` (check your `AndroidManifest.xml`), that's why this is occurring. Unfortunately, this is not addressable by the Stripe React Native library.
8+
9+
Luckily, [@stianjensen shared a fix in the above Github issue](https://github.com/stripe/stripe-react-native/issues/355#issuecomment-1701323254). It is summarized here:
10+
11+
1. Modify your `MainApplication`:
12+
13+
```diff
14+
public class MainApplication extends Application {
15+
+ private ArrayList<Class> runningActivities = new ArrayList<>();
16+
17+
+ public void addActivityToStack (Class cls) {
18+
+ if (!runningActivities.contains(cls)) runningActivities.add(cls);
19+
+ }
20+
21+
+ public void removeActivityFromStack (Class cls) {
22+
+ if (runningActivities.contains(cls)) runningActivities.remove(cls);
23+
+ }
24+
25+
+ public boolean isActivityInBackStack (Class cls) {
26+
+ return runningActivities.contains(cls);
27+
+ }
28+
}
29+
```
30+
31+
2. create `LaunchActivity`
32+
33+
```diff
34+
+ public class LaunchActivity extends Activity {
35+
+ @Override
36+
+ protected void onCreate(Bundle savedInstanceState) {
37+
+ super.onCreate(savedInstanceState);
38+
+ BaseApplication application = (BaseApplication) getApplication();
39+
+ // check that MainActivity is not started yet
40+
+ if (!application.isActivityInBackStack(MainActivity.class)) {
41+
+ Intent intent = new Intent(this, MainActivity.class);
42+
+ startActivity(intent);
43+
+ }
44+
+ finish();
45+
+ }
46+
+ }
47+
```
48+
49+
3. Modify `AndroidManifest.xml` and move `android.intent.action.MAIN` and `android.intent.category.LAUNCHER` from your `.MainActivity` to `.LaunchActivity`
50+
51+
```diff
52+
+ <activity android:name=".LaunchActivity">
53+
+ <intent-filter>
54+
+ <action android:name="android.intent.action.MAIN" />
55+
+ <category android:name="android.intent.category.LAUNCHER" />
56+
+ </intent-filter>
57+
+ </activity>
58+
59+
...
60+
- <intent-filter>
61+
- <action android:name="android.intent.action.MAIN"/>
62+
- <category android:name="android.intent.category.LAUNCHER"/>
63+
- </intent-filter>
64+
...
65+
```
66+
67+
4. Modify `MainActivity` to look _something_ like the following (you likely already have an `onCreate` method that you need to modify):
68+
69+
```
70+
@Override
71+
protected void onCreate(Bundle savedInstanceState) {
72+
super.onCreate(null);
73+
((BaseApplication) getApplication()).addActivityToStack(this.getClass());
74+
}
75+
76+
@Override
77+
protected void onDestroy() {
78+
super.onDestroy();
79+
((BaseApplication) getApplication()).removeActivityFromStack(this.getClass());
80+
}
81+
```

api-reference/.nojekyll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

api-reference/assets/hierarchy.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-reference/assets/highlight.css

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
:root {
2+
--light-hl-0: #000000;
3+
--dark-hl-0: #D4D4D4;
4+
--light-hl-1: #001080;
5+
--dark-hl-1: #9CDCFE;
6+
--light-hl-2: #A31515;
7+
--dark-hl-2: #CE9178;
8+
--light-hl-3: #000000;
9+
--dark-hl-3: #C8C8C8;
10+
--light-hl-4: #008000;
11+
--dark-hl-4: #6A9955;
12+
--light-hl-5: #795E26;
13+
--dark-hl-5: #DCDCAA;
14+
--light-hl-6: #0000FF;
15+
--dark-hl-6: #569CD6;
16+
--light-hl-7: #098658;
17+
--dark-hl-7: #B5CEA8;
18+
--light-hl-8: #0070C1;
19+
--dark-hl-8: #4FC1FF;
20+
--light-hl-9: #CD3131;
21+
--dark-hl-9: #F44747;
22+
--light-code-background: #FFFFFF;
23+
--dark-code-background: #1E1E1E;
24+
}
25+
26+
@media (prefers-color-scheme: light) { :root {
27+
--hl-0: var(--light-hl-0);
28+
--hl-1: var(--light-hl-1);
29+
--hl-2: var(--light-hl-2);
30+
--hl-3: var(--light-hl-3);
31+
--hl-4: var(--light-hl-4);
32+
--hl-5: var(--light-hl-5);
33+
--hl-6: var(--light-hl-6);
34+
--hl-7: var(--light-hl-7);
35+
--hl-8: var(--light-hl-8);
36+
--hl-9: var(--light-hl-9);
37+
--code-background: var(--light-code-background);
38+
} }
39+
40+
@media (prefers-color-scheme: dark) { :root {
41+
--hl-0: var(--dark-hl-0);
42+
--hl-1: var(--dark-hl-1);
43+
--hl-2: var(--dark-hl-2);
44+
--hl-3: var(--dark-hl-3);
45+
--hl-4: var(--dark-hl-4);
46+
--hl-5: var(--dark-hl-5);
47+
--hl-6: var(--dark-hl-6);
48+
--hl-7: var(--dark-hl-7);
49+
--hl-8: var(--dark-hl-8);
50+
--hl-9: var(--dark-hl-9);
51+
--code-background: var(--dark-code-background);
52+
} }
53+
54+
:root[data-theme='light'] {
55+
--hl-0: var(--light-hl-0);
56+
--hl-1: var(--light-hl-1);
57+
--hl-2: var(--light-hl-2);
58+
--hl-3: var(--light-hl-3);
59+
--hl-4: var(--light-hl-4);
60+
--hl-5: var(--light-hl-5);
61+
--hl-6: var(--light-hl-6);
62+
--hl-7: var(--light-hl-7);
63+
--hl-8: var(--light-hl-8);
64+
--hl-9: var(--light-hl-9);
65+
--code-background: var(--light-code-background);
66+
}
67+
68+
:root[data-theme='dark'] {
69+
--hl-0: var(--dark-hl-0);
70+
--hl-1: var(--dark-hl-1);
71+
--hl-2: var(--dark-hl-2);
72+
--hl-3: var(--dark-hl-3);
73+
--hl-4: var(--dark-hl-4);
74+
--hl-5: var(--dark-hl-5);
75+
--hl-6: var(--dark-hl-6);
76+
--hl-7: var(--dark-hl-7);
77+
--hl-8: var(--dark-hl-8);
78+
--hl-9: var(--dark-hl-9);
79+
--code-background: var(--dark-code-background);
80+
}
81+
82+
.hl-0 { color: var(--hl-0); }
83+
.hl-1 { color: var(--hl-1); }
84+
.hl-2 { color: var(--hl-2); }
85+
.hl-3 { color: var(--hl-3); }
86+
.hl-4 { color: var(--hl-4); }
87+
.hl-5 { color: var(--hl-5); }
88+
.hl-6 { color: var(--hl-6); }
89+
.hl-7 { color: var(--hl-7); }
90+
.hl-8 { color: var(--hl-8); }
91+
.hl-9 { color: var(--hl-9); }
92+
pre, code { background: var(--code-background); }

0 commit comments

Comments
 (0)