From 30dec8d04a7b97e566d32778df6c2a369e146bf3 Mon Sep 17 00:00:00 2001 From: pillowboy <33105890+poolsar42@users.noreply.github.com> Date: Thu, 27 Jul 2023 16:02:27 -0400 Subject: [PATCH] chore(console): Handle 3D Secure Events (#2529) --- ...pe-js-npm-1.54.1-5949142f7a-eb54054ede.zip | Bin 0 -> 107576 bytes apps/console/app/entry.server.tsx | 8 + apps/console/app/root.tsx | 31 +- apps/console/app/routes/__layout.tsx | 12 +- .../app/routes/__layout/billing/cancel.tsx | 51 +++ .../app/routes/__layout/billing/details.tsx | 9 +- .../app/routes/__layout/billing/index.tsx | 361 ++++++++++-------- .../app/routes/__layout/billing/update.tsx | 81 ++++ .../app/routes/__layout/billing/webhook.tsx | 91 ++--- apps/console/app/routes/apps/$clientId.tsx | 25 +- .../app/routes/apps/$clientId/billing.tsx | 256 ++++++++----- apps/console/app/services/billing/stripe.ts | 68 ++-- apps/console/app/types.ts | 8 +- apps/console/app/utils.ts | 70 +++- apps/console/app/utils/billing.ts | 200 ++++++++++ apps/console/bindings.d.ts | 1 + apps/console/package.json | 1 + apps/console/wrangler.current.toml | 1 + apps/console/wrangler.dev.toml | 1 + apps/console/wrangler.next.toml | 1 + apps/console/wrangler.toml | 1 + .../src/atoms/toast/ToastWithLink.tsx | 17 +- packages/platform-clients/core.ts | 6 +- platform/account/src/types.ts | 2 + yarn.lock | 8 + 25 files changed, 954 insertions(+), 356 deletions(-) create mode 100644 .yarn/cache/@stripe-stripe-js-npm-1.54.1-5949142f7a-eb54054ede.zip create mode 100644 apps/console/app/routes/__layout/billing/cancel.tsx create mode 100644 apps/console/app/routes/__layout/billing/update.tsx create mode 100644 apps/console/app/utils/billing.ts diff --git a/.yarn/cache/@stripe-stripe-js-npm-1.54.1-5949142f7a-eb54054ede.zip b/.yarn/cache/@stripe-stripe-js-npm-1.54.1-5949142f7a-eb54054ede.zip new file mode 100644 index 0000000000000000000000000000000000000000..97dfd088400f979cc0ca5e20fece24f7a158605c GIT binary patch literal 107576 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 z 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 literal 0 HcmV?d00001 diff --git a/apps/console/app/entry.server.tsx b/apps/console/app/entry.server.tsx index 0edc23c979..2f425856b4 100644 --- a/apps/console/app/entry.server.tsx +++ b/apps/console/app/entry.server.tsx @@ -42,6 +42,7 @@ export default function handleRequest( SELF, 'https://verify.walletconnect.com', 'form.typeform.com', + 'https://*.stripe.com', ], 'connect-src': [ SELF, @@ -50,9 +51,16 @@ export default function handleRequest( 'https://*.g.alchemy.com', 'https://upload.imagedelivery.net', 'https://analytics.rollup.id', + 'https://maps.googleapis.com', + 'https://api.stripe.com', // Used for Remix WebSocket Live Reaload ...(dev ? ['ws://localhost:*/socket'] : []), ], + 'frame-src': [ + SELF, + 'https://js.stripe.com', + 'https://hooks.stripe.com', + ], 'script-src': [SELF, `'nonce-${nonce}' ${STRICT_DYNAMIC}`], 'style-src': [ SELF, diff --git a/apps/console/app/root.tsx b/apps/console/app/root.tsx index c11857d67d..afdeded787 100644 --- a/apps/console/app/root.tsx +++ b/apps/console/app/root.tsx @@ -53,6 +53,7 @@ import { BadRequestError } from '@proofzero/errors' import posthog from 'posthog-js' import { PostHogProvider } from 'posthog-js/react' import { useHydrated } from 'remix-utils' +import { getCurrentAndUpcomingInvoices } from './utils/billing' export const links: LinksFunction = () => { return [ @@ -85,6 +86,7 @@ export type LoaderData = { avatarUrl: string PASSPORT_URL: string displayName: string + hasUnpaidInvoices: boolean ENV: { POSTHOG_API_KEY: string POSTHOG_PROXY_HOST: string @@ -144,9 +146,27 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( WALLET_CONNECT_PROJECT_ID, } = context.env + const spd = await coreClient.account.getStripePaymentData.query({ + accountURN, + }) + + // might be quite heavy object + // for that reason I don't put it in outlet context + const invoices = await getCurrentAndUpcomingInvoices( + spd, + context.env.SECRET_STRIPE_API_KEY + ) + + const hasUnpaidInvoices = invoices.some((invoice) => { + if (invoice.status) + return ['uncollectible', 'open'].includes(invoice.status) + return false + }) + return json({ apps: reshapedApps, avatarUrl, + hasUnpaidInvoices, PASSPORT_URL, ENV: { POSTHOG_API_KEY, @@ -180,7 +200,14 @@ export default function App() { const remixDevPort = loaderData.ENV.REMIX_DEV_SERVER_WS_PORT useTreeshakeHack(remixDevPort) - const { apps, avatarUrl, PASSPORT_URL, displayName, accountURN } = loaderData + const { + apps, + avatarUrl, + PASSPORT_URL, + displayName, + accountURN, + hasUnpaidInvoices, + } = loaderData useEffect(() => { if (GATag) { @@ -246,6 +273,7 @@ export default function App() { PASSPORT_URL, displayName, accountURN, + hasUnpaidInvoices, }} /> @@ -257,6 +285,7 @@ export default function App() { PASSPORT_URL, displayName, accountURN, + hasUnpaidInvoices, }} /> )} diff --git a/apps/console/app/routes/__layout.tsx b/apps/console/app/routes/__layout.tsx index c4c0795d3c..643f981ea7 100644 --- a/apps/console/app/routes/__layout.tsx +++ b/apps/console/app/routes/__layout.tsx @@ -10,13 +10,15 @@ import SiteHeader from '~/components/SiteHeader' import { Popover } from '@headlessui/react' import type { LoaderData as OutletContextData } from '~/root' +import { ToastWithLink } from '@proofzero/design-system/src/atoms/toast/ToastWithLink' // Component // ----------------------------------------------------------------------------- export default function DashboardIndexPage() { const context = useOutletContext() - const { apps, avatarUrl, displayName, PASSPORT_URL } = context + const { apps, avatarUrl, displayName, PASSPORT_URL, hasUnpaidInvoices } = + context return ( @@ -31,6 +33,14 @@ export default function DashboardIndexPage() { />

+ {hasUnpaidInvoices && ( + + )}
{ + await requireJWT(request, context.env) + + const fd = await request.formData() + + const invoiceId = fd.get('invoice_id') as string + + const headers = request.headers + let returnURL = headers.get('Referer') as string + + const flashSession = await getFlashSession(request, context.env) + + try { + await voidInvoice(invoiceId, context.env.SECRET_STRIPE_API_KEY) + flashSession.flash( + 'toastNotification', + JSON.stringify({ + type: ToastType.Success, + message: 'Invoice successfully cancelled.', + }) + ) + } catch (e) { + console.error(e) + flashSession.flash( + 'toastNotification', + JSON.stringify({ + type: ToastType.Error, + message: 'Invoice cancellation failed.', + }) + ) + } + + return redirect(returnURL, { + headers: { + 'Set-Cookie': await commitFlashSession(flashSession, context.env), + }, + }) + } +) diff --git a/apps/console/app/routes/__layout/billing/details.tsx b/apps/console/app/routes/__layout/billing/details.tsx index d620c687d3..62a4abc34d 100644 --- a/apps/console/app/routes/__layout/billing/details.tsx +++ b/apps/console/app/routes/__layout/billing/details.tsx @@ -14,6 +14,7 @@ import { import { createCustomer, updateCustomer } from '~/services/billing/stripe' import { AccountURN } from '@proofzero/urns/account' import { AddressURN } from '@proofzero/urns/address' +import { ToastType } from '@proofzero/design-system/src/atoms/toast' export const action: ActionFunction = getRollupReqFunctionErrorWrapper( async ({ request, context }) => { @@ -81,7 +82,13 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( }) const flashSession = await getFlashSession(request, context.env) - flashSession.flash('success_toast', 'Payment data updated') + flashSession.flash( + 'toast_notification', + JSON.stringify({ + type: ToastType.Success, + message: 'Payment data updated', + }) + ) return redirect('/billing', { headers: { diff --git a/apps/console/app/routes/__layout/billing/index.tsx b/apps/console/app/routes/__layout/billing/index.tsx index 2e75185fd9..41d8313283 100644 --- a/apps/console/app/routes/__layout/billing/index.tsx +++ b/apps/console/app/routes/__layout/billing/index.tsx @@ -29,6 +29,7 @@ import { import { Link, NavLink, + useActionData, useLoaderData, useOutletContext, useSubmit, @@ -64,33 +65,30 @@ import { import useConnectResult from '@proofzero/design-system/src/hooks/useConnectResult' import { ToastInfo } from '@proofzero/design-system/src/atoms/toast/ToastInfo' import { DangerPill } from '@proofzero/design-system/src/atoms/pills/DangerPill' -import { - createSubscription, - getInvoices, - reconcileAppSubscriptions, - updateSubscription, -} from '~/services/billing/stripe' +import { reconcileAppSubscriptions } from '~/services/billing/stripe' import { useHydrated } from 'remix-utils' import _ from 'lodash' import { BadRequestError, InternalServerError } from '@proofzero/errors' import iSvg from '@proofzero/design-system/src/atoms/info/i.svg' - -type StripeInvoice = { - amount: number - timestamp: number - status: string | null - url?: string -} +import { + createOrUpdateSubscription, + getCurrentAndUpcomingInvoices, + process3DSecureCard, + UnpaidInvoiceNotification, + type StripeInvoice, +} from '~/utils/billing' +import { IoWarningOutline } from 'react-icons/io5' +import { type ToastNotification } from '~/types' +import { setPurchaseToastNotification } from '~/utils' +import type Stripe from 'stripe' type LoaderData = { + STRIPE_PUBLISHABLE_KEY: string paymentData?: PaymentData entitlements: { [ServicePlanType.PRO]: number } - toastNotification?: { - message: string - type: ToastType - } + toastNotification?: ToastNotification connectedEmails: DropdownSelectListItem[] invoices: StripeInvoice[] } @@ -108,15 +106,14 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( ...traceHeader, }) - const { plans, subscriptionID } = - await coreClient.account.getEntitlements.query({ - accountURN, - }) + const { plans } = await coreClient.account.getEntitlements.query({ + accountURN, + }) const flashSession = await getFlashSession(request, context.env) let toastNotification = undefined - const toastStr = flashSession.get('toastNotification') + const toastStr = flashSession.get('toast_notification') if (toastStr) { toastNotification = JSON.parse(toastStr) } @@ -150,34 +147,14 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( spd.addressURN = targetAddressURN } - let invoices: StripeInvoice[] = [] - if (subscriptionID) { - const stripeInvoices = await getInvoices( - { - customerID: spd.customerID, - }, - context.env - ) - - invoices = stripeInvoices.invoices.data.map((i) => ({ - amount: i.total / 100, - timestamp: i.created * 1000, - status: i.status, - url: i.hosted_invoice_url ?? undefined, - })) - - if (stripeInvoices.upcomingInvoices) { - invoices = invoices.concat({ - amount: stripeInvoices.upcomingInvoices.lines.data[0].amount / 100, - timestamp: - stripeInvoices.upcomingInvoices.lines.data[0].period.start * 1000, - status: 'scheduled', - }) - } - } + const invoices = await getCurrentAndUpcomingInvoices( + spd, + context.env.SECRET_STRIPE_API_KEY + ) return json( { + STRIPE_PUBLISHABLE_KEY: context.env.STRIPE_PUBLISHABLE_KEY, paymentData: spd, entitlements: { [ServicePlanType.PRO]: @@ -209,6 +186,23 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( ...traceHeader, }) + const spd = await coreClient.account.getStripePaymentData.query({ + accountURN, + }) + + const invoices = await getCurrentAndUpcomingInvoices( + spd, + context.env.SECRET_STRIPE_API_KEY + ) + + const flashSession = await getFlashSession(request, context.env) + + await UnpaidInvoiceNotification({ + invoices, + flashSession, + env: context.env, + }) + const fd = await request.formData() const { customerID, quantity, txType } = JSON.parse( fd.get('payload') as string @@ -230,33 +224,24 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( }) } + if ((quantity < 1 && txType === 'buy') || quantity < 0) { + throw new BadRequestError({ + message: `Invalid quantity. Please enter a valid number of entitlements.`, + }) + } + const entitlements = await coreClient.account.getEntitlements.query({ accountURN, }) - let sub - if (!entitlements.subscriptionID) { - sub = await createSubscription( - { - customerID: customerID, - planID: context.env.SECRET_STRIPE_PRO_PLAN_ID, - quantity: +quantity, - accountURN, - handled: true, - }, - context.env - ) - } else { - sub = await updateSubscription( - { - subscriptionID: entitlements.subscriptionID, - planID: context.env.SECRET_STRIPE_PRO_PLAN_ID, - quantity: +quantity, - handled: true, - }, - context.env - ) - } + const sub = await createOrUpdateSubscription({ + customerID, + SECRET_STRIPE_PRO_PLAN_ID: context.env.SECRET_STRIPE_PRO_PLAN_ID, + SECRET_STRIPE_API_KEY: context.env.SECRET_STRIPE_API_KEY, + quantity, + subscriptionID: entitlements.subscriptionID, + accountURN, + }) if ( (txType === 'buy' && @@ -275,30 +260,15 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( ) } - const flashSession = await getFlashSession(request, context.env) if (txType === 'buy') { - // https://stripe.com/docs/billing/subscriptions/overview#subscription-statuses - if (sub.status === 'active' || sub.status === 'trialing') { - flashSession.flash( - 'toastNotification', - JSON.stringify({ - type: ToastType.Success, - message: 'Entitlement(s) successfully bought', - }) - ) - } else { - flashSession.flash( - 'toastNotification', - JSON.stringify({ - type: ToastType.Error, - message: 'Payment failed - check your card details', - }) - ) - } + setPurchaseToastNotification({ + sub, + flashSession, + }) } if (txType === 'remove') { flashSession.flash( - 'toastNotification', + 'toast_notification', JSON.stringify({ type: ToastType.Success, message: 'Entitlement(s) successfully removed', @@ -306,11 +276,32 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( ) } - return new Response(null, { - headers: { - 'Set-Cookie': await commitFlashSession(flashSession, context.env), + let status, client_secret, payment_method + if ( + sub.latest_invoice && + (sub.latest_invoice as Stripe.Invoice).payment_intent + ) { + // lots of stripe type casting since by default many + // props are strings (not expanded versions) + ;({ status, client_secret, payment_method } = ( + sub.latest_invoice as Stripe.Invoice + ).payment_intent as Stripe.PaymentIntent) + } + + return json( + { + status, + client_secret, + payment_method, + quantity, + subId: sub.id, }, - }) + { + headers: { + 'Set-Cookie': await commitFlashSession(flashSession, context.env), + }, + } + ) } ) @@ -459,7 +450,7 @@ const PurchaseProModal = ({ onClick={() => { setProEntitlementDelta((prev) => prev - 1) }} - disabled={proEntitlementDelta < 1} + disabled={proEntitlementDelta <= 1} > @@ -510,7 +501,6 @@ const PurchaseProModal = ({ onClick={() => { setIsOpen(false) setProEntitlementDelta(1) - submit( { payload: JSON.stringify({ @@ -789,11 +779,13 @@ const PlanCard = ({ apps, paymentData, submit, + hasUnpaidInvoices = false, }: { plan: PlanDetails entitlements: number apps: AppLoaderData[] paymentData?: PaymentData + hasUnpaidInvoices: boolean submit: (data: any, options: any) => void }) => { const [purchaseProModalOpen, setPurchaseProModalOpen] = useState(false) @@ -855,43 +847,49 @@ const PlanCard = ({ - - + + Purchase Entitlement(s) +
- - + + Remove Entitlement(s) +
@@ -1000,6 +998,7 @@ const PlanCard = ({ export default () => { const { + STRIPE_PUBLISHABLE_KEY, entitlements, toastNotification, paymentData, @@ -1007,20 +1006,32 @@ export default () => { invoices, } = useLoaderData() - const { apps, PASSPORT_URL } = useOutletContext() + const { apps, PASSPORT_URL, hasUnpaidInvoices } = + useOutletContext() + + const actionData = useActionData() + const submit = useSubmit() + + useEffect(() => { + if (actionData) { + const { status, client_secret, payment_method, subId } = actionData + process3DSecureCard({ + STRIPE_PUBLISHABLE_KEY, + status, + subId, + client_secret, + payment_method, + submit, + redirectUrl: '/billing', + }) + } + }, [actionData]) useEffect(() => { if (toastNotification) { - if (toastNotification.type === ToastType.Success) { - toast(ToastType.Success, { - message: toastNotification.message, - }) - } - if (toastNotification.type === ToastType.Error) { - toast(ToastType.Error, { - message: toastNotification.message, - }) - } + toast(toastNotification.type, { + message: toastNotification.message, + }) } }, [toastNotification]) @@ -1052,7 +1063,6 @@ export default () => { paymentData?.name ) - const submit = useSubmit() const hydrated = useHydrated() const [invoiceSort, setInvoiceSort] = useState<'asc' | 'desc'>('desc') @@ -1223,6 +1233,7 @@ export default () => { paymentData={paymentData} submit={submit} apps={apps.filter((a) => a.appPlan === ServicePlanType.PRO)} + hasUnpaidInvoices={hasUnpaidInvoices} /> @@ -1314,16 +1325,32 @@ export default () => { {hydrated && ( - - {new Date(invoice.timestamp).toLocaleString( - 'default', - { - day: '2-digit', - month: 'short', - year: 'numeric', - } +
+ + {hydrated && + new Date(invoice.timestamp).toLocaleString( + 'default', + { + day: '2-digit', + month: 'short', + year: 'numeric', + } + )} + + + {(invoice.status === 'open' || + invoice.status === 'uncollectible') && ( +
+ + + Payment Error + +
)} - +
)} @@ -1341,12 +1368,48 @@ export default () => { {invoice.status && _.startCase(invoice.status)}
{invoice.status === 'paid' && ( - + View Invoice )} + {(invoice.status === 'open' || + invoice.status === 'uncollectible') && ( +
+ + + Update Payment + + + +
+ )} ))} diff --git a/apps/console/app/routes/__layout/billing/update.tsx b/apps/console/app/routes/__layout/billing/update.tsx new file mode 100644 index 0000000000..1231f3149b --- /dev/null +++ b/apps/console/app/routes/__layout/billing/update.tsx @@ -0,0 +1,81 @@ +import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace' +import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' +import { redirect, type ActionFunction } from '@remix-run/cloudflare' +import { + commitFlashSession, + getFlashSession, + requireJWT, +} from '~/utilities/session.server' +import createCoreClient from '@proofzero/platform-clients/core' +import { + getAuthzHeaderConditionallyFromToken, + parseJwt, +} from '@proofzero/utils' +import { reconcileAppSubscriptions } from '~/services/billing/stripe' +import { type AccountURN } from '@proofzero/urns/account' +import { ToastType } from '@proofzero/design-system/src/atoms/toast' + +/** + * WARNING: Here be dragons, and not the cute, cuddly kind! This code runs twice in certain scenarios because when the user + * is doing this interactively, we first run it synchronously, followed by an asynchronous invocation that updated the + * object idemptotently with the same data. + * + * We're doing this because we need to keep the front-end updated with the latest subscription info. + * Yes, it's as fun as a porcupine at a balloon party, but until we find a better solution, this is the mess we're in. + * So if you're about to change something here, make sure you update the other instance as well. Or else you'll be the one + * explaining to the boss why our app is acting like a drunk squirrel. Good luck, you're gonna need it! + */ + +export const action: ActionFunction = getRollupReqFunctionErrorWrapper( + async ({ request, context }) => { + const jwt = await requireJWT(request, context.env) + const parsedJwt = parseJwt(jwt!) + const accountURN = parsedJwt.sub as AccountURN + + const traceHeader = generateTraceContextHeaders(context.traceSpan) + const fd = await request.formData() + + const subId = fd.get('subId') as string + const redirectUrl = fd.get('redirectUrl') as string + + const coreClient = createCoreClient(context.env.Core, { + ...getAuthzHeaderConditionallyFromToken(jwt), + ...traceHeader, + }) + const flashSession = await getFlashSession(request, context.env) + + try { + await reconcileAppSubscriptions( + { + subscriptionID: subId, + accountURN, + coreClient, + billingURL: `${context.env.CONSOLE_URL}/billing`, + settingsURL: `${context.env.CONSOLE_URL}`, + }, + context.env + ) + flashSession.flash( + 'toast_notification', + JSON.stringify({ + type: ToastType.Success, + message: 'Successfully purchased entitlement(s)', + }) + ) + } catch (ex) { + flashSession.flash( + 'toast_notification', + JSON.stringify({ + type: ToastType.Error, + message: 'Something went wrong. Please try again', + }) + ) + } + + return redirect(`${redirectUrl}`, { + headers: { + 'Set-Cookie': await commitFlashSession(flashSession, context.env), + }, + }) + } +) diff --git a/apps/console/app/routes/__layout/billing/webhook.tsx b/apps/console/app/routes/__layout/billing/webhook.tsx index be63db62b5..eeda5f3b25 100644 --- a/apps/console/app/routes/__layout/billing/webhook.tsx +++ b/apps/console/app/routes/__layout/billing/webhook.tsx @@ -7,15 +7,15 @@ import createCoreClient from '@proofzero/platform-clients/core' import { type AccountURN } from '@proofzero/urns/account' import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils' -import { - reconcileAppSubscriptions, - updateSubscriptionMetadata, -} from '~/services/billing/stripe' +import { reconcileAppSubscriptions } from '~/services/billing/stripe' import { InternalServerError, RollupError } from '@proofzero/errors' -import { AddressURN } from '@proofzero/urns/address' +import { type AddressURN } from '@proofzero/urns/address' type StripeInvoicePayload = { + id: string + subscription: string customer: string + payment_intent: string lines: { data: Array<{ price: { product: string } @@ -23,6 +23,7 @@ type StripeInvoicePayload = { quantity: number }> } + metadata: any } export const action: ActionFunction = getRollupReqFunctionErrorWrapper( @@ -51,61 +52,28 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( switch (event.type) { case 'customer.subscription.created': case 'customer.subscription.updated': - const { id, metadata: subMeta } = event.data.object as { + const { + id, + metadata: subMeta, + status: subStatus, + latest_invoice: latestInvoice, + } = event.data.object as { id: string + latest_invoice: string metadata: { accountURN: AccountURN - handled?: string | null - } - } - - if (event.data.previous_attributes) { - let metadataUpdateEvent = false - - const { metadata } = event.data.previous_attributes as { - metadata?: { - handled?: string - } - } - - // If previous attributes had a handled flag and the current - // event does not, then the webhook is handling only the - // handled removal so we shouldn't move further - if ( - !subMeta.handled && - metadata?.handled && - JSON.parse(metadata.handled) - ) { - console.info( - `Cleared Subscription ${id} - ${event.type} handled flag` - ) - metadataUpdateEvent = true - } - - if (metadataUpdateEvent) { - return null } + status: string } - // When synchronously handling subscription update effects - // a flag is set to prevent the webhook from handling it again - // when it is received asynchronously - // This call clears the flag - if (subMeta.handled) { - console.info( - `Subscription ${id} - ${event.type} already handled synchronously` - ) - - subMeta.handled = null - - await updateSubscriptionMetadata( - { - id, - metadata: subMeta, - }, - context.env - ) + const invoice = await stripeClient.invoices.retrieve(latestInvoice) + // We don't want to do anything with subscription + // if payment for it failed + if ( + (subStatus !== 'active' && subStatus !== 'trialing') || + invoice.status !== 'paid' + ) { return null } @@ -160,7 +128,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( let inferredAddressURN if (paymentData && !paymentData.addressURN) { inferredAddressURN = - await addressClient.getAddressURNForEmail.query( + await coreClient.address.getAddressURNForEmail.query( email.toLowerCase() ) @@ -246,13 +214,22 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( } break + case 'invoice.payment_failed': - const { customer: customerFail } = event.data - .object as StripeInvoicePayload + const { customer: customerFail, payment_intent: paymentIntentFail } = + event.data.object as StripeInvoicePayload const customerDataFail = await stripeClient.customers.retrieve( customerFail ) - if (!customerDataFail.deleted && customerDataFail.email) { + const paymentIntentInfo = await stripeClient.paymentIntents.retrieve( + paymentIntentFail + ) + + if ( + !customerDataFail.deleted && + customerDataFail.email && + paymentIntentInfo.status !== 'requires_action' + ) { const { email, name } = customerDataFail await coreClient.address.sendFailedPaymentNotification.mutate({ diff --git a/apps/console/app/routes/apps/$clientId.tsx b/apps/console/app/routes/apps/$clientId.tsx index a143c6cb5f..85b93f9f92 100644 --- a/apps/console/app/routes/apps/$clientId.tsx +++ b/apps/console/app/routes/apps/$clientId.tsx @@ -27,6 +27,7 @@ import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' import { PlatformAddressURNHeader } from '@proofzero/types/headers' import { getToastsAndFlashSession } from '~/utils/toast.server' import { useEffect } from 'react' +import { ToastWithLink } from '@proofzero/design-system/src/atoms/toast/ToastWithLink' type LoaderData = { appDetails: appDetailsProps @@ -143,8 +144,14 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( export default function AppDetailIndexPage() { const loaderData = useLoaderData() - const { apps, avatarUrl, PASSPORT_URL, displayName, accountURN } = - useOutletContext() + const { + apps, + avatarUrl, + PASSPORT_URL, + displayName, + accountURN, + hasUnpaidInvoices, + } = useOutletContext() const { appDetails, rotationResult, @@ -193,16 +200,25 @@ export default function AppDetailIndexPage() { />
+ {hasUnpaidInvoices && ( + + )}
diff --git a/apps/console/app/routes/apps/$clientId/billing.tsx b/apps/console/app/routes/apps/$clientId/billing.tsx index 6cf010d60f..7d2665d8dc 100644 --- a/apps/console/app/routes/apps/$clientId/billing.tsx +++ b/apps/console/app/routes/apps/$clientId/billing.tsx @@ -1,14 +1,14 @@ import { Text } from '@proofzero/design-system/src/atoms/text/Text' -import plans, { PlanDetails } from '~/routes/__layout/billing/plans' +import plans, { type PlanDetails } from '~/routes/__layout/billing/plans' import { PlanFeatures } from '~/routes/__layout/billing' -import { PaymentData, ServicePlanType } from '@proofzero/types/account' +import { type PaymentData, ServicePlanType } from '@proofzero/types/account' import { Button } from '@proofzero/design-system' import { StatusPill } from '@proofzero/design-system/src/atoms/pills/StatusPill' import { - ActionFunction, - LoaderFunction, - Session, - SessionData, + type ActionFunction, + type LoaderFunction, + type Session, + type SessionData, json, } from '@remix-run/cloudflare' import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors' @@ -23,16 +23,18 @@ import { getAuthzHeaderConditionallyFromToken, parseJwt, } from '@proofzero/utils' -import { useLoaderData, useOutletContext, useSubmit } from '@remix-run/react' -import { GetEntitlementsOutput } from '@proofzero/platform/account/src/jsonrpc/methods/getEntitlements' -import { AccountURN } from '@proofzero/urns/account' -import { BadRequestError } from '@proofzero/errors' -import type { appDetailsProps } from '~/types' -import { AppLoaderData } from '~/root' import { - createSubscription, - updateSubscription, -} from '~/services/billing/stripe' + useActionData, + useLoaderData, + useOutletContext, + useSubmit, +} from '@remix-run/react' +import { type GetEntitlementsOutput } from '@proofzero/platform/account/src/jsonrpc/methods/getEntitlements' +import { type AccountURN } from '@proofzero/urns/account' +import { BadRequestError } from '@proofzero/errors' +import type { ToastNotification, appDetailsProps } from '~/types' +import { type AppLoaderData } from '~/root' + import { Modal } from '@proofzero/design-system/src/molecules/modal/Modal' import { ToastWithLink } from '@proofzero/design-system/src/atoms/toast/ToastWithLink' import { useEffect, useMemo, useState } from 'react' @@ -42,8 +44,16 @@ import { Toaster, toast, } from '@proofzero/design-system/src/atoms/toast' -import { Env } from 'bindings' import dangerVector from '~/images/danger.svg' +import { type Env } from 'bindings' +import { + getCurrentAndUpcomingInvoices, + createOrUpdateSubscription, + process3DSecureCard, + UnpaidInvoiceNotification, +} from '~/utils/billing' +import { setPurchaseToastNotification } from '~/utils' +import type Stripe from 'stripe' export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( async ({ request, context }) => { @@ -65,15 +75,18 @@ export const loader: LoaderFunction = getRollupReqFunctionErrorWrapper( }) const flashSession = await getFlashSession(request, context.env) - const successToast = flashSession.get('success_toast') - const errorToast = flashSession.get('error_toast') + let toastNotification: ToastNotification | undefined = undefined + const toastStr = flashSession.get('toast_notification') + if (toastStr) { + toastNotification = JSON.parse(toastStr) + } return json( { entitlements, paymentData, - successToast, - errorToast, + toastNotification, + STRIPE_PUBLISHABLE_KEY: context.env.STRIPE_PUBLISHABLE_KEY, }, { headers: { @@ -136,8 +149,13 @@ const processUpdateOp = async ( }) } } - - flashSession.flash('success_toast', `${plans[plan].title} assigned.`) + flashSession.flash( + 'toast_notification', + JSON.stringify({ + type: ToastType.Success, + message: `${plans[plan].title} assigned.`, + }) + ) } const processPurchaseOp = async ( @@ -170,66 +188,41 @@ const processPurchaseOp = async ( } const { customerID } = paymentData - let sub - let quantity - try { - if (!entitlements.subscriptionID) { - quantity = 1 - sub = await createSubscription( - { - customerID: customerID, - planID: env.SECRET_STRIPE_PRO_PLAN_ID, - quantity, - accountURN, - handled: true, - }, - env - ) - } else { - quantity = entitlements.plans[plan]?.entitlements - ? entitlements.plans[plan]?.entitlements! + 1 - : 1 - - sub = await updateSubscription( - { - subscriptionID: entitlements.subscriptionID, - planID: env.SECRET_STRIPE_PRO_PLAN_ID, - quantity, - handled: true, - }, - env - ) - } - } catch (e) { - flashSession.flash( - 'error_toast', - 'Transaction failed. You were not charged.' - ) - - return new Response(null, { - headers: { - 'Set-Cookie': await commitFlashSession(flashSession, env), - }, - }) - } - - await coreClient.account.updateEntitlements.mutate({ - accountURN: accountURN, - subscriptionID: sub.id, - quantity: quantity, - type: plan, + const quantity = entitlements.subscriptionID + ? entitlements.plans[plan]?.entitlements + ? entitlements.plans[plan]?.entitlements! + 1 + : 1 + : 1 + + const sub = await createOrUpdateSubscription({ + customerID, + SECRET_STRIPE_PRO_PLAN_ID: env.SECRET_STRIPE_PRO_PLAN_ID, + SECRET_STRIPE_API_KEY: env.SECRET_STRIPE_API_KEY, + quantity, + subscriptionID: entitlements.subscriptionID, + accountURN, }) - await coreClient.starbase.setAppPlan.mutate({ - accountURN, - clientId, - plan, + setPurchaseToastNotification({ + sub, + flashSession, }) + if (sub.status === 'active' || sub.status === 'trialing') { + await coreClient.account.updateEntitlements.mutate({ + accountURN: accountURN, + subscriptionID: sub.id, + quantity: quantity, + type: plan, + }) - flashSession.flash( - 'success_toast', - `${plans[plan].title} purchased and assigned.` - ) + await coreClient.starbase.setAppPlan.mutate({ + accountURN, + clientId, + plan, + }) + } + + return sub } export const action: ActionFunction = getRollupReqFunctionErrorWrapper( @@ -241,19 +234,42 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( }) } + const parsedJwt = parseJwt(jwt!) + const accountURN = parsedJwt.sub as AccountURN + const { clientId } = params if (!clientId) throw new BadRequestError({ message: 'Missing Client ID' }) const traceHeader = generateTraceContextHeaders(context.traceSpan) + const coreClient = createCoreClient(context.env.Core, { + ...getAuthzHeaderConditionallyFromToken(jwt), + ...traceHeader, + }) + + const spd = await coreClient.account.getStripePaymentData.query({ + accountURN, + }) + + const invoices = await getCurrentAndUpcomingInvoices( + spd, + context.env.SECRET_STRIPE_API_KEY + ) + + const flashSession = await getFlashSession(request, context.env) + + await UnpaidInvoiceNotification({ + invoices, + flashSession, + env: context.env, + }) + const fd = await request.formData() const op = fd.get('op') as 'update' | 'purchase' const { plan } = JSON.parse(fd.get('payload') as string) as { plan: ServicePlanType } - const flashSession = await getFlashSession(request, context.env) - switch (op) { case 'update': { await processUpdateOp( @@ -268,7 +284,7 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( } case 'purchase': { - await processPurchaseOp( + const sub = await processPurchaseOp( jwt, plan, clientId, @@ -276,7 +292,32 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper( context.env, traceHeader ) - break + + let status, client_secret, payment_method + if ( + sub.latest_invoice && + (sub.latest_invoice as Stripe.Invoice).payment_intent + ) { + // lots of stripe type casting since by default many + // props are strings (not expanded versions) + ;({ status, client_secret, payment_method } = ( + sub.latest_invoice as Stripe.Invoice + ).payment_intent as Stripe.PaymentIntent) + } + + return json( + { + subId: sub.id, + status, + client_secret, + payment_method, + }, + { + headers: { + 'Set-Cookie': await commitFlashSession(flashSession, context.env), + }, + } + ) } } @@ -301,6 +342,7 @@ const PlanCard = ({ usedEntitlements, paymentData, featuresColor, + hasUnpaidInvoices, }: { planType: ServicePlanType currentPlan: ServicePlanType @@ -308,6 +350,7 @@ const PlanCard = ({ usedEntitlements?: number paymentData: PaymentData featuresColor: 'text-gray-500' | 'text-indigo-500' + hasUnpaidInvoices: boolean }) => { const plan = plans[planType] const active = planType === currentPlan @@ -340,6 +383,7 @@ const PlanCard = ({ {!active && ( void plan: PlanDetails paymentData?: PaymentData + hasUnpaidInvoices: boolean }) => { const submit = useSubmit() @@ -414,7 +460,7 @@ const PurchaseConfirmationModal = ({ )} -
+
{plan.title} @@ -473,7 +519,7 @@ const PurchaseConfirmationModal = ({