├── assets
├── icon.png
├── favicon.png
├── splash.png
└── adaptive-icon.png
├── babel.config.js
├── README.md
├── .gitignore
├── .expo-shared
└── assets.json
├── server
├── package.json
└── index.js
├── App.js
├── package.json
├── app.json
└── src
└── StripeApp.js
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathvarun/Expo-Stripe-Tutorial/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathvarun/Expo-Stripe-Tutorial/HEAD/assets/favicon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathvarun/Expo-Stripe-Tutorial/HEAD/assets/splash.png
--------------------------------------------------------------------------------
/assets/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathvarun/Expo-Stripe-Tutorial/HEAD/assets/adaptive-icon.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(api) {
2 | api.cache(true);
3 | return {
4 | presets: ['babel-preset-expo'],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Expo-Stripe-Tutorial
2 | Project Files for Expo Stripe Tutorial
3 |
4 | - [Expo Stripe | Card Payments ](https://youtu.be/DZlAET7Tgx4)
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | npm-debug.*
4 | *.jks
5 | *.p8
6 | *.p12
7 | *.key
8 | *.mobileprovision
9 | *.orig.*
10 | web-build/
11 |
12 | # macOS
13 | .DS_Store
14 |
--------------------------------------------------------------------------------
/.expo-shared/assets.json:
--------------------------------------------------------------------------------
1 | {
2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
4 | }
5 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "type": "module",
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "express": "^4.17.1",
15 | "nodemon": "^2.0.7"
16 | },
17 | "dependencies": {
18 | "stripe": "^8.154.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import { StatusBar } from "expo-status-bar";
2 | import React from "react";
3 | import { StyleSheet, Text, View } from "react-native";
4 | import StripeApp from "./src/StripeApp";
5 | import { StripeProvider } from "@stripe/stripe-react-native";
6 | export default function App() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | const styles = StyleSheet.create({
15 | container: {
16 | flex: 1,
17 | backgroundColor: "#fff",
18 | alignItems: "center",
19 | justifyContent: "center",
20 | },
21 | });
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "main": "node_modules/expo/AppEntry.js",
3 | "scripts": {
4 | "start": "expo start",
5 | "android": "expo start --android",
6 | "ios": "expo start --ios",
7 | "web": "expo start --web",
8 | "eject": "expo eject"
9 | },
10 | "dependencies": {
11 | "@stripe/stripe-react-native": "0.1.1",
12 | "expo": "~41.0.1",
13 | "expo-status-bar": "~1.0.4",
14 | "react": "16.13.1",
15 | "react-dom": "16.13.1",
16 | "react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
17 | "react-native-web": "~0.13.12"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.9.0"
21 | },
22 | "private": true
23 | }
24 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "expo-stripe-youtube",
4 | "slug": "expo-stripe-youtube",
5 | "version": "1.0.0",
6 | "orientation": "portrait",
7 | "icon": "./assets/icon.png",
8 | "splash": {
9 | "image": "./assets/splash.png",
10 | "resizeMode": "contain",
11 | "backgroundColor": "#ffffff"
12 | },
13 | "updates": {
14 | "fallbackToCacheTimeout": 0
15 | },
16 | "assetBundlePatterns": [
17 | "**/*"
18 | ],
19 | "ios": {
20 | "supportsTablet": true
21 | },
22 | "android": {
23 | "adaptiveIcon": {
24 | "foregroundImage": "./assets/adaptive-icon.png",
25 | "backgroundColor": "#FFFFFF"
26 | }
27 | },
28 | "web": {
29 | "favicon": "./assets/favicon.png"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 |
3 | const app = express();
4 | const port = 3000; //add your port here
5 | const PUBLISHABLE_KEY = "ADD_PUBLISHABLE KEY HERE";
6 | const SECRET_KEY = "ADD_SECRETE KEY HERE";
7 | import Stripe from "stripe";
8 |
9 | //Confirm the API version from your stripe dashboard
10 | const stripe = Stripe(SECRET_KEY, { apiVersion: "2020-08-27" });
11 |
12 | app.listen(port, () => {
13 | console.log(`Example app listening at http://localhost:${port}`);
14 | });
15 |
16 | app.post("/create-payment-intent", async (req, res) => {
17 | try {
18 | const paymentIntent = await stripe.paymentIntents.create({
19 | amount: 1099, //lowest denomination of particular currency
20 | currency: "usd",
21 | payment_method_types: ["card"], //by default
22 | });
23 |
24 | const clientSecret = paymentIntent.client_secret;
25 |
26 | res.json({
27 | clientSecret: clientSecret,
28 | });
29 | } catch (e) {
30 | console.log(e.message);
31 | res.json({ error: e.message });
32 | }
33 | });
34 |
--------------------------------------------------------------------------------
/src/StripeApp.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { View, Text, StyleSheet, TextInput, Button, Alert } from "react-native";
3 | import { CardField, useConfirmPayment } from "@stripe/stripe-react-native";
4 |
5 | //ADD localhost address of your server
6 | const API_URL = "http://localhost:3000";
7 |
8 | const StripeApp = props => {
9 | const [email, setEmail] = useState();
10 | const [cardDetails, setCardDetails] = useState();
11 | const { confirmPayment, loading } = useConfirmPayment();
12 |
13 | const fetchPaymentIntentClientSecret = async () => {
14 | const response = await fetch(`${API_URL}/create-payment-intent`, {
15 | method: "POST",
16 | headers: {
17 | "Content-Type": "application/json",
18 | },
19 | });
20 | const { clientSecret, error } = await response.json();
21 | return { clientSecret, error };
22 | };
23 |
24 | const handlePayPress = async () => {
25 | //1.Gather the customer's billing information (e.g., email)
26 | if (!cardDetails?.complete || !email) {
27 | Alert.alert("Please enter Complete card details and Email");
28 | return;
29 | }
30 | const billingDetails = {
31 | email: email,
32 | };
33 | //2.Fetch the intent client secret from the backend
34 | try {
35 | const { clientSecret, error } = await fetchPaymentIntentClientSecret();
36 | //2. confirm the payment
37 | if (error) {
38 | console.log("Unable to process payment");
39 | } else {
40 | const { paymentIntent, error } = await confirmPayment(clientSecret, {
41 | type: "Card",
42 | billingDetails: billingDetails,
43 | });
44 | if (error) {
45 | alert(`Payment Confirmation Error ${error.message}`);
46 | } else if (paymentIntent) {
47 | alert("Payment Successful");
48 | console.log("Payment successful ", paymentIntent);
49 | }
50 | }
51 | } catch (e) {
52 | console.log(e);
53 | }
54 | //3.Confirm the payment with the card details
55 | };
56 |
57 | return (
58 |
59 | setEmail(value.nativeEvent.text)}
64 | style={styles.input}
65 | />
66 | {
74 | setCardDetails(cardDetails);
75 | }}
76 | />
77 |
78 |
79 | );
80 | };
81 | export default StripeApp;
82 |
83 | const styles = StyleSheet.create({
84 | container: {
85 | flex: 1,
86 | justifyContent: "center",
87 | margin: 20,
88 | },
89 | input: {
90 | backgroundColor: "#efefefef",
91 |
92 | borderRadius: 8,
93 | fontSize: 20,
94 | height: 50,
95 | padding: 10,
96 | },
97 | card: {
98 | backgroundColor: "#efefefef",
99 | },
100 | cardContainer: {
101 | height: 50,
102 | marginVertical: 30,
103 | },
104 | });
105 |
--------------------------------------------------------------------------------