核心 API 接口

要求

只整理 api 相关的改动,用于和前端人员对接使用。


异常处理系统优化

1. 统一异常处理机制

  • 变更范围: 所有 API 接口的错误响应
  • 主要改进:
    • 引入类型安全的 ErrorCode 枚举替代字符串错误码
    • 实现统一的异常处理架构,提供一致的错误响应格式
    • 新增具体异常类型:ValidationExceptionAuthorizationExceptionResourceNotFoundException

2. HTTP 状态码规范化

  • 验证错误: 统一返回 HTTP 400 状态码(之前部分接口返回 422)
  • 权限错误: 返回 HTTP 403 状态码
  • 资源未找到: 返回 HTTP 404 状态码

3. 错误响应格式

所有 API 错误响应现在遵循统一格式:

{
  "code": 50001,
  "message": "错误描述信息"
}

提现账户管理

1. 提现账户解绑

  • 接口:

    • POST /withdraw_accounts/unbind: 用于执行提现账户的解绑操作。
    • POST /withdraw_accounts/unbind_check: 新增接口,用于在解绑前预先检查是否满足条件。
    • POST /withdraw_accounts/delete: 此路由已被移除。
  • 作用: 允许用户解绑已绑定的提现账户,并提供了预检查功能以提升用户体验。

  • 请求参数 (unbindunbind_check):

字段名类型是否必须说明
idinteger要操作的提现账户 ID
  • 错误响应 (unbindunbind_check):
错误码名称说明
50001UserWithdrawAccountStripeBalanceNotZeroStripe 账户余额不为零
50002UserWithdrawAccountWalletBalanceNotZero钱包余额不为零
50003UserWithdrawAccountHasWorkTaskNotDone尚有未完成的工作任务
50004UserWithdrawStripeBalanceNotEnoughStripe 账户余额不足
50005UserWithdrawAccountNotFound提现账户未找到
50007UserWithdrawAccountNotBound提现账户未绑定
  • 主要逻辑与变更:
    • 前置检查: 解绑前会进行严格的安全检查,确保:
      • 关联钱包余额为零。
      • Stripe 账户余额为零。
      • 没有正在处理中的工作任务。
    • 错误处理: 优化了错误处理机制,当检查失败时,会返回包含明确 codemessage 的 JSON 响应。
    • 数据库操作: 检查通过后,操作会软删除提现账户记录并删除关联的钱包记录。
    • 逻辑优化: 将钱包余额、工作任务和 Stripe 余额检查逻辑封装为独立函数,提高了代码的可读性和维护性。增加了账户绑定状态检查,确保只有已绑定的账户才能进行解绑检查。
    • 修复: 修复了余额不足时的错误提示信息。

2. 提现账户列表查询

  • 接口: POST /withdraw_accounts/list
  • 作用: 增强了提现账户列表的筛选和关联数据查询能力。
  • 新增查询参数:
字段名类型是否必须说明
currency_idinteger根据货币 ID 筛选
stripe_service_agreementstring根据 Stripe 服务协议类型筛选 (full, recipient)
  • 返回数据变更:
    • 在每个提现账户对象中,新增了 wallet 字段,包含了完整的关联钱包信息。

3. Stripe Connect 账户创建

  • 接口: POST /stripe/create_connect_account_link
  • 作用: 创建 Stripe Connect 账户的链接,用于引导用户完成 Stripe 账户的注册或关联流程。
  • 新增请求参数:
字段名类型是否必须说明
callbackstring用户完成 Stripe 流程后重定向的 URL。
countrystring用户所在的国家代码 (例如: US)。
service_agreementstringStripe 服务协议类型,可选值为 fullrecipient
  • 主要逻辑与变更:
    • 参数验证: 对 callback, country, 和 service_agreement 进行验证。
    • 重复绑定检查: 防止用户重复绑定同类型的 Stripe 账户。
    • 清理未完成的账户: 自动删除未完成的绑定记录。
    • 动态创建账户: 根据 countryservice_agreement 创建不同能力的 Stripe 账户。
    • 安全增强: 使用带签名的回调 URL 和在生产环境强制 HTTPS。

