diff --git a/functions/package-lock.json b/functions/package-lock.json index 8ee9dd2..e440629 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -7,8 +7,7 @@ "name": "functions", "dependencies": { "firebase-admin": "^9.11.1", - "firebase-functions": "^3.19.0", - "stripe": "^8.209.0" + "firebase-functions": "^3.19.0" }, "devDependencies": { "firebase-functions-test": "^0.3.3", @@ -3005,19 +3004,6 @@ "node": ">=8" } }, - "node_modules/stripe": { - "version": "8.222.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.222.0.tgz", - "integrity": "sha512-hrA79fjmN2Eb6K3kxkDzU4ODeVGGjXQsuVaAPSUro6I9MM3X+BvIsVqdphm3BXWfimAGFvUqWtPtHy25mICY1w==", - "license": "MIT", - "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.10.3" - }, - "engines": { - "node": "^8.1 || >=10.*" - } - }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", diff --git a/functions/package.json b/functions/package.json index db9fc15..8affc63 100644 --- a/functions/package.json +++ b/functions/package.json @@ -16,8 +16,7 @@ "main": "lib/index.js", "dependencies": { "firebase-admin": "^9.11.1", - "firebase-functions": "^3.19.0", - "stripe": "^8.209.0" + "firebase-functions": "^3.19.0" }, "devDependencies": { "firebase-functions-test": "^0.3.3", diff --git a/functions/src/index.ts b/functions/src/index.ts index cc18267..2801dc2 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -1,6 +1,5 @@ import * as admin from "firebase-admin"; import * as functions from "firebase-functions"; -import Stripe from "stripe"; import { GameMode, findSet, generateSeed, modes, replayEvents } from "./game"; @@ -17,12 +16,6 @@ if (process.env.FUNCTIONS_EMULATOR) { admin.initializeApp(); } -const stripe = !functions.config().stripe - ? null - : new Stripe(functions.config().stripe.secret, { - apiVersion: "2020-08-27", - }); - const MAX_GAME_ID_LENGTH = 64; const MAX_UNFINISHED_GAMES_PER_HOUR = 4; @@ -347,45 +340,6 @@ export const createGame = functions.https.onCall(async (data, context) => { return snapshot.val(); }); -/** Generate a link to the customer portal. */ -export const customerPortal = functions.https.onCall(async (data, context) => { - if (!stripe) { - throw new functions.https.HttpsError( - "failed-precondition", - "Stripe is not supported." - ); - } - - if (!context.auth) { - throw new functions.https.HttpsError( - "failed-precondition", - "This function must be called while authenticated." - ); - } - - const user = await admin.auth().getUser(context.auth.uid); - if (!user.email) { - throw new functions.https.HttpsError( - "failed-precondition", - "This function must be called by an authenticated user with email." - ); - } - - const customerResponse = await stripe.customers.list({ email: user.email }); - if (!customerResponse.data.length) { - throw new functions.https.HttpsError( - "not-found", - `A subscription with email ${user.email} was not found.` - ); - } - - const portalResponse = await stripe.billingPortal.sessions.create({ - customer: customerResponse.data[0].id, - return_url: data.returnUrl, - }); - return portalResponse.url; -}); - /** Periodically remove stale user connections */ export const clearConnections = functions.pubsub .schedule("every 1 minutes") @@ -408,58 +362,3 @@ export const clearConnections = functions.pubsub actions.push(admin.database().ref("stats/onlineUsers").set(numUsers)); await Promise.all(actions); }); - -/** Webhook that handles Stripe customer events. */ -export const handleStripe = functions.https.onRequest(async (req, res) => { - if (!stripe) { - res.status(400).send("Stripe is not supported"); - return; - } - - const payload = req.rawBody; - const sig = req.get("stripe-signature"); - - if (!sig) { - res.status(400).send("Webhook Error: Missing stripe-signature"); - return; - } - - const { endpoint_secret } = functions.config().stripe; - let event; - try { - event = stripe.webhooks.constructEvent(payload, sig, endpoint_secret); - } catch (error: any) { - res.status(400).send(`Webhook Error: ${error.message}`); - return; - } - - console.log(`Received ${event.type}: ${JSON.stringify(event.data)}`); - if ( - event.type === "customer.subscription.created" || - event.type === "customer.subscription.deleted" - ) { - const subscription = event.data.object as Stripe.Subscription; - const { email } = (await stripe.customers.retrieve( - subscription.customer as string - )) as Stripe.Response; - - if (email) { - const user = await admin - .auth() - .getUserByEmail(email) - .catch(() => null); - - if (user) { - const newState = event.type === "customer.subscription.created"; - await admin.database().ref(`users/${user.uid}/patron`).set(newState); - console.log(`Processed ${email} (${user.uid}): newState = ${newState}`); - } else { - console.log(`Failed to find user: ${email}`); - } - } else { - console.log("Subscription event received with no email, ignoring"); - } - } - - res.status(200).end(); -}); diff --git a/package-lock.json b/package-lock.json index f0e816b..0071f8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@react-spring/web": "^9.7.5", - "@stripe/stripe-js": "^1.25.0", "chart.js": "^3.7.1", "clsx": "^1.1.1", "date-fns": "^4.1.0", @@ -4322,12 +4321,6 @@ "@sinonjs/commons": "^1.7.0" } }, - "node_modules/@stripe/stripe-js": { - "version": "1.54.2", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.54.2.tgz", - "integrity": "sha512-R1PwtDvUfs99cAjfuQ/WpwJ3c92+DAMy9xGApjqlWQMj0FKQabUAys2swfTRNzuYAYJh7NqK2dzcYVNkKLEKUg==", - "license": "MIT" - }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", diff --git a/package.json b/package.json index e7761ef..f0d2e57 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.2", "@react-spring/web": "^9.7.5", - "@stripe/stripe-js": "^1.25.0", "chart.js": "^3.7.1", "clsx": "^1.1.1", "date-fns": "^4.1.0", diff --git a/src/config.js b/src/config.js index 40b8760..13eb8f3 100644 --- a/src/config.js +++ b/src/config.js @@ -9,7 +9,6 @@ const config = { projectId: "setwithforks-dev", appId: "1:488130851214:web:e656dc30f31e99e160b4df", }, - stripe: null, // Stripe not supported in development }, staging: { firebase: { @@ -22,7 +21,6 @@ const config = { appId: "1:488130851214:web:e656dc30f31e99e160b4df", measurementId: "G-LQR3228JDG", }, - stripe: null, // No Stripe yet }, production: { firebase: { @@ -35,11 +33,6 @@ const config = { appId: "1:970544876139:web:06295fe4079007f76abf2e", measurementId: "G-QDX193SN7R", }, - stripe: { - publishableKey: - "pk_live_51I0VxyCWK9K42cLJX34X6lIqsuZSWQX6I8WuOgmvEGANYlNyCsZDl2MmWGXQhuM5QnVciouCiYZ9lWq5Ope68aSj00bllKdnRr", - priceId: "price_1I2QWcCWK9K42cLJFp2sUkSh", - }, }, }; diff --git a/src/stripe.js b/src/stripe.js deleted file mode 100644 index 2b155c0..0000000 --- a/src/stripe.js +++ /dev/null @@ -1,25 +0,0 @@ -import { loadStripe } from "@stripe/stripe-js"; - -import config from "./config"; - -const stripe = !config.stripe ? null : loadStripe(config.stripe.publishableKey); - -export async function patronCheckout(email) { - if (!stripe) { - return { - error: { - message: "Stripe is not currently supported. Sorry!", - }, - }; - } - const origin = window.location.origin; - return (await stripe).redirectToCheckout({ - lineItems: [{ price: config.stripe.priceId, quantity: 1 }], - mode: "subscription", - successUrl: origin + "/donate", - cancelUrl: origin + "/donate", - customerEmail: email, - }); -} - -export default stripe;