UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

197 lines (159 loc) 9.02 kB
# OverdueInvoicePayment The `OverdueInvoicePayment` component is a specialized tool designed to handle the payment of overdue invoices for a specific customer or subscription. It simplifies the process by automatically fetching overdue invoices and presenting users with a clear interface to settle their outstanding payments. This component can operate in two modes: a default mode that displays a pre-built dialog for quick integration, and a custom mode that provides the flexibility to build a unique user interface using a render prop. ## How It Works The component orchestrates the entire overdue payment process, from fetching data to handling the final transaction confirmation. ```d2 Overdue Payment Flow direction: down User: { shape: c4-person } Client-App: { label: "Client Application" shape: rectangle OverdueInvoicePayment-Component: { label: "OverdueInvoicePayment Component" shape: rectangle } } Payment-Backend: { label: "Payment Backend" shape: cylinder } DID-Wallet: { label: "DID Wallet" icon: "https://www.arcblock.io/image-bin/uploads/37198ddc4a0b9e91e5c1c821ab895a34.svg" } User -> Client-App.OverdueInvoicePayment-Component: "1. Renders the component" Client-App.OverdueInvoicePayment-Component -> Payment-Backend: "2. Fetch overdue invoices" Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "3. Return invoice summary" Client-App.OverdueInvoicePayment-Component -> User: "4. Display payment dialog" User -> Client-App.OverdueInvoicePayment-Component: "5. Clicks 'Pay Now'" Client-App.OverdueInvoicePayment-Component -> DID-Wallet: "6. Opens connect session (collect-batch)" User -> DID-Wallet: "7. Approves payment" DID-Wallet -> Client-App.OverdueInvoicePayment-Component: "8. Sends success callback" Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "9. WebSocket event (invoice.paid)" Client-App.OverdueInvoicePayment-Component -> User: "10. Update UI (e.g., close dialog)" ``` ## Props The `OverdueInvoicePayment` component accepts the following props to customize its behavior: | Prop | Type | Description | |---|---|---| | `subscriptionId` | `string` | The ID of the subscription to check for overdue invoices. Either `subscriptionId` or `customerId` must be provided. | | `customerId` | `string` | The ID or DID of the customer. Use this to handle all overdue invoices for a customer. | | `mode` | `'default'` \| `'custom'` | The rendering mode. `'default'` shows a pre-built dialog. `'custom'` uses the `children` render prop for a custom UI. Defaults to `'default'`. | | `onPaid` | `(id, currencyId, type) => void` | An optional callback function that is triggered after payment is successfully completed. `id` will be the `subscriptionId` or `customerId`, `type` will be `'subscription'` or `'customer'`. | | `dialogProps` | `object` | Optional props to pass to the underlying Material-UI `Dialog` component in `default` mode. e.g., `{ open: true, title: 'Custom Title', onClose: handleClose }`. | | `detailLinkOptions` | `object` | Optional settings for the "View Details" link. Can be used to disable the link, change its text, or provide a custom `onClick` handler. Format: `{ enabled?: boolean, onClick?: function, title?: string }`. | | `successToast` | `boolean` | If `true`, a success toast notification is shown upon successful payment. Defaults to `true`. | | `alertMessage` | `string` | An optional message to append to the default title text when in customer mode. | | `children` | `(handlePay, data) => React.ReactNode` | A render prop function used only when `mode` is `'custom'`. It receives a `handlePay` function and a `data` object. | | `authToken` | `string` | An optional authentication token for API requests, useful for server-to-server or cross-origin scenarios. | ### `children` Render Prop When using `mode="custom"`, the `children` function receives two arguments: 1. **`handlePay(item: SummaryItem)`**: A function to initiate the payment process for a specific currency group. The `item` object comes from the `data.summary` object. 2. **`data`**: An object containing the fetched payment information: * `subscription?: Subscription`: The subscription details, if `subscriptionId` was provided. * `summary: { [key: string]: SummaryItem }`: An object where each key is a currency ID and the value contains the total amount, currency details, and payment method. * `invoices: Invoice[]`: An array of all overdue invoice objects. * `subscriptionCount?: number`: The number of subscriptions with overdue invoices (for customer mode). * `detailUrl: string`: The URL to view detailed invoice information. ## Usage Examples All examples assume you have `PaymentProvider` set up in your application. ### 1. Default Mode for a Subscription This is the simplest way to handle overdue payments for a specific subscription. The component will automatically render a dialog if any overdue invoices are found. ```tsx SubscriptionOverdue.tsx icon=logos:react import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react'; import { useSessionContext } from './hooks/session'; // Your custom session hook function SubscriptionPage({ subscriptionId }) { const { session, connect } = useSessionContext(); const handlePaymentSuccess = (id, currencyId, type) => { console.log(`Payment successful for ${type} ${id} with currency ${currencyId}`); // You can refetch subscription data here to update its status }; return ( <PaymentProvider session={session} connect={connect}> {/* This component will be null if there are no overdue invoices */} <OverdueInvoicePayment subscriptionId={subscriptionId} onPaid={handlePaymentSuccess} /> {/* Other subscription details can be rendered here */} </PaymentProvider> ); } ``` ### 2. Default Mode for a Customer Use this to create a centralized place for a customer to pay all their overdue invoices across multiple subscriptions. ```tsx CustomerDashboard.tsx icon=logos:react import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react'; import { useSessionContext } from './hooks/session'; // Your custom session hook function CustomerDashboard() { const { session, connect } = useSessionContext(); return ( <PaymentProvider session={session} connect={connect}> <h2>Payment Center</h2> <p>Please settle any outstanding payments to ensure uninterrupted service.</p> <OverdueInvoicePayment customerId={session.user.did} onPaid={() => { console.log('All customer overdue invoices paid for a currency!'); // Refresh customer account status }} /> {/* The rest of the customer dashboard */} </PaymentProvider> ); } ``` ### 3. Custom UI Mode For full control over the user experience, use `mode="custom"`. This allows you to integrate the payment functionality directly into your existing UI instead of using a dialog. ```tsx CustomOverdueUI.tsx icon=logos:react import { OverdueInvoicePayment, PaymentProvider, Amount } from '@blocklet/payment-react'; import { useSessionContext } from './hooks/session'; // Your custom session hook import { Card, CardContent, Typography, Button, Stack } from '@mui/material'; function CustomOverdueUI({ subscriptionId }) { const { session, connect } = useSessionContext(); return ( <PaymentProvider session={session} connect={connect}> <OverdueInvoicePayment subscriptionId={subscriptionId} mode="custom" onPaid={() => console.log('Custom UI payment successful!')} > {(handlePay, { summary, invoices }) => { const summaryList = Object.values(summary); if (invoices.length === 0) { return <Typography>No overdue payments. All clear!</Typography>; } return ( <Card variant="outlined"> <CardContent> <Typography variant="h6" color="error" gutterBottom> You have {invoices.length} overdue invoice(s). </Typography> <Stack spacing={2} mt={2}> {summaryList.map((item) => ( <Stack key={item.currency.id} direction="row" justifyContent="space-between" alignItems="center"> <Typography> Total Due: <Amount amount={item.amount} decimal={item.currency.decimal} symbol={item.currency.symbol} /> </Typography> <Button variant="contained" color="primary" onClick={() => handlePay(item)} > Pay with {item.currency.symbol} </Button> </Stack> ))} </Stack> </CardContent> </Card> ); }} </OverdueInvoicePayment> </PaymentProvider> ); } ```