From 8e7df46f2fbc3e73771fed9d87e31556a58bd406 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 22 Feb 2023 17:31:00 +0100 Subject: [PATCH] feat: stripe --- package-lock.json | 45 +++++++--- package.json | 2 + src/lib/system.ts | 1 + .../billing/+page.svelte | 9 +- .../billing/availableCredit.svelte | 2 +- .../billing/paymentMethods.svelte | 3 +- .../billing/paymentModal.svelte | 90 +++++++++++++++++++ .../billing/paymentSummary.svelte | 7 ++ .../billing/stripe.ts | 33 +++++++ 9 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 src/routes/console/organization-[organization]/billing/paymentModal.svelte create mode 100644 src/routes/console/organization-[organization]/billing/stripe.ts diff --git a/package-lock.json b/package-lock.json index e62b412ee..70aeecca8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,10 +14,12 @@ "@popperjs/core": "^2.11.6", "@sentry/svelte": "^7.36.0", "@sentry/tracing": "^7.36.0", + "@stripe/stripe-js": "^1.47.0", "analytics": "^0.8.1", "echarts": "^5.4.1", "pretty-bytes": "^6.1.0", "prismjs": "^1.29.0", + "stripe": "^11.11.0", "tippy.js": "^6.3.7", "web-vitals": "^3.1.1" }, @@ -1927,6 +1929,11 @@ "@sinonjs/commons": "^2.0.0" } }, + "node_modules/@stripe/stripe-js": { + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.47.0.tgz", + "integrity": "sha512-jKSClqEIKS2MbPCXlSsseDSZyJ3dVrfUrYMz5LBY1o9iS2tfKbpTZACt8r2g+xyQozI+uHr76pVTyFsmBKA4Mg==" + }, "node_modules/@sveltejs/adapter-static": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-1.0.6.tgz", @@ -2267,8 +2274,7 @@ "node_modules/@types/node": { "version": "18.11.19", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.19.tgz", - "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==", - "dev": true + "integrity": "sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw==" }, "node_modules/@types/prettier": { "version": "2.7.2", @@ -3035,7 +3041,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -4311,8 +4316,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -4356,7 +4360,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -4496,7 +4499,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -4538,7 +4540,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -6597,7 +6598,6 @@ "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7182,6 +7182,20 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -7575,7 +7589,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -7913,6 +7926,18 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/stripe": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-11.11.0.tgz", + "integrity": "sha512-CT8TZJ+bUaMmqCOljHdKwHTWym0bscrCHrKmvK2KoTaz/9gDIzG+lXTJOFUOb3K7Jwaoaori4yEVzOgA7U46+g==", + "dependencies": { + "@types/node": ">=8.1.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=12.*" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/package.json b/package.json index 5bcbe6ed6..a31ab5a7d 100644 --- a/package.json +++ b/package.json @@ -25,10 +25,12 @@ "@popperjs/core": "^2.11.6", "@sentry/svelte": "^7.36.0", "@sentry/tracing": "^7.36.0", + "@stripe/stripe-js": "^1.47.0", "analytics": "^0.8.1", "echarts": "^5.4.1", "pretty-bytes": "^6.1.0", "prismjs": "^1.29.0", + "stripe": "^11.11.0", "tippy.js": "^6.3.7", "web-vitals": "^3.1.1" }, diff --git a/src/lib/system.ts b/src/lib/system.ts index fc00cbd8e..41f283e14 100644 --- a/src/lib/system.ts +++ b/src/lib/system.ts @@ -9,6 +9,7 @@ export const VARS = { | string | undefined, CONSOLE_MODE: import.meta.env?.VITE_CONSOLE_MODE?.toString() as string | undefined, + CONSOLE_TIER: import.meta.env?.VITE_CONSOLE_TIER?.toString() as string | undefined, VERCEL_ENV: import.meta.env?.VITE_VERCEL_ENV?.toString() as string | undefined, GOOGLE_ANALYTICS: import.meta.env?.VITE_GA_PROJECT?.toString() as string | undefined }; diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte index 9a7202d86..8f30b9861 100644 --- a/src/routes/console/organization-[organization]/billing/+page.svelte +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -1,16 +1,21 @@ - - + + + diff --git a/src/routes/console/organization-[organization]/billing/availableCredit.svelte b/src/routes/console/organization-[organization]/billing/availableCredit.svelte index 7ca9c2192..1b63715fb 100644 --- a/src/routes/console/organization-[organization]/billing/availableCredit.svelte +++ b/src/routes/console/organization-[organization]/billing/availableCredit.svelte @@ -6,7 +6,7 @@ let coupon: string = null; async function redeem() { - const response = await fetch('/v1/account/credit', { + const response = await fetch('/v1/billing/credit', { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte index b8f5672ea..b5a3bb6b1 100644 --- a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte @@ -1,5 +1,6 @@ @@ -7,7 +8,7 @@

View or update your organization payment methods here.

- + (showPayment = true)}>

Add a payment method

diff --git a/src/routes/console/organization-[organization]/billing/paymentModal.svelte b/src/routes/console/organization-[organization]/billing/paymentModal.svelte new file mode 100644 index 000000000..9f7b69f9a --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/paymentModal.svelte @@ -0,0 +1,90 @@ + + + + Add Payment Method + This payment method will be added to the Acme Org billing details. + + + +
+
+
+
+ + + + + + + diff --git a/src/routes/console/organization-[organization]/billing/paymentSummary.svelte b/src/routes/console/organization-[organization]/billing/paymentSummary.svelte index bf55230cb..bd60176b9 100644 --- a/src/routes/console/organization-[organization]/billing/paymentSummary.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentSummary.svelte @@ -1,5 +1,6 @@ @@ -13,5 +14,11 @@

X projects

+ {#if VARS.CONSOLE_TIER && VARS.CONSOLE_TIER !== 'base'} +
+

Next billing data

+

XX DATE

+
+ {/if}
diff --git a/src/routes/console/organization-[organization]/billing/stripe.ts b/src/routes/console/organization-[organization]/billing/stripe.ts new file mode 100644 index 000000000..c0b61afb1 --- /dev/null +++ b/src/routes/console/organization-[organization]/billing/stripe.ts @@ -0,0 +1,33 @@ +import { writable } from 'svelte/store'; +import Stripe from 'stripe'; + +export const publicKey = import.meta.env?.VITE_STRIPE_PUBLIC_KEY?.toString() as string | undefined; +export const secretKey = import.meta.env?.VITE_STRIPE_SECRET_KEY?.toString() as string | undefined; +export const stripe = new Stripe(secretKey, undefined); + +function createCustomerStore() { + const { subscribe, set } = writable(undefined); + return { + subscribe, + set, + load: async (id: string) => { + const customer: Stripe.Customer | Stripe.DeletedCustomer = + await stripe.customers.retrieve(id); + set(customer); + }, + create: async (params: Stripe.CustomerCreateParams) => { + const customer: Stripe.Customer = await stripe.customers.create(params); + set(customer); + }, + update: async (id: string, params: Stripe.CustomerUpdateParams) => { + const customer: Stripe.Customer = await stripe.customers.update(id, params); + set(customer); + }, + remove: async (id: string) => { + const customer: Stripe.DeletedCustomer = await stripe.customers.del(id); + set(customer); + } + }; +} + +export const customer = createCustomerStore();