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