4. 获取 Stripe 仪表板链接

  • 接口: GET /stripe/stripe_dashboard_link
  • 作用: 为用户生成一个登录到其 Stripe Express 账户仪表板的安全链接。
  • 请求参数:
字段名类型是否必须说明
withdraw_account_idinteger用户的提现账户 ID。
  • 主要逻辑:
    • 验证提现账户的归属和状态。
    • 调用 Stripe API 生成一次性的登录链接。

5. Stripe Connect 账户回调处理

  • 接口: GET /stripe/create_connect_account_return
  • 作用: 这是 Stripe Connect 账户创建流程完成后,Stripe 回调的接口。它负责处理 Stripe 返回的数据,更新用户提现账户的状态,并创建相应的钱包。
  • 请求参数:
字段名类型是否必须说明
account_idstringStripe Connect 账户的 ID。
callbackstring用户在发起 create_connect_account_link 时提供的回调 URL。
  • 主要逻辑:
    • 签名验证: 验证回调 URL 的签名,确保请求的合法性。
    • 账户查找与更新: 根据 account_id 查找对应的用户提现账户,并将其 bind_statusPending 更新为 Successed
    • 获取 Stripe 账户信息: 调用 Stripe API 获取完整的账户信息,包括默认货币和支持邮箱等。
    • 更新提现账户信息: 使用获取到的 Stripe 账户信息更新用户提现账户的 currency_idstripe_email 字段。
    • 创建用户钱包: 如果用户还没有对应货币的钱包,则会创建一个新的钱包。
    • 事务处理: 所有数据库操作都在事务中进行,确保数据一致性。
    • 修复: 确保在创建钱包后立即更新提现账户的 wallet_id 字段。

钱包管理

1. 钱包列表查询

  • 接口: POST /wallets/list
  • 作用: 在钱包列表中直接返回关联的提现账户信息。
  • 返回数据变更:
    • 在每个钱包对象中,新增了 withdrawAccount 字段,包含了已成功绑定的提现账户信息。

2. 钱包提现

  • 接口: POST /wallet_withdraws/create
  • 作用: 用户发起提现请求,将钱包余额提现到指定的提现账户。
  • 请求参数:
字段名类型是否必须说明
amountinteger提现金额(最小单位,例如美分)。
withdraw_account_idinteger用户的提现账户 ID。
passwordstring用户密码,用于安全验证。
  • 错误响应:
错误码名称说明
30003SystemUserPasswordError用户密码错误
50004UserWithdrawStripeBalanceNotEnough钱包余额不足
50005UserWithdrawAccountNotFound提现账户未找到
50009UserWithdrawWalletNotFound钱包未找到
50010UserWithdrawWalletNotOwned钱包不属于用户
  • 主要逻辑与变更:
    • 安全验证: 验证用户密码和提现账户的有效性。
    • 余额检查: 确保钱包有足够的余额进行提现。
    • 事务处理: 创建提现记录和钱包交易记录的操作在数据库事务中进行,确保数据一致性。
    • 错误处理: 使用统一的异常处理机制,返回标准化的错误响应格式。

3. Stripe 连接账户支付和转账

stripe_connect_payout

  • 接口: POST /wallet_withdraws/stripe_connect_payout
  • 作用: 用于处理 Stripe 连接账户的支付操作,即将资金从连接账户提现到关联的银行账户。
  • 请求参数:
字段名类型是否必须说明
withdraw_account_idinteger用户的提现账户 ID。
amountinteger提现金额(最小单位,例如美分)。
passwordstring用户密码,用于安全验证。
  • 主要逻辑:
    • 安全验证: 验证用户密码和提现账户的有效性。
    • 余额检查: 确保 Stripe 账户有足够的余额进行提现。
    • Stripe API 调用: 调用 Stripe 的 Payouts API 执行提现操作。
    • 错误处理: 如果 Stripe 账户余额不足,将返回 UserWithdrawStripeBalanceNotEnough (50004) 错误。

stripe_connect_transfer

  • 接口: POST /wallet_withdraws/stripe_connect_transfer
  • 作用: 用于处理 Stripe 连接账户的转账操作,即将资金从平台账户转账到连接账户。
  • 请求参数:
