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("手动扣费文档创建成功") }