Used to check for browser translation.
用于检测浏览器翻译。
ブラウザの翻訳を検出する
Components

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_due status.
  • 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:

Payment Service APIPaymentProviderOverdueInvoicePaymentYour ApplicationUserPayment Service APIPaymentProviderOverdueInvoicePaymentYour ApplicationUseralt[Invoices exist][No invoices]Views a page with overdue invoicesRenders with subscriptionId or customerIdFetches overdue invoicesReturns summary and list of invoicesRenders payment UI (dialog or custom)Clicks "Pay Now" for a currencyCalls connect.open() with payment detailsShows DID Wallet connect modalScans and confirms paymentProcesses batch paymentPayment successfulTriggers onSuccess callbackRefreshes invoice dataCloses dialog (if applicable) and calls onPaid()Displays a success or empty state message

Props#

The OverdueInvoicePayment component accepts the following props to customize its behavior:

Prop

Type

Required

Default Value

Description

subscriptionId

string

No

undefined

The ID of a specific subscription to fetch overdue invoices for.

customerId

string

No

undefined

The customer's ID or DID. Used to fetch all overdue invoices for that customer. One of subscriptionId or customerId must be provided.

mode

'default' | 'custom'

No

'default'

In default mode, a dialog is shown. In custom mode, you use a render prop to build your own UI.

onPaid

(id, currencyId, type) => void

No

() => {}

Callback function executed after all overdue invoices for a currency are successfully paid. Receives the source ID, currency ID, and source type ('subscription' or 'customer').

dialogProps

object

No

{ open: true }

Props to pass to the underlying Material-UI Dialog component in default mode. Can be used to control its open state, title, onClose behavior, etc.

detailLinkOptions

{ enabled?: boolean; onClick?: (e) => void; title?: string; }

No

{ enabled: true }

Customizes the "View Details" link in the dialog. You can disable it, provide a custom title, or override the click handler.

successToast

boolean

No

true

If true, a success toast notification is shown upon successful payment.

alertMessage

string

No

''

An additional message to append to the title when fetching invoices by customerId.

children

(handlePay, data) => React.ReactNode

No

undefined

A render prop function used only when mode is set to 'custom'. It receives a payment handler and the invoice data.

authToken

string

No

undefined

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

subscription

Subscription

The full subscription object (only available if subscriptionId is provided).

summary

{ [key: string]: SummaryItem }

An object where keys are currency IDs and values contain the total amount, currency, and payment method.

invoices

Invoice[]

An array of the raw overdue invoice objects.

subscriptionCount

number

The total number of subscriptions with overdue invoices (only available if customerId is provided).

detailUrl

string

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}
/>