Skip to content

Commit

Permalink
chore(console): Handle 3D Secure Events (#2529)
Browse files Browse the repository at this point in the history
  • Loading branch information
poolsar42 committed Jul 27, 2023
1 parent 6d50119 commit 30dec8d
Show file tree
Hide file tree
Showing 25 changed files with 954 additions and 356 deletions.
Binary file not shown.
8 changes: 8 additions & 0 deletions apps/console/app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default function handleRequest(
SELF,
'https://verify.walletconnect.com',
'form.typeform.com',
'https://*.stripe.com',
],
'connect-src': [
SELF,
Expand All @@ -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,
Expand Down
31 changes: 30 additions & 1 deletion apps/console/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 [
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<LoaderData>({
apps: reshapedApps,
avatarUrl,
hasUnpaidInvoices,
PASSPORT_URL,
ENV: {
POSTHOG_API_KEY,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -246,6 +273,7 @@ export default function App() {
PASSPORT_URL,
displayName,
accountURN,
hasUnpaidInvoices,
}}
/>
</PostHogProvider>
Expand All @@ -257,6 +285,7 @@ export default function App() {
PASSPORT_URL,
displayName,
accountURN,
hasUnpaidInvoices,
}}
/>
)}
Expand Down
12 changes: 11 additions & 1 deletion apps/console/app/routes/__layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<OutletContextData>()
const { apps, avatarUrl, displayName, PASSPORT_URL } = context
const { apps, avatarUrl, displayName, PASSPORT_URL, hasUnpaidInvoices } =
context

return (
<Popover className="min-h-[100dvh] relative">
Expand All @@ -31,6 +33,14 @@ export default function DashboardIndexPage() {
/>
<main className="flex flex-col flex-initial min-h-full w-full bg-white">
<SiteHeader avatarUrl={avatarUrl} />
{hasUnpaidInvoices && (
<ToastWithLink
message="We couldn't process payment for your account"
linkHref={`/billing/portal`}
linkText="Update payment information"
type={'urgent'}
/>
)}
<div
className={`${
open
Expand Down
51 changes: 51 additions & 0 deletions apps/console/app/routes/__layout/billing/cancel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors'
import { redirect, type ActionFunction } from '@remix-run/cloudflare'
import {
commitFlashSession,
getFlashSession,
requireJWT,
} from '~/utilities/session.server'

import { voidInvoice } from '~/services/billing/stripe'
import { ToastType } from '@proofzero/design-system/src/atoms/toast'

export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context }) => {
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),
},
})
}
)
9 changes: 8 additions & 1 deletion apps/console/app/routes/__layout/billing/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => {
Expand Down Expand Up @@ -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: {
Expand Down
Loading

0 comments on commit 30dec8d

Please sign in to comment.