@blocklet/payment-react 1.20.15 → 1.20.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aigne/doc-smith/config.yaml +7 -1
- package/.aigne/doc-smith/upload-cache.yaml +441 -0
- package/docs/components-business-auto-topup.ja.md +187 -0
- package/docs/components-business-auto-topup.zh-TW.md +187 -0
- package/docs/components-business-auto-topup.zh.md +187 -0
- package/docs/components-business-overdue-invoice-payment.ja.md +196 -0
- package/docs/components-business-overdue-invoice-payment.zh-TW.md +197 -0
- package/docs/components-business-overdue-invoice-payment.zh.md +197 -0
- package/docs/components-business-resume-subscription.ja.md +190 -0
- package/docs/components-business-resume-subscription.zh-TW.md +190 -0
- package/docs/components-business-resume-subscription.zh.md +190 -0
- package/docs/components-business.ja.md +21 -0
- package/docs/components-business.zh-TW.md +21 -0
- package/docs/components-business.zh.md +21 -0
- package/docs/components-checkout-checkout-donate.ja.md +259 -0
- package/docs/components-checkout-checkout-donate.zh-TW.md +259 -0
- package/docs/components-checkout-checkout-donate.zh.md +259 -0
- package/docs/components-checkout-checkout-form.ja.md +163 -0
- package/docs/components-checkout-checkout-form.zh-TW.md +163 -0
- package/docs/components-checkout-checkout-form.zh.md +163 -0
- package/docs/components-checkout-checkout-table.ja.md +148 -0
- package/docs/components-checkout-checkout-table.zh-TW.md +148 -0
- package/docs/components-checkout-checkout-table.zh.md +149 -0
- package/docs/components-checkout.ja.md +65 -0
- package/docs/components-checkout.zh-TW.md +65 -0
- package/docs/components-checkout.zh.md +65 -0
- package/docs/components-history-credit-grants-list.ja.md +73 -0
- package/docs/components-history-credit-grants-list.zh-TW.md +73 -0
- package/docs/components-history-credit-grants-list.zh.md +73 -0
- package/docs/components-history-credit-transactions-list.ja.md +106 -0
- package/docs/components-history-credit-transactions-list.zh-TW.md +106 -0
- package/docs/components-history-credit-transactions-list.zh.md +106 -0
- package/docs/components-history-invoice-list.ja.md +110 -0
- package/docs/components-history-invoice-list.zh-TW.md +110 -0
- package/docs/components-history-invoice-list.zh.md +110 -0
- package/docs/components-history-payment-list.ja.md +44 -0
- package/docs/components-history-payment-list.zh-TW.md +44 -0
- package/docs/components-history-payment-list.zh.md +44 -0
- package/docs/components-history.ja.md +67 -0
- package/docs/components-history.zh-TW.md +67 -0
- package/docs/components-history.zh.md +67 -0
- package/docs/components-ui-form-elements-address-form.ja.md +121 -0
- package/docs/components-ui-form-elements-address-form.zh-TW.md +121 -0
- package/docs/components-ui-form-elements-address-form.zh.md +121 -0
- package/docs/components-ui-form-elements-country-select.ja.md +126 -0
- package/docs/components-ui-form-elements-country-select.zh-TW.md +126 -0
- package/docs/components-ui-form-elements-country-select.zh.md +126 -0
- package/docs/components-ui-form-elements-currency-selector.ja.md +108 -0
- package/docs/components-ui-form-elements-currency-selector.zh-TW.md +108 -0
- package/docs/components-ui-form-elements-currency-selector.zh.md +108 -0
- package/docs/components-ui-form-elements-phone-input.ja.md +138 -0
- package/docs/components-ui-form-elements-phone-input.zh-TW.md +138 -0
- package/docs/components-ui-form-elements-phone-input.zh.md +139 -0
- package/docs/components-ui-form-elements.ja.md +91 -0
- package/docs/components-ui-form-elements.zh-TW.md +91 -0
- package/docs/components-ui-form-elements.zh.md +91 -0
- package/docs/components-ui-payment-summary.ja.md +109 -0
- package/docs/components-ui-payment-summary.zh-TW.md +109 -0
- package/docs/components-ui-payment-summary.zh.md +109 -0
- package/docs/components-ui-pricing-table.ja.md +140 -0
- package/docs/components-ui-pricing-table.zh-TW.md +140 -0
- package/docs/components-ui-pricing-table.zh.md +140 -0
- package/docs/components-ui.ja.md +71 -0
- package/docs/components-ui.zh-TW.md +71 -0
- package/docs/components-ui.zh.md +71 -0
- package/docs/components.ja.md +122 -0
- package/docs/components.zh-TW.md +122 -0
- package/docs/components.zh.md +122 -0
- package/docs/getting-started.ja.md +84 -0
- package/docs/getting-started.zh-TW.md +84 -0
- package/docs/getting-started.zh.md +84 -0
- package/docs/guides-theming.ja.md +213 -0
- package/docs/guides-theming.zh-TW.md +213 -0
- package/docs/guides-theming.zh.md +213 -0
- package/docs/guides-utilities.ja.md +197 -0
- package/docs/guides-utilities.zh-TW.md +197 -0
- package/docs/guides-utilities.zh.md +197 -0
- package/docs/guides.ja.md +18 -0
- package/docs/guides.zh-TW.md +18 -0
- package/docs/guides.zh.md +18 -0
- package/docs/hooks-use-mobile.ja.md +84 -0
- package/docs/hooks-use-mobile.zh-TW.md +84 -0
- package/docs/hooks-use-mobile.zh.md +84 -0
- package/docs/hooks-use-subscription.ja.md +111 -0
- package/docs/hooks-use-subscription.zh-TW.md +111 -0
- package/docs/hooks-use-subscription.zh.md +110 -0
- package/docs/hooks.ja.md +14 -0
- package/docs/hooks.zh-TW.md +14 -0
- package/docs/hooks.zh.md +14 -0
- package/docs/overview.ja.md +80 -0
- package/docs/overview.zh-TW.md +80 -0
- package/docs/overview.zh.md +80 -0
- package/docs/providers-donate-provider.ja.md +153 -0
- package/docs/providers-donate-provider.zh-TW.md +153 -0
- package/docs/providers-donate-provider.zh.md +153 -0
- package/docs/providers-payment-provider.ja.md +191 -0
- package/docs/providers-payment-provider.zh-TW.md +191 -0
- package/docs/providers-payment-provider.zh.md +191 -0
- package/docs/providers.ja.md +42 -0
- package/docs/providers.zh-TW.md +42 -0
- package/docs/providers.zh.md +42 -0
- package/es/locales/en.js +13 -3
- package/es/locales/zh.js +13 -3
- package/es/payment/product-item.js +123 -20
- package/es/payment/success.js +2 -2
- package/lib/locales/en.js +13 -3
- package/lib/locales/zh.js +13 -3
- package/lib/payment/product-item.js +136 -32
- package/lib/payment/success.js +2 -2
- package/package.json +5 -5
- package/src/locales/en.tsx +18 -3
- package/src/locales/zh.tsx +17 -3
- package/src/payment/product-item.tsx +140 -19
- package/src/payment/success.tsx +2 -2
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# OverdueInvoicePayment
|
|
2
|
+
|
|
3
|
+
`OverdueInvoicePayment` 元件是一個專門用於處理特定客戶或訂閱的逾期發票付款的工具。它透過自動擷取逾期發票並向使用者呈現一個清晰的介面來結清其未付帳款,從而簡化了流程。
|
|
4
|
+
|
|
5
|
+
該元件可以在兩種模式下運作:一種是預設模式,會顯示一個預先建置的對話方塊以便快速整合;另一種是自訂模式,它提供了使用 render prop 建立獨特使用者介面的靈活性。
|
|
6
|
+
|
|
7
|
+
## 運作方式
|
|
8
|
+
|
|
9
|
+
該元件協調整個逾期付款流程,從擷取資料到處理最終的交易確認。
|
|
10
|
+
|
|
11
|
+
```d2 逾期支付流程
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
User: {
|
|
15
|
+
label: "使用者"
|
|
16
|
+
shape: c4-person
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Client-App: {
|
|
20
|
+
label: "客戶端應用程式"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
|
|
23
|
+
OverdueInvoicePayment-Component: {
|
|
24
|
+
label: "OverdueInvoicePayment 元件"
|
|
25
|
+
shape: rectangle
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Payment-Backend: {
|
|
30
|
+
label: "支付後端"
|
|
31
|
+
shape: cylinder
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
DID-Wallet: {
|
|
35
|
+
label: "DID 錢包"
|
|
36
|
+
icon: "https://www.arcblock.io/image-bin/uploads/37198ddc4a0b9e91e5c1c821ab895a34.svg"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
User -> Client-App.OverdueInvoicePayment-Component: "1. 渲染元件"
|
|
40
|
+
Client-App.OverdueInvoicePayment-Component -> Payment-Backend: "2. 擷取逾期發票"
|
|
41
|
+
Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "3. 回傳發票摘要"
|
|
42
|
+
Client-App.OverdueInvoicePayment-Component -> User: "4. 顯示支付對話方塊"
|
|
43
|
+
User -> Client-App.OverdueInvoicePayment-Component: "5. 點擊「立即支付」"
|
|
44
|
+
Client-App.OverdueInvoicePayment-Component -> DID-Wallet: "6. 開啟連接會話 (collect-batch)"
|
|
45
|
+
User -> DID-Wallet: "7. 批准支付"
|
|
46
|
+
DID-Wallet -> Client-App.OverdueInvoicePayment-Component: "8. 發送成功回呼"
|
|
47
|
+
Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "9. WebSocket 事件 (invoice.paid)"
|
|
48
|
+
Client-App.OverdueInvoicePayment-Component -> User: "10. 更新 UI (例如,關閉對話方塊)"
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Props
|
|
53
|
+
|
|
54
|
+
`OverdueInvoicePayment` 元件接受以下 props 來自訂其行為:
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Description |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `subscriptionId` | `string` | 要檢查逾期發票的訂閱 ID。必須提供 `subscriptionId` 或 `customerId` 其中之一。 |
|
|
59
|
+
| `customerId` | `string` | 客戶的 ID 或 DID。使用此項來處理某位客戶的所有逾期發票。 |
|
|
60
|
+
| `mode` | `'default'` \| `'custom'` | 渲染模式。`'default'` 會顯示一個預先建置的對話方塊。`'custom'` 使用 `children` render prop 來建立自訂 UI。預設為 `'default'`。 |
|
|
61
|
+
| `onPaid` | `(id, currencyId, type) => void` | 一個可選的回呼函式,在支付成功完成後觸發。`id` 將是 `subscriptionId` 或 `customerId`,`type` 將是 `'subscription'` 或 `'customer'`。 |
|
|
62
|
+
| `dialogProps` | `object` | 在 `default` 模式下,傳遞給底層 Material-UI `Dialog` 元件的可選 props。例如:`{ open: true, title: '自訂標題', onClose: handleClose }`。 |
|
|
63
|
+
| `detailLinkOptions` | `object` | 「查看詳情」連結的可選設定。可用於停用連結、變更其文字或提供自訂的 `onClick` 處理常式。格式:`{ enabled?: boolean, onClick?: function, title?: string }`。 |
|
|
64
|
+
| `successToast` | `boolean` | 如果為 `true`,支付成功後會顯示一個成功的 toast 通知。預設為 `true`。 |
|
|
65
|
+
| `alertMessage` | `string` | 在客戶模式下,附加到預設標題文字的可選訊息。 |
|
|
66
|
+
| `children` | `(handlePay, data) => React.ReactNode` | 僅在 `mode` 為 `'custom'` 時使用的 render prop 函式。它會接收一個 `handlePay` 函式和一個 `data` 物件。 |
|
|
67
|
+
| `authToken` | `string` | 用於 API 請求的可選身份驗證權杖,適用於伺服器對伺服器或跨來源的情境。 |
|
|
68
|
+
|
|
69
|
+
### `children` Render Prop
|
|
70
|
+
|
|
71
|
+
當使用 `mode="custom"` 時,`children` 函式會接收兩個參數:
|
|
72
|
+
|
|
73
|
+
1. **`handlePay(item: SummaryItem)`**:一個為特定貨幣群組啟動支付流程的函式。`item` 物件來自 `data.summary` 物件。
|
|
74
|
+
2. **`data`**:一個包含已擷取支付資訊的物件:
|
|
75
|
+
* `subscription?: Subscription`:訂閱詳情,如果提供了 `subscriptionId`。
|
|
76
|
+
* `summary: { [key: string]: SummaryItem }`:一個物件,其中每個鍵是貨幣 ID,值包含總金額、貨幣詳情和支付方式。
|
|
77
|
+
* `invoices: Invoice[]`:一個包含所有逾期發票物件的陣列。
|
|
78
|
+
* `subscriptionCount?: number`:有逾期發票的訂閱數量(適用於客戶模式)。
|
|
79
|
+
* `detailUrl: string`:查看詳細發票資訊的 URL。
|
|
80
|
+
|
|
81
|
+
## 使用範例
|
|
82
|
+
|
|
83
|
+
所有範例都假設您已在應用程式中設定好 `PaymentProvider`。
|
|
84
|
+
|
|
85
|
+
### 1. 訂閱的預設模式
|
|
86
|
+
|
|
87
|
+
這是處理特定訂閱逾期付款的最簡單方法。如果發現任何逾期發票,該元件將自動渲染一個對話方塊。
|
|
88
|
+
|
|
89
|
+
```tsx SubscriptionOverdue.tsx icon=logos:react
|
|
90
|
+
import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react';
|
|
91
|
+
import { useSessionContext } from './hooks/session'; // 您的自訂 session hook
|
|
92
|
+
|
|
93
|
+
function SubscriptionPage({ subscriptionId }) {
|
|
94
|
+
const { session, connect } = useSessionContext();
|
|
95
|
+
|
|
96
|
+
const handlePaymentSuccess = (id, currencyId, type) => {
|
|
97
|
+
console.log(`為 ${type} ${id} 使用貨幣 ${currencyId} 成功付款`);
|
|
98
|
+
// 您可以在此處重新擷取訂閱資料以更新其狀態
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<PaymentProvider session={session} connect={connect}>
|
|
103
|
+
{/* 如果沒有逾期發票,此元件將為 null */}
|
|
104
|
+
<OverdueInvoicePayment
|
|
105
|
+
subscriptionId={subscriptionId}
|
|
106
|
+
onPaid={handlePaymentSuccess}
|
|
107
|
+
/>
|
|
108
|
+
{/* 其他訂閱詳情可在此處渲染 */}
|
|
109
|
+
</PaymentProvider>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 2. 客戶的預設模式
|
|
115
|
+
|
|
116
|
+
使用此模式為客戶建立一個集中的地方,以支付其所有跨多個訂閱的逾期發票。
|
|
117
|
+
|
|
118
|
+
```tsx CustomerDashboard.tsx icon=logos:react
|
|
119
|
+
import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react';
|
|
120
|
+
import { useSessionContext } from './hooks/session'; // 您的自訂 session hook
|
|
121
|
+
|
|
122
|
+
function CustomerDashboard() {
|
|
123
|
+
const { session, connect } = useSessionContext();
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<PaymentProvider session={session} connect={connect}>
|
|
127
|
+
<h2>Payment Center</h2>
|
|
128
|
+
<p>Please settle any outstanding payments to ensure uninterrupted service.</p>
|
|
129
|
+
<OverdueInvoicePayment
|
|
130
|
+
customerId={session.user.did}
|
|
131
|
+
onPaid={() => {
|
|
132
|
+
console.log('客戶所有以某貨幣計價的逾期發票均已支付!');
|
|
133
|
+
// 重新整理客戶帳戶狀態
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
{/* 客戶儀表板的其餘部分 */}
|
|
137
|
+
</PaymentProvider>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. 自訂 UI 模式
|
|
143
|
+
|
|
144
|
+
為了完全控制使用者體驗,請使用 `mode="custom"`。這讓您可以將支付功能直接整合到您現有的 UI 中,而不是使用對話方塊。
|
|
145
|
+
|
|
146
|
+
```tsx CustomOverdueUI.tsx icon=logos:react
|
|
147
|
+
import { OverdueInvoicePayment, PaymentProvider, Amount } from '@blocklet/payment-react';
|
|
148
|
+
import { useSessionContext } from './hooks/session'; // 您的自訂 session hook
|
|
149
|
+
import { Card, CardContent, Typography, Button, Stack } from '@mui/material';
|
|
150
|
+
|
|
151
|
+
function CustomOverdueUI({ subscriptionId }) {
|
|
152
|
+
const { session, connect } = useSessionContext();
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<PaymentProvider session={session} connect={connect}>
|
|
156
|
+
<OverdueInvoicePayment
|
|
157
|
+
subscriptionId={subscriptionId}
|
|
158
|
+
mode="custom"
|
|
159
|
+
onPaid={() => console.log('自訂 UI 支付成功!')}
|
|
160
|
+
>
|
|
161
|
+
{(handlePay, { summary, invoices }) => {
|
|
162
|
+
const summaryList = Object.values(summary);
|
|
163
|
+
if (invoices.length === 0) {
|
|
164
|
+
return <Typography>沒有逾期付款。一切正常!</Typography>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<Card variant="outlined">
|
|
169
|
+
<CardContent>
|
|
170
|
+
<Typography variant="h6" color="error" gutterBottom>
|
|
171
|
+
您有 {invoices.length} 張逾期發票。
|
|
172
|
+
</Typography>
|
|
173
|
+
<Stack spacing={2} mt={2}>
|
|
174
|
+
{summaryList.map((item) => (
|
|
175
|
+
<Stack key={item.currency.id} direction="row" justifyContent="space-between" alignItems="center">
|
|
176
|
+
<Typography>
|
|
177
|
+
應付總額: <Amount amount={item.amount} decimal={item.currency.decimal} symbol={item.currency.symbol} />
|
|
178
|
+
</Typography>
|
|
179
|
+
<Button
|
|
180
|
+
variant="contained"
|
|
181
|
+
color="primary"
|
|
182
|
+
onClick={() => handlePay(item)}
|
|
183
|
+
>
|
|
184
|
+
使用 {item.currency.symbol} 支付
|
|
185
|
+
</Button>
|
|
186
|
+
</Stack>
|
|
187
|
+
))}
|
|
188
|
+
</Stack>
|
|
189
|
+
</CardContent>
|
|
190
|
+
</Card>
|
|
191
|
+
);
|
|
192
|
+
}}
|
|
193
|
+
</OverdueInvoicePayment>
|
|
194
|
+
</PaymentProvider>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# OverdueInvoicePayment
|
|
2
|
+
|
|
3
|
+
`OverdueInvoicePayment` 组件是一个专用工具,旨在处理特定客户或订阅的逾期发票支付。它通过自动获取逾期发票并为用户提供一个清晰的界面来结算其未付账款,从而简化了流程。
|
|
4
|
+
|
|
5
|
+
该组件可以在两种模式下运行:一种是默认模式,显示一个预构建的对话框以便快速集成;另一种是自定义模式,提供使用渲染属性(render prop)构建独特用户界面的灵活性。
|
|
6
|
+
|
|
7
|
+
## 工作原理
|
|
8
|
+
|
|
9
|
+
该组件协调整个逾期支付过程,从获取数据到处理最终的交易确认。
|
|
10
|
+
|
|
11
|
+
```d2 Overdue Payment Flow
|
|
12
|
+
direction: down
|
|
13
|
+
|
|
14
|
+
User: {
|
|
15
|
+
shape: c4-person
|
|
16
|
+
label: "用户"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Client-App: {
|
|
20
|
+
label: "客户端应用"
|
|
21
|
+
shape: rectangle
|
|
22
|
+
|
|
23
|
+
OverdueInvoicePayment-Component: {
|
|
24
|
+
label: "OverdueInvoicePayment 组件"
|
|
25
|
+
shape: rectangle
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Payment-Backend: {
|
|
30
|
+
label: "支付后端"
|
|
31
|
+
shape: cylinder
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
DID-Wallet: {
|
|
35
|
+
label: "DID 钱包"
|
|
36
|
+
icon: "https://www.arcblock.io/image-bin/uploads/37198ddc4a0b9e91e5c1c821ab895a34.svg"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
User -> Client-App.OverdueInvoicePayment-Component: "1. 渲染组件"
|
|
40
|
+
Client-App.OverdueInvoicePayment-Component -> Payment-Backend: "2. 获取逾期发票"
|
|
41
|
+
Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "3. 返回发票摘要"
|
|
42
|
+
Client-App.OverdueInvoicePayment-Component -> User: "4. 显示支付对话框"
|
|
43
|
+
User -> Client-App.OverdueInvoicePayment-Component: "5. 点击“立即支付”"
|
|
44
|
+
Client-App.OverdueInvoicePayment-Component -> DID-Wallet: "6. 打开连接会话 (collect-batch)"
|
|
45
|
+
User -> DID-Wallet: "7. 批准支付"
|
|
46
|
+
DID-Wallet -> Client-App.OverdueInvoicePayment-Component: "8. 发送成功回调"
|
|
47
|
+
Payment-Backend -> Client-App.OverdueInvoicePayment-Component: "9. WebSocket 事件 (invoice.paid)"
|
|
48
|
+
Client-App.OverdueInvoicePayment-Component -> User: "10. 更新 UI (例如,关闭对话框)"
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 属性
|
|
53
|
+
|
|
54
|
+
`OverdueInvoicePayment` 组件接受以下属性来自定义其行为:
|
|
55
|
+
|
|
56
|
+
| 属性 | 类型 | 描述 |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `subscriptionId` | `string` | 要检查逾期发票的订阅 ID。必须提供 `subscriptionId` 或 `customerId`。 |
|
|
59
|
+
| `customerId` | `string` | 客户的 ID 或 DID。使用此属性可处理一个客户的所有逾期发票。 |
|
|
60
|
+
| `mode` | `'default'` \| `'custom'` | 渲染模式。`'default'` 显示预构建的对话框。`'custom'` 使用 `children` 渲染属性构建自定义 UI。默认为 `'default'`。 |
|
|
61
|
+
| `onPaid` | `(id, currencyId, type) => void` | 支付成功后触发的可选回调函数。`id` 将是 `subscriptionId` 或 `customerId`,`type` 将是 `'subscription'` 或 `'customer'`。 |
|
|
62
|
+
| `dialogProps` | `object` | 在 `default` 模式下,传递给底层 Material-UI `Dialog` 组件的可选属性。例如:`{ open: true, title: '自定义标题', onClose: handleClose }`。 |
|
|
63
|
+
| `detailLinkOptions` | `object` | “查看详情”链接的可选设置。可用于禁用链接、更改其文本或提供自定义的 `onClick` 处理程序。格式:`{ enabled?: boolean, onClick?: function, title?: string }`。 |
|
|
64
|
+
| `successToast` | `boolean` | 如果为 `true`,支付成功后会显示一个成功的 toast 通知。默认为 `true`。 |
|
|
65
|
+
| `alertMessage` | `string` | 在客户模式下,附加到默认标题文本的可选消息。 |
|
|
66
|
+
| `children` | `(handlePay, data) => React.ReactNode` | 仅在 `mode` 为 `'custom'` 时使用的渲染属性函数。它接收一个 `handlePay` 函数和一个 `data` 对象。 |
|
|
67
|
+
| `authToken` | `string` | 用于 API 请求的可选身份验证令牌,适用于服务器到服务器或跨域场景。 |
|
|
68
|
+
|
|
69
|
+
### `children` 渲染属性
|
|
70
|
+
|
|
71
|
+
当使用 `mode="custom"` 时,`children` 函数接收两个参数:
|
|
72
|
+
|
|
73
|
+
1. **`handlePay(item: SummaryItem)`**:一个为特定货币组启动支付流程的函数。`item` 对象来自 `data.summary` 对象。
|
|
74
|
+
2. **`data`**:一个包含获取到的支付信息的对象:
|
|
75
|
+
* `subscription?: Subscription`:订阅详情,如果提供了 `subscriptionId`。
|
|
76
|
+
* `summary: { [key: string]: SummaryItem }`:一个对象,其中每个键是货币 ID,值包含总金额、货币详情和支付方式。
|
|
77
|
+
* `invoices: Invoice[]`:包含所有逾期发票对象的数组。
|
|
78
|
+
* `subscriptionCount?: number`:有逾期发票的订阅数量(用于客户模式)。
|
|
79
|
+
* `detailUrl: string`:用于查看详细发票信息的 URL。
|
|
80
|
+
|
|
81
|
+
## 使用示例
|
|
82
|
+
|
|
83
|
+
所有示例都假定你已在应用程序中设置了 `PaymentProvider`。
|
|
84
|
+
|
|
85
|
+
### 1. 订阅的默认模式
|
|
86
|
+
|
|
87
|
+
这是处理特定订阅逾期付款的最简单方法。如果发现任何逾期发票,该组件将自动渲染一个对话框。
|
|
88
|
+
|
|
89
|
+
```tsx SubscriptionOverdue.tsx icon=logos:react
|
|
90
|
+
import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react';
|
|
91
|
+
import { useSessionContext } from './hooks/session'; // 你的自定义 session hook
|
|
92
|
+
|
|
93
|
+
function SubscriptionPage({ subscriptionId }) {
|
|
94
|
+
const { session, connect } = useSessionContext();
|
|
95
|
+
|
|
96
|
+
const handlePaymentSuccess = (id, currencyId, type) => {
|
|
97
|
+
console.log(`类型为 ${type} 的 ${id} 使用货币 ${currencyId} 支付成功`);
|
|
98
|
+
// 你可以在此处重新获取订阅数据以更新其状态
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<PaymentProvider session={session} connect={connect}>
|
|
103
|
+
{/* 如果没有逾期发票,此组件将为 null */}
|
|
104
|
+
<OverdueInvoicePayment
|
|
105
|
+
subscriptionId={subscriptionId}
|
|
106
|
+
onPaid={handlePaymentSuccess}
|
|
107
|
+
/>
|
|
108
|
+
{/* 其他订阅详情可在此处渲染 */}
|
|
109
|
+
</PaymentProvider>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 2. 客户的默认模式
|
|
115
|
+
|
|
116
|
+
使用此模式可以创建一个集中的地方,让客户支付其所有订阅的逾期发票。
|
|
117
|
+
|
|
118
|
+
```tsx CustomerDashboard.tsx icon=logos:react
|
|
119
|
+
import { OverdueInvoicePayment, PaymentProvider } from '@blocklet/payment-react';
|
|
120
|
+
import { useSessionContext } from './hooks/session'; // 你的自定义 session hook
|
|
121
|
+
|
|
122
|
+
function CustomerDashboard() {
|
|
123
|
+
const { session, connect } = useSessionContext();
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<PaymentProvider session={session} connect={connect}>
|
|
127
|
+
<h2>支付中心</h2>
|
|
128
|
+
<p>请结清所有未付账款,以确保服务不被中断。</p>
|
|
129
|
+
<OverdueInvoicePayment
|
|
130
|
+
customerId={session.user.did}
|
|
131
|
+
onPaid={() => {
|
|
132
|
+
console.log('客户某种货币的所有逾期发票已支付!');
|
|
133
|
+
// 刷新客户账户状态
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
{/* 客户仪表盘的其余部分 */}
|
|
137
|
+
</PaymentProvider>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. 自定义 UI 模式
|
|
143
|
+
|
|
144
|
+
要完全控制用户体验,请使用 `mode="custom"`。这允许您将支付功能直接集成到现有 UI 中,而不是使用对话框。
|
|
145
|
+
|
|
146
|
+
```tsx CustomOverdueUI.tsx icon=logos:react
|
|
147
|
+
import { OverdueInvoicePayment, PaymentProvider, Amount } from '@blocklet/payment-react';
|
|
148
|
+
import { useSessionContext } from './hooks/session'; // 你的自定义 session hook
|
|
149
|
+
import { Card, CardContent, Typography, Button, Stack } from '@mui/material';
|
|
150
|
+
|
|
151
|
+
function CustomOverdueUI({ subscriptionId }) {
|
|
152
|
+
const { session, connect } = useSessionContext();
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<PaymentProvider session={session} connect={connect}>
|
|
156
|
+
<OverdueInvoicePayment
|
|
157
|
+
subscriptionId={subscriptionId}
|
|
158
|
+
mode="custom"
|
|
159
|
+
onPaid={() => console.log('自定义 UI 支付成功!')}
|
|
160
|
+
>
|
|
161
|
+
{(handlePay, { summary, invoices }) => {
|
|
162
|
+
const summaryList = Object.values(summary);
|
|
163
|
+
if (invoices.length === 0) {
|
|
164
|
+
return <Typography>没有逾期付款。一切正常!</Typography>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<Card variant="outlined">
|
|
169
|
+
<CardContent>
|
|
170
|
+
<Typography variant="h6" color="error" gutterBottom>
|
|
171
|
+
您有 {invoices.length} 张逾期发票。
|
|
172
|
+
</Typography>
|
|
173
|
+
<Stack spacing={2} mt={2}>
|
|
174
|
+
{summaryList.map((item) => (
|
|
175
|
+
<Stack key={item.currency.id} direction="row" justifyContent="space-between" alignItems="center">
|
|
176
|
+
<Typography>
|
|
177
|
+
应付总额: <Amount amount={item.amount} decimal={item.currency.decimal} symbol={item.currency.symbol} />
|
|
178
|
+
</Typography>
|
|
179
|
+
<Button
|
|
180
|
+
variant="contained"
|
|
181
|
+
color="primary"
|
|
182
|
+
onClick={() => handlePay(item)}
|
|
183
|
+
>
|
|
184
|
+
使用 {item.currency.symbol} 支付
|
|
185
|
+
</Button>
|
|
186
|
+
</Stack>
|
|
187
|
+
))}
|
|
188
|
+
</Stack>
|
|
189
|
+
</CardContent>
|
|
190
|
+
</Card>
|
|
191
|
+
);
|
|
192
|
+
}}
|
|
193
|
+
</OverdueInvoicePayment>
|
|
194
|
+
</PaymentProvider>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# ResumeSubscription
|
|
2
|
+
|
|
3
|
+
`ResumeSubscription` コンポーネントは、キャンセルされたサブスクリプションをユーザーが再開するための、分かりやすいUIを提供します。ユーザーを確認プロセスに沿って案内するダイアログをレンダリングし、サブスクリプションで必要な場合には再ステーキングのような複雑なシナリオも自動的に処理します。
|
|
4
|
+
|
|
5
|
+
このコンポーネントは、ウォレットとのやり取りを処理するために必要なコンテキストにアクセスするため、`PaymentProvider` 内で使用する必要があります。
|
|
6
|
+
|
|
7
|
+
## ワークフロー
|
|
8
|
+
|
|
9
|
+
以下の図は、ユーザーがサブスクリプションを再開する際のプロセスフローを示したもので、再ステーキングの条件分岐ロジックも含まれています。
|
|
10
|
+
|
|
11
|
+
```d2
|
|
12
|
+
shape: sequence_diagram
|
|
13
|
+
|
|
14
|
+
User: { label: "ユーザー"; shape: c4-person }
|
|
15
|
+
ResumeSubscription: { label: "ResumeSubscription コンポーネント" }
|
|
16
|
+
PaymentAPI: { label: "決済API" }
|
|
17
|
+
DIDWallet: { label: "DID Wallet" }
|
|
18
|
+
|
|
19
|
+
User -> ResumeSubscription: "1. 再開をトリガー"
|
|
20
|
+
ResumeSubscription -> PaymentAPI: "2. GET /recover-info"
|
|
21
|
+
PaymentAPI -> ResumeSubscription: "3. ステータスを返す\n(例: needStake: true)"
|
|
22
|
+
|
|
23
|
+
ResumeSubscription.t1 -> User: "4. 確認ダイアログを表示"
|
|
24
|
+
User -> ResumeSubscription.t1: "5. 確認"
|
|
25
|
+
|
|
26
|
+
alt "再ステーキングが必要" {
|
|
27
|
+
ResumeSubscription.t1 -> DIDWallet: "6a. 再ステークセッションを開く"
|
|
28
|
+
User -> DIDWallet: "7a. 承認"
|
|
29
|
+
DIDWallet -> ResumeSubscription.t1: "8a. 成功コールバック"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
alt "ステーキング不要" {
|
|
33
|
+
ResumeSubscription.t1 -> PaymentAPI: "6b. PUT /recover"
|
|
34
|
+
PaymentAPI -> ResumeSubscription.t1: "7b. 成功"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ResumeSubscription.t1 -> PaymentAPI: "9. 更新されたサブスクリプションを取得"
|
|
38
|
+
PaymentAPI -> ResumeSubscription.t1: "10. サブスクリプションを返す"
|
|
39
|
+
ResumeSubscription.t1 -> User: "11. onResumed()を呼び出し、ダイアログを閉じる"
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
## Props
|
|
45
|
+
|
|
46
|
+
| プロパティ | 型 | 必須 | 説明 |
|
|
47
|
+
| ---------------- | -------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
48
|
+
| `subscriptionId` | `string` | はい | 再開するサブスクリプションの一意の識別子。 |
|
|
49
|
+
| `onResumed` | `(subscription: Subscription) => void` | いいえ | サブスクリプションが正常に再開された後にトリガーされるコールバック関数。引数として更新されたサブスクリプションオブジェクトを受け取ります。 |
|
|
50
|
+
| `dialogProps` | `object` | いいえ | 基礎となるMaterial-UIダイアログをカスタマイズするためのProps。状態(`open`、`onClose`)と外観(`title`)を制御できます。 |
|
|
51
|
+
| `successToast` | `boolean` | いいえ | `true`の場合、正常に再開されると成功通知のトーストが表示されます。デフォルトは`true`です。 |
|
|
52
|
+
| `authToken` | `string` | いいえ | APIリクエスト用のオプションの認証トークン。これは、オリジン間またはサーバー間のインテグレーションシナリオで役立ちます。 |
|
|
53
|
+
|
|
54
|
+
## 使用例
|
|
55
|
+
|
|
56
|
+
### 基本的な使い方
|
|
57
|
+
|
|
58
|
+
これは、コンポーネントを使用する最も簡単な方法です。デフォルトで開いた状態のダイアログがレンダリングされます。
|
|
59
|
+
|
|
60
|
+
```tsx Basic ResumeSubscription Example icon=logos:react
|
|
61
|
+
import { ResumeSubscription } from '@blocklet/payment-react';
|
|
62
|
+
|
|
63
|
+
function ResumePage({ subscriptionId }) {
|
|
64
|
+
// このコンポーネントはPaymentProvider内でレンダリングする必要があります
|
|
65
|
+
return <ResumeSubscription subscriptionId={subscriptionId} />;
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 結果のハンドリング
|
|
70
|
+
|
|
71
|
+
`onResumed`コールバックを使用して、更新されたサブスクリプションデータを受け取り、アプリケーションの状態を更新します。
|
|
72
|
+
|
|
73
|
+
```tsx Handling the onResumed Callback icon=logos:react
|
|
74
|
+
import { ResumeSubscription } from '@blocklet/payment-react';
|
|
75
|
+
import { useState } from 'react';
|
|
76
|
+
|
|
77
|
+
function SubscriptionDetails({ initialSubscription }) {
|
|
78
|
+
const [subscription, setSubscription] = useState(initialSubscription);
|
|
79
|
+
|
|
80
|
+
const handleSubscriptionResumed = (updatedSubscription) => {
|
|
81
|
+
console.log('サブスクリプションが正常に再開されました:', updatedSubscription);
|
|
82
|
+
setSubscription(updatedSubscription);
|
|
83
|
+
// 確認メッセージの表示やユーザーのリダイレクトも可能です。
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div>
|
|
88
|
+
{/* `subscription` の状態に基づいてサブスクリプションの詳細を表示 */}
|
|
89
|
+
<ResumeSubscription
|
|
90
|
+
subscriptionId={subscription.id}
|
|
91
|
+
onResumed={handleSubscriptionResumed}
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ダイアログの制御
|
|
99
|
+
|
|
100
|
+
より実用的な統合のために、親コンポーネントからダイアログの可視性を制御します。これにより、ボタンのクリックなどのユーザーアクションに応じてダイアログを開くことができます。
|
|
101
|
+
|
|
102
|
+
```tsx Triggering ResumeSubscription with a Button icon=logos:react
|
|
103
|
+
import { ResumeSubscription } from '@blocklet/payment-react';
|
|
104
|
+
import { useState } from 'react';
|
|
105
|
+
import { Button } from '@mui/material';
|
|
106
|
+
|
|
107
|
+
function SubscriptionActions({ subscriptionId }) {
|
|
108
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
109
|
+
|
|
110
|
+
const handleResumed = () => {
|
|
111
|
+
setIsModalOpen(false);
|
|
112
|
+
// サブスクリプションデータを再取得してUIを更新
|
|
113
|
+
alert('サブスクリプションが再開されました!');
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<>
|
|
118
|
+
<Button variant="contained" onClick={() => setIsModalOpen(true)}>
|
|
119
|
+
サブスクリプションを再開
|
|
120
|
+
</Button>
|
|
121
|
+
|
|
122
|
+
{isModalOpen && (
|
|
123
|
+
<ResumeSubscription
|
|
124
|
+
subscriptionId={subscriptionId}
|
|
125
|
+
onResumed={handleResumed}
|
|
126
|
+
dialogProps={{
|
|
127
|
+
open: isModalOpen,
|
|
128
|
+
title: 'サブスクリプション更新の確認',
|
|
129
|
+
onClose: () => setIsModalOpen(false),
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
)}
|
|
133
|
+
</>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 完全な統合例
|
|
139
|
+
|
|
140
|
+
以下は、必須の`PaymentProvider`内に`ResumeSubscription`を統合する方法を示す完全な例です。
|
|
141
|
+
|
|
142
|
+
```tsx Complete Integration Example icon=logos:react
|
|
143
|
+
import { PaymentProvider, ResumeSubscription } from '@blocklet/payment-react';
|
|
144
|
+
import { useSessionContext } from 'path/to/your/session/context'; // あなたのアプリのセッションコンテキスト
|
|
145
|
+
import { useState } from 'react';
|
|
146
|
+
import { Button, Card, CardContent, Typography } from '@mui/material';
|
|
147
|
+
|
|
148
|
+
function SubscriptionManagementPage({ subscription }) {
|
|
149
|
+
const { session, connect } = useSessionContext();
|
|
150
|
+
const [isResumeOpen, setIsResumeOpen] = useState(false);
|
|
151
|
+
|
|
152
|
+
const handleResumed = (updatedSubscription) => {
|
|
153
|
+
console.log('サブスクリプションが更新されました:', updatedSubscription);
|
|
154
|
+
setIsResumeOpen(false);
|
|
155
|
+
// 理想的には、ここでデータを再取得してページ全体を更新します。
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<PaymentProvider session={session} connect={connect}>
|
|
160
|
+
<Card>
|
|
161
|
+
<CardContent>
|
|
162
|
+
<Typography variant="h5">サブスクリプションの管理</Typography>
|
|
163
|
+
<Typography color="text.secondary">ステータス: {subscription.status}</Typography>
|
|
164
|
+
|
|
165
|
+
{subscription.status === 'canceled' && (
|
|
166
|
+
<Button
|
|
167
|
+
variant="contained"
|
|
168
|
+
color="primary"
|
|
169
|
+
sx={{ mt: 2 }}
|
|
170
|
+
onClick={() => setIsResumeOpen(true)}>
|
|
171
|
+
サブスクリプションを再開
|
|
172
|
+
</Button>
|
|
173
|
+
)}
|
|
174
|
+
</CardContent>
|
|
175
|
+
</Card>
|
|
176
|
+
|
|
177
|
+
{isResumeOpen && (
|
|
178
|
+
<ResumeSubscription
|
|
179
|
+
subscriptionId={subscription.id}
|
|
180
|
+
onResumed={handleResumed}
|
|
181
|
+
dialogProps={{
|
|
182
|
+
open: isResumeOpen,
|
|
183
|
+
onClose: () => setIsResumeOpen(false),
|
|
184
|
+
}}
|
|
185
|
+
/>
|
|
186
|
+
)}
|
|
187
|
+
</PaymentProvider>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
```
|