OverdueInvoicePayment
The OverdueInvoicePayment component is designed to handle the payment of overdue invoices for a specific customer or subscription. It can operate in two modes: a default dialog mode that presents a pre-built UI for payment, or a custom mode that provides data and a payment handler to build a custom user interface.
This component streamlines the process of collecting late payments by summarizing amounts by currency and initiating a batch payment process through the user's DID Wallet.
When to Use#
Use this component in your application's subscription management or customer billing sections to:
- Prompt users to pay for a subscription that has fallen into a
past_duestatus. - Allow customers to clear all outstanding invoices across multiple subscriptions in a single operation.
Component Logic Flow#
The component follows a clear sequence to manage overdue payments:
Props#
The OverdueInvoicePayment component accepts the following props to customize its behavior:
Prop | Type | Required | Default Value | Description |
|---|---|---|---|---|
|
| No |
| The ID of a specific subscription to fetch overdue invoices for. |
|
| No |
| The customer's ID or DID. Used to fetch all overdue invoices for that customer. One of |
|
| No |
| In |
|
| No |
| Callback function executed after all overdue invoices for a currency are successfully paid. Receives the source ID, currency ID, and source type ( |
|
| No |
| Props to pass to the underlying Material-UI |
|
| No |
| Customizes the "View Details" link in the dialog. You can disable it, provide a custom title, or override the click handler. |
|
| No |
| If |
|
| No |
| An additional message to append to the title when fetching invoices by |
|
| No |
| A render prop function used only when |
|
| No |
| An authentication token for API requests, typically used in cross-origin or server-to-server scenarios. |
Usage Examples#
All examples assume that the component is rendered within a PaymentProvider context.
1. Default Mode for a Single Subscription#
This is the simplest use case. The component will render as a dialog prompting the user to pay the overdue amount for a specific subscription.
import { PaymentProvider, OverdueInvoicePayment } from '@blocklet/payment-react';
function SubscriptionDetailsPage({ subscriptionId, session, connectApi }) {
const handlePaymentSuccess = (id, currencyId, type) => {
console.log(`${type} with ID ${id} paid for currency ${currencyId}`);
// You can refresh your subscription data here
};
return (
<PaymentProvider session={session} connect={connectApi}>
<OverdueInvoicePayment
subscriptionId={subscriptionId}
onPaid={handlePaymentSuccess}
/>
</PaymentProvider>
);
}2. Default Mode for a Customer#
To handle all overdue invoices for a customer, provide the customerId prop. The component will summarize totals from all overdue invoices across all their subscriptions.
import { PaymentProvider, OverdueInvoicePayment } from '@blocklet/payment-react';
function CustomerBillingPage({ customerId, session, connectApi }) {
return (
<PaymentProvider session={session} connect={connectApi}>
<OverdueInvoicePayment
customerId={customerId}
onPaid={() => {
console.log('All customer overdue invoices have been paid.');
// Refresh customer and invoice data
}}
/>
</PaymentProvider>
);
}3. Custom Mode UI#
For full control over the user interface, set mode to 'custom' and provide a function as children. This function receives handlePay and a data object, allowing you to build a completely custom component.
import { PaymentProvider, OverdueInvoicePayment, Amount } from '@blocklet/payment-react';
import { Button, Card, CardContent, CardHeader, Stack, Typography } from '@mui/material';
function CustomOverdueUI({ subscriptionId, session, connectApi }) {
return (
<PaymentProvider session={session} connect={connectApi}>
<OverdueInvoicePayment
subscriptionId={subscriptionId}
onPaid={() => {
console.log('Payment successful from custom UI');
}}
mode="custom"
>
{(handlePay, { subscription, summary, invoices }) => {
if (invoices.length === 0) {
return <Typography>No overdue payments for {subscription?.description}.</Typography>;
}
return (
<Card>
<CardHeader title={`Overdue Payments for ${subscription?.description}`} />
<CardContent>
<Stack spacing={2}>
{Object.values(summary).map((info) => (
<div key={info.currency.id}>
<Typography>
Total Due: <Amount amount={info.amount} /> {info.currency?.symbol}
</Typography>
<Button
onClick={() => handlePay(info)}
variant="contained"
>
Pay with {info.currency.symbol}
</Button>
</div>
))}
</Stack>
</CardContent>
</Card>
);
}}
</OverdueInvoicePayment>
</PaymentProvider>
);
}Custom Mode data Object#
When using mode="custom", the children render prop receives a data object with the following structure:
Key | Type | Description |
|---|---|---|
|
| The full subscription object (only available if |
|
| An object where keys are currency IDs and values contain the total amount, currency, and payment method. |
|
| An array of the raw overdue invoice objects. |
|
| The total number of subscriptions with overdue invoices (only available if |
|
| A pre-generated URL pointing to the subscription details or customer invoice list page. |
Best Practices#
Controlling the Dialog in Default Mode#
While the dialog opens by default, you can manage its state from your parent component for a more integrated user experience. Pass open and onClose props via dialogProps.
import { PaymentProvider, OverdueInvoicePayment } from '@blocklet/payment-react';
import { Button } from '@mui/material';
import { useState } from 'react';
function ControlledDialogExample({ subscriptionId, session, connectApi }) {
const [isOverdueModalOpen, setOverdueModalOpen] = useState(false);
return (
<PaymentProvider session={session} connect={connectApi}>
<Button onClick={() => setOverdueModalOpen(true)}>
Pay Overdue Invoices
</Button>
{isOverdueModalOpen && (
<OverdueInvoicePayment
subscriptionId={subscriptionId}
dialogProps={{
open: isOverdueModalOpen,
onClose: () => setOverdueModalOpen(false),
}}
onPaid={() => {
setOverdueModalOpen(false);
// Refresh your data here
}}
/>
)}
</PaymentProvider>
);
}Refreshing Data After Payment#
The onPaid callback is the most reliable way to know when a payment cycle is complete. Always use it to trigger a data refresh for the relevant subscription or customer. This ensures your UI immediately reflects the new active status and removes any "past due" warnings.
Authentication for Embedded Scenarios#
When embedding the payment component in an environment where the standard session cookie might not be available (e.g., a cross-origin iframe), use the authToken prop. This token allows the component to make authenticated API requests on behalf of the user, ensuring the correct invoice data is fetched and processed.
// This is a conceptual example of how you might get a token
const authToken = await getAuthTokenForCurrentUser();
<OverdueInvoicePayment
customerId={customerId}
authToken={authToken}
/>