Initial commit: 网络验证平台

This commit is contained in:
Admin
2026-04-27 17:22:56 +08:00
commit afe67d704e
780 changed files with 88960 additions and 0 deletions
+349
View File
@@ -0,0 +1,349 @@
package main
import (
"log"
"verification-platform-backend/internal/database"
"verification-platform-backend/internal/model"
)
func main() {
database.Init()
docContent := `# 手动扣费 API
## 概述
手动扣费功能允许开发者在余额模式下,通过 API 自行控制扣费时机和金额。这为开发者提供了最大的灵活性,可以根据业务需求实现自定义的计费逻辑。
## 前提条件
1. 应用的运营模式必须设置为**余额模式**
2. 扣费方式必须设置为**手动扣费**
## 扣费方式说明
扣费方式分为两级选择:
### 第一级:扣费方式
| 方式 | 说明 |
|------|------|
| 自动扣费 | 系统自动触发扣费 |
| 手动扣费 | 通过 API 自行控制扣费 |
### 第二级:自动扣费类型(仅自动扣费时显示)
| 类型 | 说明 |
|------|------|
| 登录扣费 | 每次登录验证时扣费 |
| 计时扣费 | 按设定的时间间隔自动扣费 |
### 计时扣费配置
选择计时扣费后,可自定义扣费间隔:
- **间隔值**1-9999 之间的整数
- **时间单位**:分钟、小时、天
例如:设置为 "每 30 分钟扣费一次" 或 "每 2 小时扣费一次"
## 接口详情
### 请求地址
POST /api/v1/dev/applications/:id/deduct
### 请求头
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| Authorization | string | 是 | Bearer {token},开发者登录后获取的令牌 |
| Content-Type | string | 是 | application/json |
### 路径参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | integer | 是 | 应用ID |
### 请求参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| user_id | integer | 是 | 要扣费的用户ID |
| amount | number | 是 | 扣费金额,必须大于0 |
| description | string | 否 | 扣费描述/原因 |
### 请求示例
` + "```json" + `
{
"user_id": 123,
"amount": 10.5,
"description": "使用高级功能扣费"
}
` + "```" + `
### 响应示例
#### 成功响应
` + "```json" + `
{
"code": 200,
"message": "success",
"data": {
"user_id": 123,
"username": "testuser",
"amount": 10.5,
"balance_before": 100.5,
"balance_after": 90.0,
"description": "使用高级功能扣费",
"message": "扣费成功"
}
}
` + "```" + `
#### 错误响应
**应用不存在**
` + "```json" + `
{
"code": 404,
"message": "应用不存在"
}
` + "```" + `
**非余额模式**
` + "```json" + `
{
"code": 400,
"message": "只有余额模式的应用才支持手动扣费"
}
` + "```" + `
**未开启手动扣费**
` + "```json" + `
{
"code": 400,
"message": "该应用未开启手动扣费模式,请先在设置中修改扣费频率为手动扣费"
}
` + "```" + `
**用户不存在**
` + "```json" + `
{
"code": 404,
"message": "用户不存在"
}
` + "```" + `
**余额不足**
` + "```json" + `
{
"code": 400,
"message": "用户余额不足,当前余额: 5.00,需扣除: 10.50"
}
` + "```" + `
**永久会员**
` + "```json" + `
{
"code": 400,
"message": "该用户为永久会员,无法扣费"
}
` + "```" + `
## 使用场景
### 1. 按次计费
用户每次使用特定功能时扣费:
` + "```javascript" + `
// 用户使用高级分析功能
async function useAdvancedAnalysis(userId) {
const response = await fetch('/api/v1/dev/applications/1/deduct', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
amount: 5.0,
description: '使用高级分析功能'
})
});
const result = await response.json();
if (result.code === 200) {
// 扣费成功,执行功能
return true;
} else {
// 扣费失败,提示用户
alert(result.message);
return false;
}
}
` + "```" + `
### 2. 阶梯计费
根据使用量阶梯定价:
` + "```javascript" + `
function calculatePrice(usage) {
if (usage <= 100) {
return 1.0; // 前100次,每次1元
} else if (usage <= 500) {
return 0.8; // 101-500次,每次0.8元
} else {
return 0.5; // 500次以上,每次0.5元
}
}
async function chargeUser(userId, currentUsage) {
const price = calculatePrice(currentUsage);
// 调用扣费API...
}
` + "```" + `
### 3. 动态定价
根据时间段或活动动态调整价格:
` + "```javascript" + `
function getDynamicPrice() {
const hour = new Date().getHours();
const dayOfWeek = new Date().getDay();
// 周末打折
if (dayOfWeek === 0 || dayOfWeek === 6) {
return 5.0 * 0.8;
}
// 深夜时段打折
if (hour >= 22 || hour < 6) {
return 5.0 * 0.5;
}
return 5.0;
}
` + "```" + `
### 4. 批量扣费
对多个用户批量扣费:
` + "```javascript" + `
async function batchDeduct(users) {
const results = [];
for (const user of users) {
try {
const response = await fetch('/api/v1/dev/applications/1/deduct', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: user.id,
amount: user.amount,
description: user.description
})
});
const result = await response.json();
results.push({
user_id: user.id,
success: result.code === 200,
message: result.message
});
} catch (error) {
results.push({
user_id: user.id,
success: false,
message: error.message
});
}
}
return results;
}
` + "```" + `
## 注意事项
1. **余额检查**: 调用扣费接口前,建议先检查用户余额是否充足
2. **幂等性**: 如果业务需要保证幂等性,请在业务层实现去重逻辑
3. **并发控制**: 高并发场景下,建议使用锁机制防止余额扣成负数
4. **记录保存**: 每次扣费都会自动创建消费记录,可在后台查看
5. **错误处理**: 请妥善处理各种错误情况,给用户友好的提示
## 与自动扣费的区别
| 特性 | 手动扣费 | 自动扣费 |
|------|----------|----------|
| 扣费时机 | 开发者自行控制 | 系统自动执行 |
| 扣费金额 | 每次可不同 | 固定金额 |
| 灵活性 | 高 | 低 |
| 实现复杂度 | 需要开发者实现 | 无需开发 |
| 适用场景 | 复杂计费逻辑 | 简单按时/按次计费 |
## 相关接口
- [获取用户信息](/docs/app-api-docs#获取账户信息) - 查询用户当前余额
- [用户充值](/docs/app-api-docs#卡密充值) - 用户通过卡密充值
- [消费记录](/docs/finance) - 查看扣费记录`
var devCategory model.DocCategory
if err := database.DB.Where("slug = ?", "dev-docs").First(&devCategory).Error; err != nil {
devCategory = model.DocCategory{
Name: "开发者文档",
Slug: "dev-docs",
Description: "开发者API接口文档",
Sort: 90,
}
if err := database.DB.Create(&devCategory).Error; err != nil {
log.Printf("创建开发者文档分类失败: %v", err)
return
}
}
var existingDoc model.Doc
if err := database.DB.Where("slug = ?", "manual-deduct-api").First(&existingDoc).Error; err == nil {
existingDoc.Content = docContent
if err := database.DB.Save(&existingDoc).Error; err != nil {
log.Printf("更新手动扣费文档失败: %v", err)
} else {
log.Println("手动扣费文档更新成功")
}
return
}
doc := model.Doc{
Title: "手动扣费 API",
CategoryID: &devCategory.ID,
Slug: "manual-deduct-api",
Content: docContent,
Summary: "余额模式下通过API自行控制扣费时机和金额,支持按次计费、阶梯计费、动态定价等场景",
Icon: "💳",
Sort: 10,
Status: "published",
}
if err := database.DB.Create(&doc).Error; err != nil {
log.Printf("创建手动扣费文档失败: %v", err)
return
}
log.Println("手动扣费文档创建成功")
}