字段名类型是否必须说明
withdraw_account_idinteger用户的提现账户 ID。
amountinteger转账金额(最小单位,例如美分)。
passwordstring用户密码,用于安全验证。
  • 错误响应:
错误码名称说明
30003SystemUserPasswordError用户密码错误
50004UserWithdrawStripeBalanceNotEnough钱包余额不足
50005UserWithdrawAccountNotFound提现账户未找到
50006UserWithdrawAccountTypeInvalid提现账户类型必须为Stripe
50007UserWithdrawAccountNotBound提现账户未绑定成功
50008UserWithdrawAccountServiceAgreementInvalidStripe服务协议必须为recipient
50009UserWithdrawWalletNotFound钱包未找到
50010UserWithdrawWalletNotOwned钱包不属于用户
  • 主要逻辑:
    • 安全验证: 验证用户密码和提现账户的有效性。
    • 余额检查: 确保钱包有足够的余额进行转账。
    • Stripe验证: 验证Stripe账户类型、绑定状态和服务协议类型。
    • Stripe API 调用: 调用 Stripe 的 Transfers API 执行转账操作。
    • 错误处理: 使用统一的异常处理机制,返回标准化的错误响应格式。

邮箱验证码管理

1. API 接口重构

已废弃的独立接口:

  • POST /user/send_sign_up_code - 发送注册验证码 (已移除)
  • POST /user/verify_sign_up_code - 验证注册验证码 (已移除)
  • POST /user/send_forget_psw_code - 发送忘记密码验证码 (已移除)
  • POST /user/verify_forget_psw_code - 验证忘记密码验证码 (已移除)
  • POST /withdraw_accounts/send_email_code - 发送提现账户验证码 (已移除)
  • POST /user/send_change_email_code - 发送修改邮箱验证码 (已移除)

统一验证码接口:

  • POST /user/send_email_verify_code - 统一发送验证码接口
  • POST /user/verify_email_verify_code - 统一验证验证码接口

发送验证码接口 (send_email_verify_code)

  • 接口: POST /user/send_email_verify_code
  • 作用: 根据不同业务场景向指定邮箱发送验证码
  • 认证要求: 无需登录(公开接口)

请求参数:

字段名类型是否必须说明
emailstring邮箱地址,需符合email格式
typestring验证码类型,根据登录状态不同有不同可选值

type字段可选值:

  • 未登录用户: sign_up (注册), forget_psw (忘记密码)
  • 已登录用户: manage_withdraw_account (管理提现账户), change_email_org (原邮箱验证), change_email_new (新邮箱验证)

成功响应:

{
    "ok": true
}

验证验证码接口 (verify_email_verify_code)

  • 接口: POST /user/verify_email_verify_code
  • 作用: 验证用户输入的验证码是否正确
  • 认证要求: 无需登录(公开接口)

请求参数:

字段名类型是否必须说明
emailstring邮箱地址,需符合email格式
codestring6位数字验证码
typestring验证码类型(与发送时保持一致)

type字段可选值:(与发送接口相同)

  • 未登录用户: sign_up (注册), forget_psw (忘记密码)
  • 已登录用户: manage_withdraw_account (管理提现账户), change_email_org (原邮箱验证), change_email_new (新邮箱验证)

成功响应:

{
    "ok": true
}

2. 业务流程整合

注册流程:

  • 调用统一验证码接口发送和验证
  • POST /user/sign_up 中直接使用 EmailVerifyCodeService::use() 方法标记验证码为已使用

密码重置流程:

  • 调用统一验证码接口发送和验证
  • POST /user/forget_psw_change 中直接使用 EmailVerifyCodeService::use() 方法标记验证码为已使用

提现账户管理流程:

  • 调用统一验证码接口发送和验证
  • POST /withdraw_accounts/create 中先验证再使用:verify()use()

修改邮箱流程:

  • 分为两步验证:原邮箱验证(change_email_org)和新邮箱验证(change_email_new)
  • POST /user/change_email 中直接验证和使用新邮箱验证码:verify()use()
  • 使用统一验证码接口替代原有的独立修改邮箱验证码接口

