@seaverse/payment-sdk 0.9.0 → 0.9.2
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/README.md +610 -843
- package/dist/index.browser.js +140 -67
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +140 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +137 -86
- package/dist/index.js +140 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,439 +1,309 @@
|
|
|
1
1
|
# @seaverse/payment-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Version**: 0.9.2 | **Language**: English
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A comprehensive payment solution for SeaVerse platform, providing credit management, payment checkout, subscription management, and order tracking.
|
|
6
6
|
|
|
7
|
-
## 📦
|
|
7
|
+
## 📦 Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install @seaverse/payment-sdk
|
|
11
|
-
#
|
|
11
|
+
# or
|
|
12
12
|
pnpm add @seaverse/payment-sdk
|
|
13
|
+
# or
|
|
14
|
+
yarn add @seaverse/payment-sdk
|
|
13
15
|
```
|
|
14
16
|
|
|
15
|
-
## 🚀
|
|
17
|
+
## 🚀 Quick Start
|
|
16
18
|
|
|
17
|
-
### 1.
|
|
19
|
+
### 1. Credit Package Modal (Recommended)
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
The simplest integration - complete payment flow in 3 lines of code:
|
|
20
22
|
|
|
21
23
|
```typescript
|
|
22
24
|
import { CreditPackageModal } from '@seaverse/payment-sdk';
|
|
23
25
|
|
|
24
|
-
//
|
|
26
|
+
// Create modal
|
|
25
27
|
const modal = new CreditPackageModal({
|
|
28
|
+
language: 'en', // 'en' | 'zh' | 'zh-TW' | 'ja' | 'ko' | 'es' | 'fr' | 'de' | 'pt' | 'ru' | 'ar' | 'hi' | 'id'
|
|
29
|
+
|
|
26
30
|
sdkConfig: {
|
|
27
|
-
environment: 'development', //
|
|
28
|
-
|
|
29
|
-
accountToken: 'user-token', // 用户认证令牌(可选)
|
|
31
|
+
environment: 'development', // 'development' | 'production'
|
|
32
|
+
accountToken: 'user-token', // User authentication token
|
|
30
33
|
},
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
|
|
35
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
36
|
+
console.log('Payment successful!', { orderId, transactionId, credits: pkg.total_credits });
|
|
33
37
|
},
|
|
34
38
|
});
|
|
35
39
|
|
|
36
|
-
//
|
|
40
|
+
// Open modal
|
|
37
41
|
modal.open();
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
- ✅
|
|
42
|
-
- ✅
|
|
43
|
-
- ✅
|
|
44
|
-
- ✅
|
|
45
|
-
- ✅
|
|
44
|
+
**What you get**:
|
|
45
|
+
- ✅ Pre-configured credit packages (fetched from API)
|
|
46
|
+
- ✅ Automatic SDK initialization
|
|
47
|
+
- ✅ Auto order creation
|
|
48
|
+
- ✅ Animated success modal
|
|
49
|
+
- ✅ Auto credit balance refresh
|
|
46
50
|
|
|
47
|
-
### 2.
|
|
51
|
+
### 2. Generic Package Modal (Custom Packages)
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
For promotions, special offers, and custom packages:
|
|
50
54
|
|
|
51
55
|
```typescript
|
|
52
56
|
import { GenericPackageModal, type GenericPackage } from '@seaverse/payment-sdk';
|
|
53
57
|
|
|
54
|
-
//
|
|
58
|
+
// Define custom packages
|
|
55
59
|
const packages: GenericPackage[] = [
|
|
56
60
|
{
|
|
57
|
-
id: '
|
|
61
|
+
id: 'pkg_ice_breaker',
|
|
58
62
|
name: 'Ice Breaker Pack',
|
|
59
63
|
price: '0.49',
|
|
60
64
|
currency: 'USD',
|
|
61
65
|
credits: '120',
|
|
66
|
+
base_credits: '100',
|
|
67
|
+
bonus_credits: '20',
|
|
62
68
|
bonus_percentage: 20,
|
|
63
|
-
day_limit: 1, // 每日限购1次
|
|
64
69
|
package_type: 'iceBreaker',
|
|
65
70
|
},
|
|
66
|
-
{
|
|
67
|
-
id: 'pkg_pro',
|
|
68
|
-
name: 'Emergency Pack',
|
|
69
|
-
price: '0.99',
|
|
70
|
-
currency: 'USD',
|
|
71
|
-
credits: '240',
|
|
72
|
-
day_limit: 3, // 每日限购3次
|
|
73
|
-
package_type: 'emergency',
|
|
74
|
-
},
|
|
75
71
|
];
|
|
76
72
|
|
|
77
|
-
//
|
|
73
|
+
// Create modal
|
|
78
74
|
const modal = new GenericPackageModal({
|
|
79
75
|
packages: packages,
|
|
76
|
+
language: 'en',
|
|
77
|
+
|
|
80
78
|
sdkConfig: {
|
|
81
79
|
environment: 'development',
|
|
82
|
-
countryCode: 'SG',
|
|
83
80
|
accountToken: 'user-token',
|
|
84
81
|
},
|
|
85
|
-
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
86
|
-
console.log(`${pkg.name} 购买成功!`, orderId);
|
|
87
|
-
},
|
|
88
|
-
onPaymentFailed: (error, pkg) => {
|
|
89
|
-
if (error.message.includes('limit')) {
|
|
90
|
-
alert(`${pkg.name} 已达购买限额`);
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
modal.open();
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## 🏗️ 架构设计
|
|
99
|
-
|
|
100
|
-
### 代码重构 (v0.8.1)
|
|
101
|
-
|
|
102
|
-
为了提高代码可维护性和消除重复逻辑,SDK 进行了架构重构:
|
|
103
|
-
|
|
104
|
-
**核心改进**:
|
|
105
|
-
- ✅ **抽象基类设计** - 创建 `BasePackageModal<TPackage, TOptions>` 抽象基类
|
|
106
|
-
- ✅ **消除重复代码** - 减少 ~400 行重复代码(SDK 初始化、支付流程、事件处理)
|
|
107
|
-
- ✅ **类型安全** - 使用 TypeScript 泛型确保类型安全
|
|
108
|
-
- ✅ **向后兼容** - 公开 API 完全不变,现有代码无需修改
|
|
109
|
-
|
|
110
|
-
**类继承结构**:
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
BasePackageModal<TPackage, TOptions> (抽象基类)
|
|
114
|
-
├── CreditPackageModal (积分套餐弹框)
|
|
115
|
-
└── GenericPackageModal (通用套餐弹框)
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**BasePackageModal 提供的共享功能**:
|
|
119
|
-
- SDK 初始化和状态管理
|
|
120
|
-
- 支付流程处理(订单创建、支付弹框)
|
|
121
|
-
- 事件监听和按钮处理
|
|
122
|
-
- 工具方法(formatNumber、cleanup 等)
|
|
123
|
-
|
|
124
|
-
**子类只需实现**:
|
|
125
|
-
- `createModal()` - 创建和配置 PaymentModal
|
|
126
|
-
- `renderContent()` - 渲染弹框内容(UI 特定逻辑)
|
|
127
|
-
- `getPackages()` - 获取套餐列表
|
|
128
|
-
- `getPackageDisplayName()` - 获取套餐显示名称
|
|
129
|
-
- `getLoadingButtonHTML()` - 获取加载按钮 HTML
|
|
130
|
-
|
|
131
|
-
这种设计确保:
|
|
132
|
-
- **单一职责** - 基类负责逻辑,子类负责 UI
|
|
133
|
-
- **DRY 原则** - 共享逻辑只需维护一处
|
|
134
|
-
- **易于扩展** - 添加新套餐类型只需继承基类
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## 📖 核心功能模块
|
|
139
|
-
|
|
140
|
-
### ⭐️ 推荐功能(新用户优先使用)
|
|
141
|
-
|
|
142
|
-
| 功能 | 组件 | 使用场景 | 文档 |
|
|
143
|
-
| ------------------ | ---------------------- | ---------------------- | ----------------------------------------------- |
|
|
144
|
-
| **积分套餐购买** | `CreditPackageModal` | 标准积分购买(最简单) | [👉 查看](#creditpackagemodal---标准积分购买) |
|
|
145
|
-
| **自定义套餐购买** | `GenericPackageModal` | 促销活动、特殊套餐 | [👉 查看](#genericpackagemodal---自定义套餐购买) |
|
|
146
|
-
| **购买成功弹窗** | `PurchaseSuccessModal` | 自动集成,无需手动调用 | [👉 查看](#purchasesuccessmodal---购买成功弹窗) |
|
|
147
|
-
|
|
148
|
-
### 🔧 高级功能(进阶用户)
|
|
149
|
-
|
|
150
|
-
| 功能 | API | 使用场景 |
|
|
151
|
-
| --------------------- | ---------------------------------------------- | -------------------------- |
|
|
152
|
-
| **积分查询** | `PaymentClient` | 查询用户积分余额、交易记录 |
|
|
153
|
-
| **订阅管理** | `getCurrentSubscription`, `changeSubscription` | 订阅状态查询、升级/降级 |
|
|
154
|
-
| **订单管理** | `checkOrderStatus`, `pollOrderStatus` | 订单状态查询、轮询 |
|
|
155
|
-
| **SeaartPayment SDK** | `SeaartPaymentSDK` | 完全自定义支付流程 |
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## 📚 详细使用文档
|
|
160
|
-
|
|
161
|
-
### CreditPackageModal - 标准积分购买
|
|
162
|
-
|
|
163
|
-
**适用场景**:
|
|
164
|
-
- ✅ 标准积分套餐购买(120/240/520/1200 积分)
|
|
165
|
-
- ✅ 展示创作力量类型(文生图、图生图等)
|
|
166
|
-
- ✅ 最简单的集成方式
|
|
167
|
-
|
|
168
|
-
#### 基础用法
|
|
169
82
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const modal = new CreditPackageModal({
|
|
174
|
-
// 语言设置(可选,默认 'en')
|
|
175
|
-
language: 'zh-CN', // 'en' | 'zh-CN'
|
|
176
|
-
|
|
177
|
-
// SDK 配置(必填)
|
|
178
|
-
sdkConfig: {
|
|
179
|
-
environment: 'development', // 'development' | 'production'
|
|
180
|
-
countryCode: 'SG', // ISO 3166-1 国家代码
|
|
181
|
-
accountToken: 'user-token', // 用户认证令牌(可选)
|
|
182
|
-
businessType: 1, // 1=一次性购买, 2=订阅(可选,默认1)
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
// 回调函数
|
|
186
|
-
onPaymentSuccess: (orderId: string, transactionId: string) => {
|
|
187
|
-
console.log('支付成功!', { orderId, transactionId });
|
|
188
|
-
// 刷新用户积分、更新 UI 等
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
onPaymentFailed: (error: Error) => {
|
|
192
|
-
console.error('支付失败:', error.message);
|
|
193
|
-
// 显示错误提示
|
|
83
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
84
|
+
console.log(`${pkg.name} purchased!`, orderId);
|
|
194
85
|
},
|
|
195
86
|
|
|
196
87
|
onClose: () => {
|
|
197
|
-
console.log('
|
|
88
|
+
console.log('Modal closed');
|
|
198
89
|
},
|
|
199
90
|
});
|
|
200
91
|
|
|
201
|
-
// 打开弹窗
|
|
202
92
|
modal.open();
|
|
203
|
-
|
|
204
|
-
// 关闭弹窗(可选)
|
|
205
|
-
modal.close();
|
|
206
|
-
|
|
207
|
-
// 检查弹窗状态
|
|
208
|
-
console.log('弹窗是否打开:', modal.isOpen());
|
|
209
93
|
```
|
|
210
94
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
SDK 内置以下积分套餐:
|
|
214
|
-
|
|
215
|
-
| 套餐 | 积分 | 价格 | 说明 |
|
|
216
|
-
| ------- | ---- | ----- | -------- |
|
|
217
|
-
| Starter | 120 | $0.49 | 入门套餐 |
|
|
218
|
-
| Value | 240 | $0.99 | 超值套餐 |
|
|
219
|
-
| Pro | 520 | $1.99 | 专业套餐 |
|
|
220
|
-
| Ultra | 1200 | $4.99 | 旗舰套餐 |
|
|
221
|
-
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
### PaymentCheckoutModal - 完整收银台流程
|
|
225
|
-
|
|
226
|
-
**适用场景**:
|
|
227
|
-
- ✅ 需要完整的支付收银台体验(支付方式选择 + 订单信息展示)
|
|
228
|
-
- ✅ 自动创建订单并完成支付
|
|
229
|
-
- ✅ 支持三种支付方式:Link Payment、Dropin Payment、BindCard Payment
|
|
230
|
-
- ✅ 适合需要更多控制和自定义的场景
|
|
95
|
+
### 3. Payment Checkout Modal (Full Checkout Experience)
|
|
231
96
|
|
|
232
|
-
|
|
97
|
+
Complete checkout flow with payment method selection:
|
|
233
98
|
|
|
234
99
|
```typescript
|
|
235
|
-
import { PaymentCheckoutModal,
|
|
236
|
-
|
|
237
|
-
// 定义产品信息
|
|
238
|
-
const product: Product = {
|
|
239
|
-
id: 'pkg_credit_100',
|
|
240
|
-
name: '100 Credits Package',
|
|
241
|
-
price: 9.99,
|
|
242
|
-
currency: 'USD',
|
|
243
|
-
type: 'credit_package', // 'credit_package' | 'subscription' | 'change_subscription'
|
|
244
|
-
};
|
|
100
|
+
import { PaymentCheckoutModal, PRODUCT_TYPE } from '@seaverse/payment-sdk';
|
|
245
101
|
|
|
246
|
-
// 创建收银台 modal
|
|
247
102
|
const modal = new PaymentCheckoutModal({
|
|
248
|
-
|
|
249
|
-
|
|
103
|
+
product: {
|
|
104
|
+
id: 'pkg_credit_100',
|
|
105
|
+
name: '100 Credits Package',
|
|
106
|
+
price: 9.99,
|
|
107
|
+
currency: 'USD',
|
|
108
|
+
type: PRODUCT_TYPE.CREDITPACK,
|
|
109
|
+
},
|
|
250
110
|
|
|
251
|
-
// 自动创建订单配置
|
|
252
111
|
autoCreateOrder: {
|
|
253
|
-
productId:
|
|
254
|
-
purchaseType: 1,
|
|
255
|
-
apiHost: 'https://
|
|
112
|
+
productId: 'pkg_credit_100',
|
|
113
|
+
purchaseType: 1, // 1 = one-time purchase, 2 = subscription
|
|
114
|
+
apiHost: 'https://payment.seaverse.com',
|
|
256
115
|
accountToken: 'user-token',
|
|
257
116
|
clientId: 'your-client-id',
|
|
258
|
-
|
|
117
|
+
language_code: 'en',
|
|
259
118
|
},
|
|
260
119
|
|
|
261
|
-
|
|
262
|
-
accountName: 'John Doe', // 显示在订单信息中
|
|
263
|
-
language: 'en', // 'en' | 'zh-CN'
|
|
120
|
+
language: 'en',
|
|
264
121
|
|
|
265
|
-
// 回调函数
|
|
266
122
|
onPaymentSuccess: (payload) => {
|
|
267
|
-
console.log('
|
|
268
|
-
// payload 包含: orderId, transactionId, 等信息
|
|
123
|
+
console.log('Payment completed!', payload);
|
|
269
124
|
},
|
|
125
|
+
});
|
|
270
126
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
},
|
|
127
|
+
modal.open();
|
|
128
|
+
```
|
|
274
129
|
|
|
275
|
-
|
|
276
|
-
console.log('选择支付方式:', method.name);
|
|
277
|
-
},
|
|
130
|
+
---
|
|
278
131
|
|
|
279
|
-
|
|
280
|
-
console.log('Link 支付开始:', methodName);
|
|
281
|
-
// 可以在这里显示 "请在新窗口完成支付" 提示
|
|
282
|
-
},
|
|
132
|
+
## 🏗️ Architecture
|
|
283
133
|
|
|
284
|
-
|
|
285
|
-
console.log('加载状态:', loading);
|
|
286
|
-
},
|
|
287
|
-
});
|
|
134
|
+
### Version 0.9.2 - Enhancement
|
|
288
135
|
|
|
289
|
-
|
|
290
|
-
modal.open();
|
|
291
|
-
```
|
|
136
|
+
**Improvements in this release**:
|
|
292
137
|
|
|
293
|
-
|
|
138
|
+
1. **Enhanced GenericPackageModal** 🎯
|
|
139
|
+
- Added `onClose` callback support for custom package modals
|
|
140
|
+
- Callback is now triggered when modal is closed via the close button
|
|
141
|
+
- Enables better integration with parent component lifecycle
|
|
142
|
+
- Example usage:
|
|
143
|
+
```typescript
|
|
144
|
+
const modal = new GenericPackageModal({
|
|
145
|
+
packages: [...],
|
|
146
|
+
onClose: () => {
|
|
147
|
+
console.log('Modal closed by user');
|
|
148
|
+
// Perform cleanup or refresh actions
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
```
|
|
294
152
|
|
|
295
|
-
|
|
153
|
+
### Version 0.9.0 - Critical Bug Fixes
|
|
296
154
|
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
const modal = new PaymentCheckoutModal({
|
|
300
|
-
product: { id: 'pkg_1', name: 'Product', price: 9.99, currency: 'USD', type: 'credit_package' },
|
|
301
|
-
autoCreateOrder: {
|
|
302
|
-
productId: 'pkg_1',
|
|
303
|
-
purchaseType: 1,
|
|
304
|
-
apiHost: 'https://api.example.com',
|
|
305
|
-
accountToken: 'token',
|
|
306
|
-
clientId: 'client-id',
|
|
307
|
-
countryCode: 'SG',
|
|
308
|
-
},
|
|
309
|
-
onPaymentSuccess: (payload) => { /* ... */ },
|
|
310
|
-
});
|
|
311
|
-
```
|
|
155
|
+
**Major fixes in this release**:
|
|
312
156
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
157
|
+
1. **Fixed SDK Initialization Error** 🔧
|
|
158
|
+
- Resolved "Payment method 'dropin' not found" error
|
|
159
|
+
- Issue: BasePackageModal tried to find Dropin payment when only Link payments available
|
|
160
|
+
- Solution: Override `initializeSDK()` in CreditPackageModal and GenericPackageModal to skip legacy initialization
|
|
161
|
+
- Now PaymentCheckoutModal handles all SDK initialization independently
|
|
316
162
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
163
|
+
2. **Fixed Link Payment Auto-Execution** 🔧
|
|
164
|
+
- Prevented immediate redirect before users see checkout modal
|
|
165
|
+
- Issue: `autoSelectDefaultPaymentMethod()` auto-executed Link payment, causing instant redirect
|
|
166
|
+
- Solution: Only auto-select Dropin payments, wait for manual selection when only Link available
|
|
167
|
+
- Improved user experience with proper checkout flow
|
|
322
168
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
```
|
|
169
|
+
3. **UI/UX Enhancements** 🎨
|
|
170
|
+
- Increased payment method card spacing from 8px to 14px
|
|
171
|
+
- Better visual hierarchy and click targets
|
|
172
|
+
- Consistent spacing in both skeleton and main UI
|
|
173
|
+
|
|
174
|
+
### Class Hierarchy
|
|
330
175
|
|
|
331
|
-
**模式 3: transactionId(延迟初始化)**
|
|
332
|
-
```typescript
|
|
333
|
-
const modal = new PaymentCheckoutModal({
|
|
334
|
-
product: { /* ... */ },
|
|
335
|
-
transactionId: 'txn_123',
|
|
336
|
-
paymentMethods: [...], // 需要手动提供支付方式列表
|
|
337
|
-
onPaymentSuccess: (payload) => { /* ... */ },
|
|
338
|
-
});
|
|
339
176
|
```
|
|
177
|
+
BasePackageModal<TPackage, TOptions> (Abstract base class)
|
|
178
|
+
├── CreditPackageModal (Standard credit packages)
|
|
179
|
+
└── GenericPackageModal (Custom promotional packages)
|
|
340
180
|
|
|
341
|
-
|
|
181
|
+
PaymentCheckoutModal (Standalone checkout system)
|
|
182
|
+
├── PaymentStrategyFactory
|
|
183
|
+
│ ├── LinkPaymentStrategy (Redirect payments)
|
|
184
|
+
│ ├── DropinPaymentStrategy (Embedded forms)
|
|
185
|
+
│ └── BasePaymentStrategy (Strategy base)
|
|
186
|
+
└── Services
|
|
187
|
+
├── PaymentOrderService (Order management)
|
|
188
|
+
├── PaymentLoadingManager (Loading states)
|
|
189
|
+
└── PaymentStateManager (State management)
|
|
190
|
+
```
|
|
342
191
|
|
|
343
|
-
|
|
344
|
-
|------|------|------|------|
|
|
345
|
-
| `product` | `Product` | 否 | 产品信息(id, name, price, currency, type) |
|
|
346
|
-
| `autoCreateOrder` | `AutoCreateOrderConfig` | 三选一 | 自动创建订单配置(推荐) |
|
|
347
|
-
| `payment` | `OrderPayment` | 三选一 | 提前创建的 OrderPayment 实例 |
|
|
348
|
-
| `transactionId` | `string` | 三选一 | 订单 transaction_id(延迟初始化) |
|
|
349
|
-
| `paymentMethods` | `PaymentMethod[]` | 否 | 支付方式列表(autoCreateOrder 模式会自动获取) |
|
|
350
|
-
| `accountName` | `string` | 否 | 用户账号名称(显示在订单信息中) |
|
|
351
|
-
| `language` | `'en' \| 'zh-CN'` | 否 | 语言设置(默认 'en') |
|
|
352
|
-
| `onPaymentSuccess` | `(payload) => void` | 否 | 支付成功回调 |
|
|
353
|
-
| `onPaymentFailed` | `(error) => void` | 否 | 支付失败回调 |
|
|
354
|
-
| `onPaymentMethodSelect` | `(method) => void` | 否 | 选择支付方式回调 |
|
|
355
|
-
| `onLinkPaymentStart` | `(methodName) => void` | 否 | Link 支付开始回调 |
|
|
356
|
-
| `onLoading` | `(loading) => void` | 否 | 加载状态回调 |
|
|
192
|
+
### Design Patterns Used
|
|
357
193
|
|
|
358
|
-
|
|
194
|
+
- **Singleton Pattern**: SeaartPaymentSDK.getInstance()
|
|
195
|
+
- **Strategy Pattern**: Payment strategy selection (Link vs Dropin)
|
|
196
|
+
- **Template Method Pattern**: BasePackageModal with abstract methods
|
|
197
|
+
- **Factory Pattern**: PaymentStrategyFactory.createStrategy()
|
|
198
|
+
- **Service Locator Pattern**: Service injection in PaymentCheckoutModal
|
|
359
199
|
|
|
360
|
-
|
|
361
|
-
|------|------|------|
|
|
362
|
-
| 信用包 | `'credit_package'` | 一次性购买积分包 |
|
|
363
|
-
| 订阅 | `'subscription'` | 新订阅购买 |
|
|
364
|
-
| 变更订阅 | `'change_subscription'` | 订阅升级/降级 |
|
|
200
|
+
---
|
|
365
201
|
|
|
366
|
-
|
|
202
|
+
## 📚 Core Features
|
|
367
203
|
|
|
368
|
-
|
|
204
|
+
### 🌟 Recommended Features (For New Users)
|
|
369
205
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
206
|
+
| Feature | Component | Use Case | Documentation |
|
|
207
|
+
|---------|-----------|----------|---------------|
|
|
208
|
+
| **Credit Packages** | `CreditPackageModal` | Standard credit purchases | [👉 View](#creditpackagemodal---standard-credit-purchases) |
|
|
209
|
+
| **Custom Packages** | `GenericPackageModal` | Promotions & special offers | [👉 View](#genericpackagemodal---custom-packages) |
|
|
210
|
+
| **Checkout System** | `PaymentCheckoutModal` | Full checkout experience | [👉 View](#paymentcheckoutmodal---checkout-system) |
|
|
211
|
+
| **Success Modal** | `PurchaseSuccessModal` | Auto-integrated, no manual call needed | [👉 View](#purchasesuccessmodal---purchase-success) |
|
|
373
212
|
|
|
374
|
-
|
|
213
|
+
### 🔧 Advanced Features
|
|
375
214
|
|
|
376
|
-
|
|
215
|
+
| Feature | API | Use Case |
|
|
216
|
+
|---------|-----|----------|
|
|
217
|
+
| **Credit Query** | `getCreditDetail` | Check user credit balance |
|
|
218
|
+
| **Subscription Management** | `getCurrentSubscription`, `changeSubscription` | Manage subscriptions |
|
|
219
|
+
| **Order Management** | `checkOrderStatus`, `pollOrderStatus` | Track order status |
|
|
220
|
+
| **Custom Payment Flows** | `SeaartPaymentSDK` | Full control over payment process |
|
|
377
221
|
|
|
378
222
|
---
|
|
379
223
|
|
|
380
|
-
|
|
224
|
+
## 📖 Detailed Documentation
|
|
381
225
|
|
|
382
|
-
|
|
226
|
+
### CreditPackageModal - Standard Credit Purchases
|
|
383
227
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
walletApiUrl: 'https://wallet.sg.seaverse.dev',
|
|
391
|
-
}
|
|
392
|
-
```
|
|
228
|
+
**Use Cases**:
|
|
229
|
+
- ✅ Standard credit package purchases
|
|
230
|
+
- ✅ Dynamic packages from API
|
|
231
|
+
- ✅ Simplest integration method
|
|
232
|
+
|
|
233
|
+
#### Basic Usage
|
|
393
234
|
|
|
394
|
-
**生产环境 (production)**:
|
|
395
235
|
```typescript
|
|
396
|
-
{
|
|
397
|
-
scriptUrl: 'https://payment-static.seaverse.com/sdk/seaart-payment-component.js',
|
|
398
|
-
clientId: 'prod_client_id',
|
|
399
|
-
orderApiUrl: 'https://payment.seaverse.com',
|
|
400
|
-
walletApiUrl: 'https://wallet.seaverse.com',
|
|
401
|
-
}
|
|
402
|
-
```
|
|
236
|
+
import { CreditPackageModal } from '@seaverse/payment-sdk';
|
|
403
237
|
|
|
404
|
-
|
|
238
|
+
const modal = new CreditPackageModal({
|
|
239
|
+
// Language (optional, defaults to 'en')
|
|
240
|
+
language: 'en', // 'en' | 'zh' | 'zh-TW' | 'ja' | 'ko' | etc.
|
|
405
241
|
|
|
406
|
-
|
|
242
|
+
// Modal title (optional)
|
|
243
|
+
title: 'Purchase Credits',
|
|
244
|
+
title_cn: '购买积分', // Chinese title
|
|
407
245
|
|
|
408
|
-
|
|
409
|
-
const modal = new CreditPackageModal({
|
|
246
|
+
// SDK Configuration (required)
|
|
410
247
|
sdkConfig: {
|
|
411
248
|
environment: 'production',
|
|
412
|
-
|
|
249
|
+
accountToken: 'user-token',
|
|
413
250
|
|
|
414
|
-
//
|
|
415
|
-
|
|
251
|
+
// Optional overrides
|
|
252
|
+
businessType: 1, // 1 = one-time, 2 = subscription
|
|
416
253
|
clientId: 'custom-client-id',
|
|
417
254
|
orderApiUrl: 'https://custom-api.com',
|
|
418
255
|
},
|
|
256
|
+
|
|
257
|
+
// Callbacks
|
|
258
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
259
|
+
console.log('Payment successful!', {
|
|
260
|
+
orderId,
|
|
261
|
+
transactionId,
|
|
262
|
+
credits: pkg.total_credits
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
onPaymentFailed: (error, pkg) => {
|
|
267
|
+
console.error('Payment failed:', error.message);
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
onClose: () => {
|
|
271
|
+
console.log('Modal closed');
|
|
272
|
+
},
|
|
419
273
|
});
|
|
274
|
+
|
|
275
|
+
// Open modal
|
|
276
|
+
modal.open();
|
|
277
|
+
|
|
278
|
+
// Close modal (optional)
|
|
279
|
+
modal.close();
|
|
280
|
+
|
|
281
|
+
// Check status
|
|
282
|
+
console.log('Is open:', modal.isOpen());
|
|
420
283
|
```
|
|
421
284
|
|
|
285
|
+
#### Dynamic Package Fetching
|
|
286
|
+
|
|
287
|
+
Packages are automatically fetched from the API based on:
|
|
288
|
+
- Environment (`development` or `production`)
|
|
289
|
+
- Account token (for user-specific packages)
|
|
290
|
+
- Business type (one-time vs subscription)
|
|
291
|
+
|
|
422
292
|
---
|
|
423
293
|
|
|
424
|
-
### GenericPackageModal -
|
|
294
|
+
### GenericPackageModal - Custom Packages
|
|
425
295
|
|
|
426
|
-
|
|
427
|
-
- ✅
|
|
428
|
-
- ✅
|
|
429
|
-
- ✅
|
|
296
|
+
**Use Cases**:
|
|
297
|
+
- ✅ Special promotions (ice breaker packs, emergency packs)
|
|
298
|
+
- ✅ Limited-time offers
|
|
299
|
+
- ✅ First-purchase bonuses
|
|
300
|
+
- ✅ Custom package configurations
|
|
430
301
|
|
|
431
|
-
####
|
|
302
|
+
#### Basic Usage
|
|
432
303
|
|
|
433
304
|
```typescript
|
|
434
305
|
import { GenericPackageModal, type GenericPackage } from '@seaverse/payment-sdk';
|
|
435
306
|
|
|
436
|
-
// 定义套餐数据
|
|
437
307
|
const packages: GenericPackage[] = [
|
|
438
308
|
{
|
|
439
309
|
id: 'pkg_ice_breaker',
|
|
@@ -443,523 +313,394 @@ const packages: GenericPackage[] = [
|
|
|
443
313
|
credits: '120',
|
|
444
314
|
base_credits: '100',
|
|
445
315
|
bonus_credits: '20',
|
|
446
|
-
bonus_percentage: 20,
|
|
447
|
-
|
|
448
|
-
|
|
316
|
+
bonus_percentage: 20, // Show "+20%" badge
|
|
317
|
+
package_type: 'iceBreaker', // Display "One-time Only"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
id: 'pkg_emergency',
|
|
321
|
+
name: 'Emergency Pack',
|
|
322
|
+
price: '0.99',
|
|
323
|
+
currency: 'USD',
|
|
324
|
+
credits: '240',
|
|
325
|
+
package_type: 'emergency',
|
|
449
326
|
},
|
|
450
327
|
];
|
|
451
328
|
|
|
452
|
-
// 创建弹窗
|
|
453
329
|
const modal = new GenericPackageModal({
|
|
454
|
-
language: 'zh-CN',
|
|
455
330
|
packages: packages,
|
|
331
|
+
language: 'en',
|
|
456
332
|
|
|
457
333
|
sdkConfig: {
|
|
458
334
|
environment: 'development',
|
|
459
|
-
countryCode: 'SG',
|
|
460
335
|
accountToken: 'user-token',
|
|
461
336
|
},
|
|
462
337
|
|
|
463
338
|
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
464
|
-
console.log(`${pkg.name}
|
|
465
|
-
},
|
|
466
|
-
|
|
467
|
-
onPaymentFailed: (error, pkg) => {
|
|
468
|
-
console.error(`${pkg.name} 购买失败:`, error.message);
|
|
339
|
+
console.log(`${pkg.name} purchased successfully!`);
|
|
469
340
|
},
|
|
470
341
|
});
|
|
471
342
|
|
|
472
343
|
modal.open();
|
|
473
344
|
```
|
|
474
345
|
|
|
475
|
-
#### GenericPackage
|
|
346
|
+
#### GenericPackage Interface
|
|
476
347
|
|
|
477
348
|
```typescript
|
|
478
349
|
interface GenericPackage {
|
|
479
|
-
//
|
|
480
|
-
id: string; //
|
|
481
|
-
name: string; //
|
|
482
|
-
price: string; //
|
|
483
|
-
currency: string; //
|
|
484
|
-
credits: string; //
|
|
485
|
-
|
|
486
|
-
//
|
|
487
|
-
base_credits?: string; //
|
|
488
|
-
bonus_credits?: string; //
|
|
489
|
-
bonus_percentage?: number; //
|
|
490
|
-
|
|
491
|
-
//
|
|
492
|
-
day_limit?: number; // 每日限购次数(0 = 无限制)
|
|
493
|
-
lifetime_limit?: number; // 终身限购次数(0 = 无限制)
|
|
494
|
-
|
|
495
|
-
// 分类标识(可选)
|
|
350
|
+
// Required fields
|
|
351
|
+
id: string; // Unique package identifier
|
|
352
|
+
name: string; // Package name
|
|
353
|
+
price: string; // Price (string to support decimals)
|
|
354
|
+
currency: string; // Currency code (e.g., 'USD')
|
|
355
|
+
credits: string; // Total credits
|
|
356
|
+
|
|
357
|
+
// Optional bonus fields
|
|
358
|
+
base_credits?: string; // Base credits
|
|
359
|
+
bonus_credits?: string; // Bonus credits
|
|
360
|
+
bonus_percentage?: number; // Bonus percentage (e.g., 20 for +20%)
|
|
361
|
+
|
|
362
|
+
// Optional classification
|
|
496
363
|
package_type?: 'iceBreaker' | 'emergency' | 'firstCharge' | 'custom';
|
|
497
364
|
}
|
|
498
365
|
```
|
|
499
366
|
|
|
500
|
-
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
### PaymentCheckoutModal - Checkout System
|
|
501
370
|
|
|
502
|
-
|
|
371
|
+
**Use Cases**:
|
|
372
|
+
- ✅ Full checkout experience with payment method selection
|
|
373
|
+
- ✅ Support for multiple payment types (Link, Dropin, BindCard)
|
|
374
|
+
- ✅ Auto order creation and payment
|
|
375
|
+
- ✅ Advanced customization and control
|
|
376
|
+
|
|
377
|
+
#### Basic Usage
|
|
503
378
|
|
|
504
379
|
```typescript
|
|
505
|
-
import {
|
|
506
|
-
EXAMPLE_ICE_BREAKER, // 破冰包
|
|
507
|
-
EXAMPLE_EMERGENCY, // 告急包
|
|
508
|
-
EXAMPLE_FIRST_CHARGE, // 首充包
|
|
509
|
-
EXAMPLE_PACKAGES, // 所有示例套餐数组
|
|
510
|
-
} from '@seaverse/payment-sdk';
|
|
380
|
+
import { PaymentCheckoutModal, PRODUCT_TYPE } from '@seaverse/payment-sdk';
|
|
511
381
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
382
|
+
const modal = new PaymentCheckoutModal({
|
|
383
|
+
// Product information
|
|
384
|
+
product: {
|
|
385
|
+
id: 'pkg_credit_100',
|
|
386
|
+
name: '100 Credits Package',
|
|
387
|
+
price: 9.99,
|
|
388
|
+
currency: 'USD',
|
|
389
|
+
type: PRODUCT_TYPE.CREDITPACK, // CREDITPACK | SUBSCRIPTION | CHANGE_SUBSCRIPTION
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
// Auto create order (recommended)
|
|
393
|
+
autoCreateOrder: {
|
|
394
|
+
productId: 'pkg_credit_100',
|
|
395
|
+
purchaseType: 1, // 1 = one-time, 2 = subscription
|
|
396
|
+
apiHost: 'https://payment.seaverse.com',
|
|
397
|
+
accountToken: 'user-token',
|
|
398
|
+
clientId: 'your-client-id',
|
|
399
|
+
language_code: 'en',
|
|
400
|
+
},
|
|
401
|
+
|
|
402
|
+
// Optional configuration
|
|
403
|
+
accountName: 'John Doe', // Display in order summary
|
|
404
|
+
language: 'en',
|
|
405
|
+
|
|
406
|
+
// Callbacks
|
|
407
|
+
onPaymentSuccess: (payload) => {
|
|
408
|
+
console.log('Payment successful!', payload);
|
|
409
|
+
},
|
|
410
|
+
|
|
411
|
+
onPaymentFailed: (error) => {
|
|
412
|
+
console.error('Payment failed:', error.message);
|
|
413
|
+
},
|
|
414
|
+
|
|
415
|
+
onPaymentMethodSelect: (method) => {
|
|
416
|
+
console.log('Payment method selected:', method.payment_method_name);
|
|
417
|
+
},
|
|
418
|
+
|
|
419
|
+
onLinkPaymentStart: (methodName) => {
|
|
420
|
+
console.log('Link payment started:', methodName);
|
|
421
|
+
// Show "Please complete payment in new window" message
|
|
422
|
+
},
|
|
423
|
+
|
|
424
|
+
onLoading: (loading) => {
|
|
425
|
+
console.log('Loading state:', loading);
|
|
426
|
+
},
|
|
516
427
|
});
|
|
428
|
+
|
|
429
|
+
modal.open();
|
|
517
430
|
```
|
|
518
431
|
|
|
519
|
-
|
|
432
|
+
#### Payment Methods Supported
|
|
433
|
+
|
|
434
|
+
1. **Link Payment** (payment_type = 1)
|
|
435
|
+
- Redirect to external payment page
|
|
436
|
+
- Auto order status polling
|
|
437
|
+
- Verification modal after redirect
|
|
438
|
+
|
|
439
|
+
2. **Dropin Payment** (payment_type = 2)
|
|
440
|
+
- Embedded payment form
|
|
441
|
+
- Support credit cards, PayPal, etc.
|
|
442
|
+
- Inline validation and submission
|
|
443
|
+
|
|
444
|
+
3. **BindCard Payment** (payment_type = 2 with saved cards)
|
|
445
|
+
- Display saved payment methods
|
|
446
|
+
- Quick payment with saved cards
|
|
447
|
+
- Add new card option
|
|
448
|
+
|
|
449
|
+
#### Auto-Selection Strategy (Fixed in v0.9.0)
|
|
520
450
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
451
|
+
The checkout modal intelligently handles payment method selection:
|
|
452
|
+
|
|
453
|
+
- ✅ **When Dropin available**: Auto-select first Dropin and render payment form
|
|
454
|
+
- ✅ **When only Link available**: Wait for user manual selection (no auto-execution)
|
|
455
|
+
- ✅ **Prevents issue**: No more instant redirect before users see checkout
|
|
526
456
|
|
|
527
457
|
---
|
|
528
458
|
|
|
529
|
-
### PurchaseSuccessModal -
|
|
459
|
+
### PurchaseSuccessModal - Purchase Success
|
|
530
460
|
|
|
531
|
-
**✨
|
|
461
|
+
**✨ Auto-integrated** - Automatically displays after successful payment in CreditPackageModal and GenericPackageModal.
|
|
532
462
|
|
|
533
|
-
####
|
|
463
|
+
#### Features
|
|
534
464
|
|
|
535
|
-
- ✅
|
|
536
|
-
- ✅
|
|
537
|
-
- ✅
|
|
538
|
-
- ✅
|
|
539
|
-
- ✅
|
|
540
|
-
- ✅
|
|
465
|
+
- ✅ Email confirmation card design
|
|
466
|
+
- ✅ Beautiful animations (fade in/out, scale, sequential)
|
|
467
|
+
- ✅ Display purchase details (package name, credits, amount)
|
|
468
|
+
- ✅ Support ESC key, overlay click, close button
|
|
469
|
+
- ✅ Auto prevent body scroll
|
|
470
|
+
- ✅ Multi-language support (13+ languages)
|
|
541
471
|
|
|
542
|
-
####
|
|
472
|
+
#### Auto-trigger Flow
|
|
543
473
|
|
|
544
474
|
```
|
|
545
|
-
|
|
475
|
+
User clicks purchase button
|
|
546
476
|
↓
|
|
547
|
-
|
|
477
|
+
Payment successful
|
|
548
478
|
↓
|
|
549
|
-
CreditPackageModal/GenericPackageModal
|
|
479
|
+
CreditPackageModal/GenericPackageModal closes
|
|
550
480
|
↓
|
|
551
|
-
PurchaseSuccessModal
|
|
481
|
+
PurchaseSuccessModal displays (with animation)
|
|
552
482
|
↓
|
|
553
|
-
|
|
483
|
+
User closes success modal
|
|
554
484
|
↓
|
|
555
|
-
|
|
485
|
+
Auto credit balance refresh
|
|
556
486
|
↓
|
|
557
|
-
|
|
487
|
+
Trigger onPaymentSuccess callback
|
|
558
488
|
```
|
|
559
489
|
|
|
560
|
-
####
|
|
561
|
-
|
|
562
|
-
如需在其他场景手动调用:
|
|
490
|
+
#### Manual Usage (Optional)
|
|
563
491
|
|
|
564
492
|
```typescript
|
|
565
493
|
import { PurchaseSuccessModal } from '@seaverse/payment-sdk';
|
|
566
494
|
|
|
567
|
-
const
|
|
495
|
+
const modal = new PurchaseSuccessModal({
|
|
568
496
|
data: {
|
|
569
497
|
packName: 'Ice Breaker Pack',
|
|
570
498
|
credits: 120,
|
|
571
499
|
amount: '0.49',
|
|
572
|
-
currency: '$',
|
|
500
|
+
currency: '$', // Auto-converted from currency code
|
|
573
501
|
orderId: 'order_123',
|
|
574
502
|
transactionId: 'txn_456',
|
|
575
503
|
},
|
|
576
|
-
language: '
|
|
504
|
+
language: 'en',
|
|
577
505
|
onClose: () => {
|
|
578
|
-
console.log('
|
|
506
|
+
console.log('Success modal closed');
|
|
579
507
|
},
|
|
580
508
|
});
|
|
581
509
|
|
|
582
|
-
|
|
510
|
+
modal.open();
|
|
583
511
|
```
|
|
584
512
|
|
|
585
513
|
---
|
|
586
514
|
|
|
587
|
-
##
|
|
515
|
+
## 🌍 Internationalization
|
|
588
516
|
|
|
589
|
-
###
|
|
517
|
+
### Supported Languages (13+)
|
|
590
518
|
|
|
591
|
-
|
|
519
|
+
| Language | Code | Country Mapping |
|
|
520
|
+
|----------|------|-----------------|
|
|
521
|
+
| English | `en` | US |
|
|
522
|
+
| Simplified Chinese | `zh` | CN |
|
|
523
|
+
| Traditional Chinese | `zh-TW` | TW |
|
|
524
|
+
| Japanese | `ja` | JP |
|
|
525
|
+
| Korean | `ko` | KR |
|
|
526
|
+
| Spanish | `es` | ES |
|
|
527
|
+
| French | `fr` | FR |
|
|
528
|
+
| German | `de` | DE |
|
|
529
|
+
| Portuguese | `pt` | PT |
|
|
530
|
+
| Russian | `ru` | RU |
|
|
531
|
+
| Arabic | `ar` | SA |
|
|
532
|
+
| Hindi | `hi` | IN |
|
|
533
|
+
| Indonesian | `id` | ID |
|
|
592
534
|
|
|
593
|
-
|
|
594
|
-
import { PaymentClient } from '@seaverse/payment-sdk';
|
|
595
|
-
|
|
596
|
-
const client = new PaymentClient({
|
|
597
|
-
appId: 'seaverse',
|
|
598
|
-
token: 'your-bearer-token',
|
|
599
|
-
baseURL: 'https://payment.sg.seaverse.dev', // 可选
|
|
600
|
-
});
|
|
535
|
+
### Language Auto-Mapping
|
|
601
536
|
|
|
602
|
-
|
|
603
|
-
const detail = await client.getCreditDetail();
|
|
604
|
-
console.log('总余额:', detail.total_balance);
|
|
537
|
+
The SDK automatically maps language codes to country codes for payment method retrieval:
|
|
605
538
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
const transactions = await client.listTransactions({
|
|
612
|
-
page: 1,
|
|
613
|
-
page_size: 20,
|
|
614
|
-
start_time: '2024-01-01T00:00:00Z',
|
|
615
|
-
end_time: '2024-12-31T23:59:59Z',
|
|
539
|
+
```typescript
|
|
540
|
+
// User sets language
|
|
541
|
+
const modal = new CreditPackageModal({
|
|
542
|
+
language: 'ja', // Japanese
|
|
543
|
+
sdkConfig: { /* ... */ }
|
|
616
544
|
});
|
|
617
545
|
|
|
618
|
-
|
|
619
|
-
console.log(`${txn.type}: ${txn.amount} 积分`);
|
|
620
|
-
});
|
|
546
|
+
// SDK automatically uses country_code: 'JP' when fetching payment methods
|
|
621
547
|
```
|
|
622
548
|
|
|
623
|
-
|
|
549
|
+
### Custom Language Handling
|
|
624
550
|
|
|
625
|
-
|
|
626
|
-
| ----------- | -------- | -------------- |
|
|
627
|
-
| `daily` | 每日积分 | 次日 00:00 UTC |
|
|
628
|
-
| `event` | 活动积分 | 活动截止日期 |
|
|
629
|
-
| `monthly` | 月度积分 | 授予后 30 天 |
|
|
630
|
-
| `permanent` | 永久积分 | 永不过期 |
|
|
631
|
-
|
|
632
|
-
**消费优先级**:Daily → Event → Monthly → Permanent
|
|
633
|
-
|
|
634
|
-
---
|
|
635
|
-
|
|
636
|
-
### 订阅管理
|
|
637
|
-
|
|
638
|
-
查询和管理用户订阅:
|
|
551
|
+
For SDK initialization, some languages require special formatting:
|
|
639
552
|
|
|
640
553
|
```typescript
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const apiUrl = 'https://payment.sg.seaverse.dev';
|
|
649
|
-
const token = 'user-token';
|
|
650
|
-
|
|
651
|
-
// 查询当前订阅状态
|
|
652
|
-
const current = await getCurrentSubscription(apiUrl, token);
|
|
653
|
-
console.log('订阅状态:', current.subscription_status);
|
|
654
|
-
|
|
655
|
-
// 查询活跃订阅详情
|
|
656
|
-
const active = await getActiveSubscription(apiUrl, token);
|
|
657
|
-
console.log('当前套餐:', active.product_name);
|
|
658
|
-
|
|
659
|
-
// 升级/降级订阅
|
|
660
|
-
const changeResult = await changeSubscription(apiUrl, token, {
|
|
661
|
-
productId: 'pro_plan',
|
|
662
|
-
billingPeriod: 'year',
|
|
663
|
-
redirectUrl: window.location.href,
|
|
664
|
-
});
|
|
665
|
-
|
|
666
|
-
// 重启已取消的订阅
|
|
667
|
-
const restartResult = await restartSubscription(apiUrl, token, {
|
|
668
|
-
subscriptionId: 'sub_123',
|
|
669
|
-
});
|
|
554
|
+
// SDK Language Format Conversion
|
|
555
|
+
'zh' → 'zhCN' // Simplified Chinese
|
|
556
|
+
'zh-TW' → 'zhTW' // Traditional Chinese
|
|
557
|
+
'en' → 'en' // English (no conversion)
|
|
558
|
+
'ja' → 'ja' // Japanese (no conversion)
|
|
559
|
+
// ... other languages use code directly
|
|
670
560
|
```
|
|
671
561
|
|
|
672
562
|
---
|
|
673
563
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
检查订单状态和轮询支付结果:
|
|
564
|
+
## ⚙️ Configuration
|
|
677
565
|
|
|
678
|
-
|
|
679
|
-
import { checkOrderStatus, pollOrderStatus } from '@seaverse/payment-sdk';
|
|
680
|
-
|
|
681
|
-
const apiUrl = 'https://payment.sg.seaverse.dev';
|
|
682
|
-
const token = 'user-token';
|
|
683
|
-
|
|
684
|
-
// 单次查询订单状态
|
|
685
|
-
const status = await checkOrderStatus('transaction_id', apiUrl, token);
|
|
686
|
-
console.log('订单状态:', status.order_status);
|
|
566
|
+
### Environment Configuration
|
|
687
567
|
|
|
688
|
-
|
|
689
|
-
const finalStatus = await pollOrderStatus('transaction_id', apiUrl, token, {
|
|
690
|
-
interval: 2000, // 轮询间隔(毫秒)
|
|
691
|
-
maxAttempts: 30, // 最大尝试次数
|
|
692
|
-
onPoll: (status, attempt) => {
|
|
693
|
-
console.log(`第 ${attempt} 次查询:${status}`);
|
|
694
|
-
},
|
|
695
|
-
});
|
|
568
|
+
The SDK auto-configures based on `environment`:
|
|
696
569
|
|
|
697
|
-
|
|
570
|
+
**Development**:
|
|
571
|
+
```typescript
|
|
572
|
+
{
|
|
573
|
+
scriptUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/client.js',
|
|
574
|
+
clientId: 'XF49NOfyZ54O16GujB0ptio2',
|
|
575
|
+
orderApiUrl: 'https://payment.sg.seaverse.dev',
|
|
576
|
+
walletApiUrl: 'https://wallet.sg.seaverse.dev',
|
|
577
|
+
cssUrl: 'https://seaart-publish.sc-api-release.saconsole.com/payment-component/client.css',
|
|
578
|
+
}
|
|
698
579
|
```
|
|
699
580
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
### SeaartPayment SDK(完全自定义)
|
|
703
|
-
|
|
704
|
-
适用于需要完全控制支付流程的高级场景:
|
|
705
|
-
|
|
581
|
+
**Production**:
|
|
706
582
|
```typescript
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
cssUrl: 'https://your-cdn.com/seaart-payment.css', // 可选
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
// 2. 获取支付方式
|
|
719
|
-
const methods = await sdk.getPaymentMethods({
|
|
720
|
-
country_code: 'US',
|
|
721
|
-
business_type: 2, // 1=一次性, 2=订阅
|
|
722
|
-
});
|
|
583
|
+
{
|
|
584
|
+
scriptUrl: 'https://payment-static.seaverse.com/sdk/seaart-payment-component.js',
|
|
585
|
+
clientId: 'prod_client_id',
|
|
586
|
+
orderApiUrl: 'https://payment.seaverse.com',
|
|
587
|
+
walletApiUrl: 'https://wallet.seaverse.com',
|
|
588
|
+
cssUrl: 'https://payment-static.seaverse.com/sdk/seaart-payment-component.css',
|
|
589
|
+
}
|
|
590
|
+
```
|
|
723
591
|
|
|
724
|
-
|
|
725
|
-
const orderPayment = sdk.createOrderPayment({
|
|
726
|
-
orderId: 'order-123',
|
|
727
|
-
accountToken: 'user-token',
|
|
728
|
-
});
|
|
592
|
+
### PaymentSDKConfig Interface
|
|
729
593
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
//
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
},
|
|
747
|
-
});
|
|
748
|
-
await dropinPayment.render();
|
|
749
|
-
|
|
750
|
-
// 5. 处理支付回调(回调页面)
|
|
751
|
-
const result = await sdk.handleCallback(
|
|
752
|
-
{ type: 'subscription' },
|
|
753
|
-
'https://payment-api.com',
|
|
754
|
-
'auth-token'
|
|
755
|
-
);
|
|
756
|
-
if (result.success) {
|
|
757
|
-
console.log('支付验证成功:', result.data);
|
|
594
|
+
```typescript
|
|
595
|
+
interface PaymentSDKConfig {
|
|
596
|
+
// Required
|
|
597
|
+
environment: 'development' | 'production';
|
|
598
|
+
accountToken: string;
|
|
599
|
+
|
|
600
|
+
// Optional (with sensible defaults)
|
|
601
|
+
businessType?: 1 | 2; // 1 = one-time, 2 = subscription
|
|
602
|
+
scriptTimeout?: number; // Default: 10000ms
|
|
603
|
+
paymentMethodType?: string; // Default: 'dropin'
|
|
604
|
+
|
|
605
|
+
// Advanced overrides
|
|
606
|
+
scriptUrl?: string; // Override environment config
|
|
607
|
+
clientId?: string; // Override environment config
|
|
608
|
+
orderApiUrl?: string; // Override environment config
|
|
609
|
+
cssUrl?: string; // Override environment config
|
|
758
610
|
}
|
|
759
611
|
```
|
|
760
612
|
|
|
761
613
|
---
|
|
762
614
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
**适用场景**:
|
|
766
|
-
- ✅ 需要弹框形式的 Dropin 支付(无需自己创建弹框容器)
|
|
767
|
-
- ✅ 支持用户取消支付时的挽留弹框(可选)
|
|
768
|
-
- ✅ 自动处理弹框打开/关闭/清理逻辑
|
|
615
|
+
## 🔍 Advanced Features
|
|
769
616
|
|
|
770
|
-
|
|
617
|
+
### Credit Query
|
|
771
618
|
|
|
772
619
|
```typescript
|
|
773
|
-
import {
|
|
774
|
-
|
|
775
|
-
// 1. 初始化 SDK
|
|
776
|
-
const sdk = SeaartPaymentSDK.getInstance();
|
|
777
|
-
await sdk.init({
|
|
778
|
-
scriptUrl: 'https://your-cdn.com/seaart-payment.js',
|
|
779
|
-
clientId: 'your-client-id',
|
|
780
|
-
language: 'en',
|
|
781
|
-
});
|
|
782
|
-
|
|
783
|
-
// 2. 获取支付方式
|
|
784
|
-
const methods = await sdk.getPaymentMethods({
|
|
785
|
-
country_code: 'US',
|
|
786
|
-
business_type: 1, // 1=一次性购买
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
// 3. 创建订单支付实例
|
|
790
|
-
const orderPayment = sdk.createOrderPayment({
|
|
791
|
-
orderId: 'order-123',
|
|
792
|
-
accountToken: 'user-token',
|
|
793
|
-
});
|
|
794
|
-
|
|
795
|
-
// 4. 选择 Dropin 支付方式
|
|
796
|
-
const dropinMethod = methods.find(m => m.payment_type === 2);
|
|
797
|
-
|
|
798
|
-
// 5. 创建 Dropin 支付弹框
|
|
799
|
-
const modal = new DropinPaymentModal(
|
|
800
|
-
orderPayment,
|
|
801
|
-
'order-123',
|
|
802
|
-
'user-token',
|
|
803
|
-
dropinMethod,
|
|
804
|
-
{
|
|
805
|
-
// 弹框配置
|
|
806
|
-
modalTitle: `Pay with ${dropinMethod.payment_method_name}`,
|
|
807
|
-
enableRetention: true, // 启用挽留弹框(默认:true)
|
|
808
|
-
|
|
809
|
-
// 挽留弹框配置
|
|
810
|
-
retentionOptions: {
|
|
811
|
-
language: 'en', // 'en' | 'zh-CN'
|
|
812
|
-
bonusAmount: 990, // 活动赠送积分(可选)
|
|
813
|
-
},
|
|
814
|
-
|
|
815
|
-
// 支付回调
|
|
816
|
-
onCompleted: (payload) => {
|
|
817
|
-
console.log('支付成功!', payload);
|
|
818
|
-
// 刷新积分、更新 UI 等
|
|
819
|
-
},
|
|
820
|
-
|
|
821
|
-
onFailed: (payload) => {
|
|
822
|
-
console.error('支付失败:', payload);
|
|
823
|
-
},
|
|
620
|
+
import { getCreditDetail } from '@seaverse/payment-sdk';
|
|
824
621
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
},
|
|
828
|
-
}
|
|
829
|
-
);
|
|
622
|
+
const apiHost = 'https://wallet.seaverse.com';
|
|
623
|
+
const token = 'user-token';
|
|
830
624
|
|
|
831
|
-
|
|
832
|
-
await modal.open();
|
|
625
|
+
const detail = await getCreditDetail(apiHost, token);
|
|
833
626
|
|
|
834
|
-
|
|
835
|
-
|
|
627
|
+
console.log('Total balance:', detail.total_balance);
|
|
628
|
+
console.log('Tier:', detail.tier);
|
|
836
629
|
|
|
837
|
-
|
|
838
|
-
|
|
630
|
+
detail.pools.forEach(pool => {
|
|
631
|
+
console.log(`${pool.type} pool: ${pool.balance} credits`);
|
|
632
|
+
});
|
|
839
633
|
```
|
|
840
634
|
|
|
841
|
-
####
|
|
635
|
+
#### Credit Pool System
|
|
842
636
|
|
|
843
|
-
|
|
637
|
+
| Pool Type | Description | Expiration |
|
|
638
|
+
|-----------|-------------|------------|
|
|
639
|
+
| `daily` | Daily credits | Next day 00:00 UTC |
|
|
640
|
+
| `event` | Event credits | Event end date |
|
|
641
|
+
| `monthly` | Monthly credits | 30 days after grant |
|
|
642
|
+
| `permanent` | Permanent credits | Never expires |
|
|
844
643
|
|
|
845
|
-
|
|
846
|
-
2. **显示挽留弹框** → 自动弹出挽留弹框,展示:
|
|
847
|
-
- 订单详情(商品名称、购买数量、优惠价格)
|
|
848
|
-
- 倒计时提示(15分钟订单过期时间)
|
|
849
|
-
- 活动赠送(如果有)
|
|
850
|
-
3. **用户选择**:
|
|
851
|
-
- **继续支付**:关闭挽留弹框 → 重新打开支付弹框
|
|
852
|
-
- **确认取消**:关闭所有弹框 → 清理资源
|
|
644
|
+
**Consumption Priority**: Daily → Event → Monthly → Permanent
|
|
853
645
|
|
|
854
|
-
|
|
646
|
+
### Subscription Management
|
|
855
647
|
|
|
856
648
|
```typescript
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
modalOptions?: {
|
|
863
|
-
showCloseButton?: boolean; // 显示关闭按钮(默认:true)
|
|
864
|
-
closeOnOverlayClick?: boolean; // 点击遮罩关闭(默认:false)
|
|
865
|
-
closeOnEsc?: boolean; // ESC 键关闭(默认:false)
|
|
866
|
-
className?: string; // 自定义类名
|
|
867
|
-
maxWidth?: string; // 最大宽度(默认:'600px')
|
|
868
|
-
};
|
|
869
|
-
|
|
870
|
-
// 是否启用挽留弹框(默认:true)
|
|
871
|
-
enableRetention?: boolean;
|
|
872
|
-
|
|
873
|
-
// 挽留弹框配置
|
|
874
|
-
retentionOptions?: {
|
|
875
|
-
language?: 'en' | 'zh-CN'; // 语言(默认:'en')
|
|
876
|
-
bonusAmount?: number; // 活动赠送积分(可选)
|
|
877
|
-
};
|
|
878
|
-
|
|
879
|
-
// 支付回调
|
|
880
|
-
onSubmit?: (payload: any) => void;
|
|
881
|
-
onError?: (payload: any, error: any) => void;
|
|
882
|
-
onCreateOrder?: (payload: any) => void;
|
|
883
|
-
onCompleted?: (payload: any) => void;
|
|
884
|
-
onFailed?: (payload: any) => void;
|
|
885
|
-
onLoading?: (loading: boolean) => void;
|
|
886
|
-
}
|
|
887
|
-
```
|
|
888
|
-
|
|
889
|
-
#### 挽留弹框预览
|
|
890
|
-
|
|
891
|
-
挽留弹框采用深色卡片设计,包含:
|
|
892
|
-
- 订单倒计时(15 分钟)
|
|
893
|
-
- 商品信息(名称、购买数量、活动赠送、优惠价)
|
|
894
|
-
- 价格显示(自动根据货币代码映射符号,如 USD→$, EUR→€, JPY→¥ 等)
|
|
895
|
-
- 两个按钮:「取消」和「继续支付」(使用与积分弹框一致的绿色渐变主题色)
|
|
649
|
+
import {
|
|
650
|
+
getCurrentSubscription,
|
|
651
|
+
getActiveSubscription,
|
|
652
|
+
changeSubscription,
|
|
653
|
+
} from '@seaverse/payment-sdk';
|
|
896
654
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
- 欧元 (EUR) → €
|
|
900
|
-
- 英镑 (GBP) → £
|
|
901
|
-
- 日元 (JPY) / 人民币 (CNY) → ¥
|
|
902
|
-
- 新加坡元 (SGD) → S$
|
|
903
|
-
- 港币 (HKD) → HK$
|
|
904
|
-
- 等 30+ 种货币符号...
|
|
655
|
+
const apiUrl = 'https://payment.seaverse.com';
|
|
656
|
+
const token = 'user-token';
|
|
905
657
|
|
|
906
|
-
|
|
658
|
+
// Query current subscription status
|
|
659
|
+
const current = await getCurrentSubscription(apiUrl, token);
|
|
660
|
+
console.log('Status:', current.subscription_status);
|
|
907
661
|
|
|
908
|
-
|
|
662
|
+
// Get active subscription details
|
|
663
|
+
const active = await getActiveSubscription(apiUrl, token);
|
|
664
|
+
console.log('Plan:', active.product_name);
|
|
909
665
|
|
|
910
|
-
|
|
911
|
-
const
|
|
912
|
-
|
|
913
|
-
'
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
{
|
|
917
|
-
enableRetention: false, // 禁用挽留弹框
|
|
918
|
-
onCompleted: (payload) => {
|
|
919
|
-
console.log('支付成功!', payload);
|
|
920
|
-
},
|
|
921
|
-
}
|
|
922
|
-
);
|
|
666
|
+
// Upgrade/downgrade subscription
|
|
667
|
+
const result = await changeSubscription(apiUrl, token, {
|
|
668
|
+
productId: 'pro_plan',
|
|
669
|
+
billingPeriod: 'year',
|
|
670
|
+
redirectUrl: window.location.href,
|
|
671
|
+
});
|
|
923
672
|
```
|
|
924
673
|
|
|
925
|
-
|
|
674
|
+
### Order Status Tracking
|
|
926
675
|
|
|
927
|
-
|
|
676
|
+
```typescript
|
|
677
|
+
import { checkOrderStatus, pollOrderStatus } from '@seaverse/payment-sdk';
|
|
928
678
|
|
|
929
|
-
|
|
679
|
+
const apiUrl = 'https://payment.seaverse.com';
|
|
680
|
+
const token = 'user-token';
|
|
681
|
+
const transactionId = 'txn_123';
|
|
930
682
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
| 生产环境 | `'production'` | 正式生产环境 |
|
|
683
|
+
// Single status check
|
|
684
|
+
const status = await checkOrderStatus(transactionId, apiUrl, token);
|
|
685
|
+
console.log('Order status:', status.order_status);
|
|
935
686
|
|
|
936
|
-
|
|
687
|
+
// Poll until final status
|
|
688
|
+
const finalStatus = await pollOrderStatus(transactionId, apiUrl, token, {
|
|
689
|
+
interval: 2000, // Poll interval (ms)
|
|
690
|
+
maxAttempts: 30, // Max attempts
|
|
691
|
+
onPoll: (status, attempt) => {
|
|
692
|
+
console.log(`Attempt ${attempt}: ${status}`);
|
|
693
|
+
},
|
|
694
|
+
});
|
|
937
695
|
|
|
938
|
-
|
|
939
|
-
interface PaymentSDKConfig {
|
|
940
|
-
// 必填参数
|
|
941
|
-
environment: 'development' | 'production'; // 环境变量
|
|
942
|
-
countryCode: string; // 国家代码(ISO 3166-1)
|
|
943
|
-
|
|
944
|
-
// 可选参数
|
|
945
|
-
accountToken?: string; // 用户认证令牌
|
|
946
|
-
businessType?: 1 | 2; // 1=一次性购买, 2=订阅(默认 1)
|
|
947
|
-
|
|
948
|
-
// 高级选项(覆盖环境配置)
|
|
949
|
-
scriptUrl?: string; // 自定义脚本 URL
|
|
950
|
-
clientId?: string; // 自定义客户端 ID
|
|
951
|
-
orderApiUrl?: string; // 自定义订单 API 地址
|
|
952
|
-
cssUrl?: string; // 自定义 CSS URL
|
|
953
|
-
scriptTimeout?: number; // 脚本加载超时(默认 10000ms)
|
|
954
|
-
paymentMethodType?: string; // 支付方式类型过滤(默认 'dropin')
|
|
955
|
-
}
|
|
696
|
+
console.log('Final status:', finalStatus.order_status);
|
|
956
697
|
```
|
|
957
698
|
|
|
958
699
|
---
|
|
959
700
|
|
|
960
|
-
## 🎨 UI
|
|
701
|
+
## 🎨 UI Feedback Utilities
|
|
961
702
|
|
|
962
|
-
SDK
|
|
703
|
+
SDK provides unified UI feedback tools (replacement for browser `alert()`):
|
|
963
704
|
|
|
964
705
|
```typescript
|
|
965
706
|
import {
|
|
@@ -970,46 +711,44 @@ import {
|
|
|
970
711
|
hideLoadingIndicator,
|
|
971
712
|
} from '@seaverse/payment-sdk';
|
|
972
713
|
|
|
973
|
-
//
|
|
974
|
-
showErrorMessage('
|
|
714
|
+
// Error message (red gradient)
|
|
715
|
+
showErrorMessage('Payment failed, please try again', 3000);
|
|
975
716
|
|
|
976
|
-
//
|
|
977
|
-
showSuccessMessage('
|
|
717
|
+
// Success message (green gradient)
|
|
718
|
+
showSuccessMessage('Payment successful!', 3000);
|
|
978
719
|
|
|
979
|
-
//
|
|
980
|
-
showInfoMessage('
|
|
720
|
+
// Info message (blue gradient)
|
|
721
|
+
showInfoMessage('Processing your request...', 3000);
|
|
981
722
|
|
|
982
|
-
//
|
|
983
|
-
const loader = showLoadingIndicator('
|
|
984
|
-
// ...
|
|
723
|
+
// Loading indicator
|
|
724
|
+
const loader = showLoadingIndicator('Initializing payment system...');
|
|
725
|
+
// ... async operation
|
|
985
726
|
hideLoadingIndicator(loader);
|
|
986
727
|
```
|
|
987
728
|
|
|
988
|
-
|
|
989
|
-
- ✅
|
|
990
|
-
- ✅
|
|
991
|
-
- ✅
|
|
992
|
-
- ✅
|
|
993
|
-
- ✅ XSS
|
|
729
|
+
**Features**:
|
|
730
|
+
- ✅ Beautiful gradient backgrounds + icons
|
|
731
|
+
- ✅ Auto fade in/out animations
|
|
732
|
+
- ✅ Auto removal (configurable duration)
|
|
733
|
+
- ✅ Prevent duplicate display
|
|
734
|
+
- ✅ XSS protection
|
|
994
735
|
|
|
995
736
|
---
|
|
996
737
|
|
|
997
|
-
## 🛡️
|
|
738
|
+
## 🛡️ Error Handling
|
|
998
739
|
|
|
999
|
-
###
|
|
740
|
+
### Common Error Codes
|
|
1000
741
|
|
|
1001
|
-
|
|
|
1002
|
-
|
|
1003
|
-
| `0`
|
|
1004
|
-
| `400`
|
|
1005
|
-
| `401`
|
|
1006
|
-
| `500`
|
|
1007
|
-
| `4001` | `DAILY_LIMIT_EXCEEDED` |
|
|
1008
|
-
| `4002` | `PRODUCT_NOT_FOUND`
|
|
1009
|
-
| `4004` | `INSUFFICIENT_BALANCE` | 余额不足 |
|
|
1010
|
-
| `4005` | `ORDER_NOT_FOUND` | 订单不存在 |
|
|
742
|
+
| Code | Constant | Description |
|
|
743
|
+
|------|----------|-------------|
|
|
744
|
+
| `0` | `SUCCESS` | Success |
|
|
745
|
+
| `400` | `BAD_REQUEST` | Invalid parameters |
|
|
746
|
+
| `401` | `UNAUTHORIZED` | Unauthorized |
|
|
747
|
+
| `500` | `SERVER_ERROR` | Server error |
|
|
748
|
+
| `4001` | `DAILY_LIMIT_EXCEEDED` | Daily limit exceeded |
|
|
749
|
+
| `4002` | `PRODUCT_NOT_FOUND` | Product not found |
|
|
1011
750
|
|
|
1012
|
-
###
|
|
751
|
+
### Error Handling Example
|
|
1013
752
|
|
|
1014
753
|
```typescript
|
|
1015
754
|
const modal = new GenericPackageModal({
|
|
@@ -1017,13 +756,12 @@ const modal = new GenericPackageModal({
|
|
|
1017
756
|
sdkConfig: { /* ... */ },
|
|
1018
757
|
|
|
1019
758
|
onPaymentFailed: (error, pkg) => {
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
showErrorMessage('此套餐仅限购买一次,您已购买过');
|
|
759
|
+
if (error.message.includes('limit')) {
|
|
760
|
+
showErrorMessage(`Daily limit reached for ${pkg.name}`);
|
|
761
|
+
} else if (error.message.includes('payment')) {
|
|
762
|
+
showErrorMessage('Payment processing failed');
|
|
1025
763
|
} else {
|
|
1026
|
-
showErrorMessage(
|
|
764
|
+
showErrorMessage(`Error: ${error.message}`);
|
|
1027
765
|
}
|
|
1028
766
|
},
|
|
1029
767
|
});
|
|
@@ -1031,64 +769,22 @@ const modal = new GenericPackageModal({
|
|
|
1031
769
|
|
|
1032
770
|
---
|
|
1033
771
|
|
|
1034
|
-
## 🧪
|
|
1035
|
-
|
|
1036
|
-
在开发环境测试支付功能:
|
|
1037
|
-
|
|
1038
|
-
| 字段 | 值 |
|
|
1039
|
-
| -------- | ------------------ |
|
|
1040
|
-
| 卡号 | `4212345678910006` |
|
|
1041
|
-
| 有效期 | `03/30` |
|
|
1042
|
-
| CVC | `737` |
|
|
1043
|
-
| 3DS 密码 | `password` |
|
|
1044
|
-
|
|
1045
|
-
---
|
|
1046
|
-
|
|
1047
|
-
## 📊 API 对比表
|
|
1048
|
-
|
|
1049
|
-
### CreditPackageModal vs GenericPackageModal
|
|
1050
|
-
|
|
1051
|
-
| 特性 | CreditPackageModal | GenericPackageModal |
|
|
1052
|
-
| -------------- | ------------------ | --------------------------------- |
|
|
1053
|
-
| **套餐数据** | 内置预设套餐 | 外部配置(灵活) |
|
|
1054
|
-
| **套餐类型** | 标准积分套餐 | 任意类型(破冰/告急/首充/自定义) |
|
|
1055
|
-
| **购买限制** | 无 | 支持每日/终身限购 |
|
|
1056
|
-
| **奖励展示** | 无 | 支持奖励百分比 |
|
|
1057
|
-
| **配置复杂度** | ⭐️ 简单 | ⭐️⭐️ 中等 |
|
|
1058
|
-
| **使用场景** | 标准积分购买 | 特殊促销、限时活动 |
|
|
1059
|
-
|
|
1060
|
-
**选择建议**:
|
|
1061
|
-
- 🎯 **标准积分购买** → 使用 `CreditPackageModal`(推荐新手)
|
|
1062
|
-
- 🎁 **特殊促销活动** → 使用 `GenericPackageModal`
|
|
1063
|
-
|
|
1064
|
-
---
|
|
1065
|
-
|
|
1066
|
-
## 🔄 迁移指南
|
|
1067
|
-
|
|
1068
|
-
### 从 v0.8.x 迁移到 v0.9.x
|
|
772
|
+
## 🧪 Testing
|
|
1069
773
|
|
|
1070
|
-
|
|
774
|
+
### Test Card Numbers (Development Only)
|
|
1071
775
|
|
|
1072
|
-
|
|
1073
|
-
// ✅ 新版本(v0.8.x)
|
|
1074
|
-
const modal = new GenericPackageModal({
|
|
1075
|
-
packages: packages,
|
|
1076
|
-
sdkConfig: {
|
|
1077
|
-
environment: 'development', // 只需指定环境
|
|
1078
|
-
countryCode: 'SG', // 扁平化参数
|
|
1079
|
-
businessType: 1, // 可选,默认 1
|
|
1080
|
-
},
|
|
1081
|
-
});
|
|
1082
|
-
```
|
|
776
|
+
For testing payment functionality in development environment:
|
|
1083
777
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
778
|
+
| Field | Value |
|
|
779
|
+
|-------|-------|
|
|
780
|
+
| Card Number | `4212345678910006` |
|
|
781
|
+
| Expiry | `03/30` |
|
|
782
|
+
| CVC | `737` |
|
|
783
|
+
| 3DS Password | `password` |
|
|
1088
784
|
|
|
1089
785
|
---
|
|
1090
786
|
|
|
1091
|
-
## 🌐
|
|
787
|
+
## 🌐 Framework Integration
|
|
1092
788
|
|
|
1093
789
|
### Vue 3
|
|
1094
790
|
|
|
@@ -1097,16 +793,18 @@ const modal = new GenericPackageModal({
|
|
|
1097
793
|
import { ref } from 'vue';
|
|
1098
794
|
import { CreditPackageModal } from '@seaverse/payment-sdk';
|
|
1099
795
|
|
|
1100
|
-
const
|
|
796
|
+
const userToken = ref('user-token-here');
|
|
797
|
+
|
|
798
|
+
const openPaymentModal = () => {
|
|
1101
799
|
const modal = new CreditPackageModal({
|
|
800
|
+
language: 'en',
|
|
1102
801
|
sdkConfig: {
|
|
1103
802
|
environment: import.meta.env.DEV ? 'development' : 'production',
|
|
1104
|
-
countryCode: 'SG',
|
|
1105
803
|
accountToken: userToken.value,
|
|
1106
804
|
},
|
|
1107
|
-
onPaymentSuccess: (orderId, transactionId) => {
|
|
1108
|
-
console.log('
|
|
1109
|
-
//
|
|
805
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
806
|
+
console.log('Payment successful', { orderId, transactionId });
|
|
807
|
+
// Refresh user data
|
|
1110
808
|
},
|
|
1111
809
|
});
|
|
1112
810
|
modal.open();
|
|
@@ -1114,7 +812,7 @@ const showModal = () => {
|
|
|
1114
812
|
</script>
|
|
1115
813
|
|
|
1116
814
|
<template>
|
|
1117
|
-
<button @click="
|
|
815
|
+
<button @click="openPaymentModal">Purchase Credits</button>
|
|
1118
816
|
</template>
|
|
1119
817
|
```
|
|
1120
818
|
|
|
@@ -1126,101 +824,170 @@ import { CreditPackageModal } from '@seaverse/payment-sdk';
|
|
|
1126
824
|
function PurchaseButton() {
|
|
1127
825
|
const handlePurchase = () => {
|
|
1128
826
|
const modal = new CreditPackageModal({
|
|
827
|
+
language: 'en',
|
|
1129
828
|
sdkConfig: {
|
|
1130
829
|
environment: process.env.NODE_ENV === 'development' ? 'development' : 'production',
|
|
1131
|
-
countryCode: 'SG',
|
|
1132
830
|
accountToken: getUserToken(),
|
|
1133
831
|
},
|
|
1134
|
-
onPaymentSuccess: (orderId, transactionId) => {
|
|
1135
|
-
console.log('
|
|
1136
|
-
//
|
|
832
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
833
|
+
console.log('Payment successful', { orderId, transactionId });
|
|
834
|
+
// Refresh user data
|
|
1137
835
|
},
|
|
1138
836
|
});
|
|
1139
837
|
modal.open();
|
|
1140
838
|
};
|
|
1141
839
|
|
|
1142
|
-
return <button onClick={handlePurchase}
|
|
840
|
+
return <button onClick={handlePurchase}>Purchase Credits</button>;
|
|
1143
841
|
}
|
|
1144
842
|
```
|
|
1145
843
|
|
|
844
|
+
### Svelte
|
|
845
|
+
|
|
846
|
+
```svelte
|
|
847
|
+
<script lang="ts">
|
|
848
|
+
import { CreditPackageModal } from '@seaverse/payment-sdk';
|
|
849
|
+
|
|
850
|
+
let userToken = 'user-token-here';
|
|
851
|
+
|
|
852
|
+
function openPaymentModal() {
|
|
853
|
+
const modal = new CreditPackageModal({
|
|
854
|
+
language: 'en',
|
|
855
|
+
sdkConfig: {
|
|
856
|
+
environment: 'development',
|
|
857
|
+
accountToken: userToken,
|
|
858
|
+
},
|
|
859
|
+
onPaymentSuccess: (orderId, transactionId, pkg) => {
|
|
860
|
+
console.log('Payment successful', { orderId, transactionId });
|
|
861
|
+
},
|
|
862
|
+
});
|
|
863
|
+
modal.open();
|
|
864
|
+
}
|
|
865
|
+
</script>
|
|
866
|
+
|
|
867
|
+
<button on:click={openPaymentModal}>Purchase Credits</button>
|
|
868
|
+
```
|
|
869
|
+
|
|
1146
870
|
---
|
|
1147
871
|
|
|
1148
|
-
## 📝 TypeScript
|
|
872
|
+
## 📝 TypeScript Support
|
|
1149
873
|
|
|
1150
|
-
|
|
874
|
+
Full TypeScript type definitions included:
|
|
1151
875
|
|
|
1152
876
|
```typescript
|
|
1153
877
|
import type {
|
|
1154
|
-
// Modal
|
|
878
|
+
// Modal types
|
|
1155
879
|
CreditPackageModalOptions,
|
|
1156
880
|
GenericPackageModalOptions,
|
|
1157
881
|
GenericPackage,
|
|
1158
|
-
|
|
882
|
+
CreditPackageItem,
|
|
1159
883
|
|
|
1160
|
-
//
|
|
884
|
+
// Configuration types
|
|
1161
885
|
PaymentSDKConfig,
|
|
1162
886
|
Environment,
|
|
1163
887
|
EnvironmentConfig,
|
|
888
|
+
LocaleCode,
|
|
889
|
+
CountryCode,
|
|
1164
890
|
|
|
1165
|
-
//
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
891
|
+
// Payment types
|
|
892
|
+
Product,
|
|
893
|
+
ProductType,
|
|
894
|
+
AutoCreateOrderConfig,
|
|
895
|
+
PaymentMethod,
|
|
896
|
+
BindCard,
|
|
1169
897
|
|
|
1170
|
-
//
|
|
898
|
+
// Response types
|
|
899
|
+
OrderStatusResponse,
|
|
900
|
+
CreditDetailResponse,
|
|
1171
901
|
CurrentSubscription,
|
|
1172
902
|
ActiveSubscription,
|
|
1173
|
-
|
|
1174
|
-
// 订单相关
|
|
1175
|
-
OrderStatus,
|
|
1176
|
-
OrderStatusResponse,
|
|
1177
903
|
} from '@seaverse/payment-sdk';
|
|
1178
904
|
```
|
|
1179
905
|
|
|
1180
906
|
---
|
|
1181
907
|
|
|
1182
|
-
##
|
|
908
|
+
## 📊 Comparison Table
|
|
1183
909
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
910
|
+
### CreditPackageModal vs GenericPackageModal vs PaymentCheckoutModal
|
|
911
|
+
|
|
912
|
+
| Feature | CreditPackageModal | GenericPackageModal | PaymentCheckoutModal |
|
|
913
|
+
|---------|-------------------|---------------------|---------------------|
|
|
914
|
+
| **Package Data** | API-fetched | User-provided | User-provided product |
|
|
915
|
+
| **Package Type** | Dynamic credit packs | Custom (promo/special) | Any product type |
|
|
916
|
+
| **Complexity** | ⭐️ Simple | ⭐️⭐️ Medium | ⭐️⭐️⭐️ Advanced |
|
|
917
|
+
| **Use Case** | Standard purchases | Promotions/offers | Full checkout control |
|
|
918
|
+
| **Customization** | Limited | Medium | Full control |
|
|
919
|
+
| **SDK Initialization** | Auto (via PaymentCheckoutModal) | Auto (via PaymentCheckoutModal) | Auto |
|
|
920
|
+
| **Payment Methods** | All supported | All supported | All supported |
|
|
921
|
+
|
|
922
|
+
**Selection Guide**:
|
|
923
|
+
- 🎯 **Standard credit purchases** → Use `CreditPackageModal` (recommended for beginners)
|
|
924
|
+
- 🎁 **Special promotions** → Use `GenericPackageModal`
|
|
925
|
+
- 🔧 **Advanced custom flows** → Use `PaymentCheckoutModal`
|
|
1188
926
|
|
|
1189
927
|
---
|
|
1190
928
|
|
|
1191
|
-
## 📄
|
|
929
|
+
## 📄 Changelog
|
|
1192
930
|
|
|
1193
|
-
|
|
931
|
+
### v0.9.0 (2026-02-07) - Critical Bug Fixes
|
|
932
|
+
|
|
933
|
+
**🔧 Critical Fixes**:
|
|
934
|
+
- Fixed SDK initialization failure when only Link payment methods available
|
|
935
|
+
- Issue: `BasePackageModal.initializeSDK()` required Dropin payment (payment_type === 2)
|
|
936
|
+
- Solution: Override `initializeSDK()` in CreditPackageModal and GenericPackageModal
|
|
937
|
+
- Now PaymentCheckoutModal handles all SDK initialization independently
|
|
938
|
+
|
|
939
|
+
- Fixed Link payment auto-execution issue
|
|
940
|
+
- Issue: `autoSelectDefaultPaymentMethod()` auto-executed Link payment, causing instant redirect
|
|
941
|
+
- Solution: Refined strategy - only auto-select when Dropin exists; wait for manual selection when only Link available
|
|
942
|
+
- Improved UX: Users now see checkout modal before any payment action
|
|
943
|
+
|
|
944
|
+
**🎨 UI/UX Improvements**:
|
|
945
|
+
- Increased payment method card spacing from 8px to 14px
|
|
946
|
+
- Better visual breathing room and click targets
|
|
947
|
+
- Consistent spacing in both skeleton and main UI
|
|
948
|
+
|
|
949
|
+
**📁 Files Changed** (5 files, +86 -53 lines):
|
|
950
|
+
- `CreditPackageModal.ts`: Added `initializeSDK()` and `waitForSDKInitialization()` overrides
|
|
951
|
+
- `GenericPackageModal.ts`: Added `initializeSDK()` and `waitForSDKInitialization()` overrides
|
|
952
|
+
- `PaymentCheckoutModal.ts`: Refined `autoSelectDefaultPaymentMethod()` logic (lines 485-517)
|
|
953
|
+
- `PaymentUIRenderer.ts`: Updated card gap from 8px to 14px (lines 207, 276)
|
|
954
|
+
- `index.ts`: Version bump
|
|
955
|
+
|
|
956
|
+
### v0.8.2 (2026-02-02) - Architecture Refactoring
|
|
957
|
+
|
|
958
|
+
**🏗️ Architecture**:
|
|
959
|
+
- Created `BasePackageModal` abstract base class
|
|
960
|
+
- Eliminated ~400 lines of duplicate code between CreditPackageModal and GenericPackageModal
|
|
961
|
+
- Improved type safety with TypeScript generics
|
|
962
|
+
- 100% backward compatible - no breaking changes
|
|
963
|
+
|
|
964
|
+
**📦 Package Size**:
|
|
965
|
+
- CreditPackageModal: 1042 lines → 515 lines (50% reduction)
|
|
966
|
+
- GenericPackageModal: 752 lines → 340 lines (55% reduction)
|
|
967
|
+
- Total code reduction: ~25%
|
|
1194
968
|
|
|
1195
969
|
---
|
|
1196
970
|
|
|
1197
|
-
##
|
|
971
|
+
## 🔗 Links
|
|
1198
972
|
|
|
1199
|
-
|
|
973
|
+
- 📦 [NPM Package](https://www.npmjs.com/package/@seaverse/payment-sdk)
|
|
974
|
+
- 🐙 [GitHub Repository](https://github.com/SeaVerseAI/sv-sdk)
|
|
975
|
+
- 📖 [API Documentation](https://github.com/SeaVerseAI/sv-sdk/tree/main/packages/payment-sdk)
|
|
976
|
+
- 🐛 [Issue Tracker](https://github.com/SeaVerseAI/sv-sdk/issues)
|
|
1200
977
|
|
|
1201
978
|
---
|
|
1202
979
|
|
|
1203
|
-
|
|
1204
|
-
|
|
980
|
+
## 📄 License
|
|
981
|
+
|
|
982
|
+
MIT License
|
|
1205
983
|
|
|
1206
|
-
|
|
984
|
+
---
|
|
1207
985
|
|
|
1208
|
-
|
|
986
|
+
## 🤝 Contributing
|
|
1209
987
|
|
|
1210
|
-
|
|
1211
|
-
- 🏗️ 创建 `BasePackageModal` 抽象基类,消除 `CreditPackageModal` 和 `GenericPackageModal` 之间的重复代码
|
|
1212
|
-
- 📉 减少约 400 行重复代码(25% 代码量减少)
|
|
1213
|
-
- 🎯 `CreditPackageModal`: 从 1042 行减少到 515 行
|
|
1214
|
-
- 🎯 `GenericPackageModal`: 从 752 行减少到 340 行
|
|
1215
|
-
- ✅ 完全向后兼容,现有代码无需修改
|
|
1216
|
-
- 🔒 通过 TypeScript 泛型确保类型安全
|
|
988
|
+
Issues and Pull Requests are welcome!
|
|
1217
989
|
|
|
1218
|
-
|
|
1219
|
-
- 新增 `BasePackage` 接口 - 所有套餐类型的基础接口
|
|
1220
|
-
- 新增 `BasePackageModalOptions<TPackage>` 接口 - 通用配置接口
|
|
1221
|
-
- `CreditPackage` 和 `GenericPackage` 现在继承自 `BasePackage`
|
|
990
|
+
---
|
|
1222
991
|
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
- 修复 bug 只需在基类中修改一处
|
|
1226
|
-
- 更清晰的职责分离(基类处理逻辑,子类处理 UI)
|
|
992
|
+
**Last Updated**: 2026-02-07
|
|
993
|
+
**SDK Version**: 0.9.0
|