3. 邮箱验证逻辑优化

发送验证码时的邮箱状态检查:

  • 注册验证码 (sign_up) 和 新邮箱验证码 (change_email_new): 检查邮箱是否已存在,存在则抛出 SystemEmailVerifyEmailExists 错误
  • 忘记密码验证码 (forget_psw): 检查邮箱是否存在,不存在则抛出 SystemEmailVerifyEmailNotFound 错误
  • 原邮箱验证码 (change_email_org) 和 提现账户验证码 (manage_withdraw_account): 无需邮箱状态检查

修改邮箱接口优化 (POST /user/change_email):

  • 移除了原有的独立发送验证码逻辑,统一使用 EmailVerifyCodeService
  • 简化了验证流程,直接验证和使用新邮箱验证码
  • 优化了错误处理,使用统一的异常处理机制

4. 安全机制与限制

  • 验证码格式: 6位随机数字(100000-999999)
  • 有效期: 1小时过期时间
  • 频率限制: 单个邮箱+验证类型组合2分钟内最多验证10次
  • 唯一性: 每次发送新验证码会自动删除该邮箱同类型的旧验证码
  • 状态管理: 验证码状态流转 SENTVERIFIEDUSED
  • 数据库事务: 确保验证码创建和清理的原子性操作

5. 实现优化

  • 竞态条件修复: 使用数据库事务确保验证码创建和旧验证码清理的原子性
  • 数据一致性: 先创建新验证码,再删除同类型旧验证码,避免并发导致的数据不一致
  • 记录使用时间: 新增 used_at 字段记录验证码使用时间
  • 防刷保护: 验证失败次数限制和缓存机制

6. 错误响应

错误码名称说明
30001SystemCaptchaError验证码错误
30004SystemEmailVerifyCodeNotFound验证码不存在
30005SystemEmailVerifyCodeExpired验证码已过期
30006SystemEmailSendError邮件发送失败
30007SystemEmailVerifyCodeAttemptsLimit验证尝试次数过多,请稍后再试
30008SystemEmailVerifyEmailExists邮箱已存在
30009SystemEmailVerifyEmailNotFound邮箱未找到

7. 数据库优化

  • 新增字段: used_at 时间戳字段记录验证码使用时间
  • 索引优化:
    • idx_email_type_status: 复合索引用于查询特定状态的验证码
    • idx_email_type_code: 复合索引用于验证码校验
    • idx_expired_at: 单字段索引用于清理过期数据

Model 定义

UserWithdrawAccount (用户提现账户)

  • 表名: user_withdraw_accounts
  • 主要字段:
    • id: integer, 主键
    • user_id: integer, 用户 ID
    • type: enum (UserWithdrawAccountType), 提现账户类型 (例如: Alipay, Stripe)
    • bind_status: enum (UserWithdrawAccountStatus), 绑定状态 (例如: Successed, Pending, Unbound)
    • currency_id: integer, 关联的货币 ID
    • alipay_account: string, 支付宝账号 (如果 type 是 Alipay)
    • alipay_name: string, 支付宝姓名 (如果 type 是 Alipay)
    • stripe_connect_account_id: string, Stripe Connect 账户 ID (如果 type 是 Stripe)
    • stripe_service_agreement: enum (UserWithdrawStripeServiceAgreement), Stripe 服务协议类型 (例如: Full, Recipient)
    • stripe_email: string, Stripe 账户邮箱
    • unbound_at: datetime, 解绑时间 (软删除时记录)
    • deleted_at: datetime, 软删除时间
    • stripe_balance: object, Stripe 账户余额信息 (通过 UserWithdrawAccount 模型中的 stripe_balance 属性获取)
  • 关联关系:
    • user(): 属于 User 模型 (多对一)
    • currency(): 属于 Currency 模型 (多对一)
    • wallet(): 属于 Wallet 模型 (多对一)

Wallet (钱包)

  • 表名: wallets
  • 主要字段:
    • id: integer, 主键
    • user_id: integer, 用户 ID
    • currency_id: integer, 关联的货币 ID
    • balance: decimal, 余额
    • usage: enum (WalletUsage), 钱包用途
    • deposit_type: enum (WalletDepositType), 存款类型
    • stripe_connect_account_id: string, Stripe Connect 账户 ID (如果关联 Stripe)
    • deleted_at: datetime, 软删除时间
  • 关联关系:
    • user(): 属于 User 模型 (多对一)
    • currency(): 属于 Currency 模型 (多对一)
    • transactions(): 拥有多个 WalletTransaction (一对多)
    • withdrawAccounts(): 拥有多个 UserWithdrawAccount (一对多)
    • withdrawAccount(): 拥有一个 UserWithdrawAccount (一对一,且 bind_statusSuccessed)

Currency (货币)

  • 表名: currencies
  • 主要字段:
    • id: integer, 主键
    • code: string, 货币代码 (例如: USD, CNY)
    • symbol: string, 货币符号
    • name: string, 货币名称
  • 辅助属性:
    • is_zero_decimal: boolean, 是否是零小数货币 (例如: 日元)
    • is_can_withdraw: boolean, 是否可提现货币
    • is_default_withdraw: boolean, 是否默认提现货币

枚举 (Enums) 定义

UserWithdrawAccountType (用户提现账户类型)

  • 类型: string
  • 可能值:
    • alipay: 支付宝
    • stripe: Stripe

UserWithdrawAccountStatus (用户提现账户状态)

  • 类型: string
  • 可能值:
    • pending: 待处理
    • successed: 成功
    • failed: 失败
    • unbound: 已解绑

UserWithdrawStripeServiceAgreement (用户提现 Stripe 服务协议)

  • 类型: string
  • 可能值:
    • full: 完整服务协议
    • recipient: 收款人服务协议

WalletUsage (钱包用途)

  • 类型: string
  • 可能值:
    • deposit: 艺术家收款钱包,用于提现
    • credit: 用户礼品卡,仅用于支付抵扣
    • plat_fee: 艺术家平台手续费,仅用于抵扣平台手续费

WalletDepositType (钱包存款类型)

  • 类型: string
  • 可能值:
    • alipay: 支付宝
    • stripe_full: Stripe 完整服务协议
    • stripe_recipient: Stripe 收款人服务协议

ErrorCode (错误码)

  • 类型: int
错误码名称中文描述
10001ChatMessageNeedReceiverReturnMessage聊天消息需要接收者回复消息
10002ChatMessageUndoTimeLimit聊天消息撤回时间限制
20001WorkTaskHasPayingOrder工作任务有正在支付的订单
20002WorkTaskNoUnpaidStage工作任务没有未支付的阶段
30001SystemCaptchaError验证码错误
30002SystemError系统错误
30003SystemUserPasswordError用户密码错误
30004SystemEmailVerifyCodeNotFound验证码不存在
30005SystemEmailVerifyCodeExpired验证码已过期
30006SystemEmailSendError邮件发送失败
30007SystemEmailVerifyCodeAttemptsLimit验证尝试次数过多,请稍后再试
30008SystemEmailVerifyEmailExists邮箱已存在
30009SystemEmailVerifyEmailNotFound邮箱未找到
35001BusinessLogicError业务逻辑错误
40002GroupMessageUndoTimeLimit群组消息撤回时间限制
40003GroupReminderLimit群组提醒限制
40004GroupReminderExistInvalidUser群组提醒存在无效用户
50001UserWithdrawAccountStripeBalanceNotZeroStripe账户余额不为零
50002UserWithdrawAccountWalletBalanceNotZero钱包余额不为零
50003UserWithdrawAccountHasWorkTaskNotDone尚有未完成的工作任务
50004UserWithdrawStripeBalanceNotEnough余额不足
50005UserWithdrawAccountNotFound提现账户未找到
50006UserWithdrawAccountTypeInvalid提现账户类型无效
50007UserWithdrawAccountNotBound提现账户未绑定
50008UserWithdrawAccountServiceAgreementInvalidStripe服务协议无效
50009UserWithdrawWalletNotFound钱包未找到
50010UserWithdrawWalletNotOwned钱包不属于用户