Files
kami_backend/.qoder/repowiki/zh/content/业务逻辑层架构/业务逻辑层架构.md
danial 96ed936079 docs(api): 添加详细Apple卡密管理API文档
- 新增API端点参考文档,涵盖权限、卡密、订单、商户、监控、限制等模块
- 详细说明Apple卡密充值处理流程,包括提交、查询、回调和轮询接口
- 描述充值订单状态机及生命周期,支持超时重试和状态迁移
- 介绍签名验证、幂等控制及重复卡密防刷单策略
- 增加商户配置管理、历史记录查询和错误处理机制说明
- 提供API使用示例代码及客户端实现指导
- 删除过时的.drone.yml.bak文件,清理无用配置
- 添加.dockerignore忽略指定目录和文件
2025-10-08 20:13:40 +08:00

16 KiB
Raw Blame History

业务逻辑层架构

**本文档中引用的文件** - [main.go](file://main.go) - [logic.go](file://internal/logic/logic.go) - [sys_user.go](file://internal/service/sys_user.go) - [sys_user.go](file://internal/dao/v_1_sys_user.go) - [sys_user.go](file://internal/model/sys_user.go) - [sys_user.go](file://internal/logic/sys_user/sys_user.go) - [card_apple_order.go](file://internal/logic/card_apple_order/order.go) - [card_redeem_order.go](file://internal/logic/card_redeem_order/order.go) - [merchant_order.go](file://internal/logic/merchant_order/order.go) - [restriction.go](file://internal/logic/restriction/restriction.go) - [card_t_mall_order.go](file://internal/logic/card_t_mall_order/order.go) - [card_apple_order.go](file://internal/service/card_apple_order.go) - [card_redeem_order.go](file://internal/service/card_redeem_order.go) - [merchant_order.go](file://internal/service/merchant_order.go) - [restriction.go](file://internal/service/restriction.go) - [card_t_mall_order.go](file://internal/service/card_t_mall_order.go) - [config.yaml](file://manifest/config/config.yaml)

目录

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构概述
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排除指南
  9. 结论

引言

kami_backend 是一个用于管理卡密充值、订单处理和账户管理的后端服务系统。该系统采用分层架构设计,包含 controller、service 和 logic 三层,分别负责请求处理、业务逻辑和数据访问。系统支持多种卡密类型,包括 Apple、京东、沃尔玛等并提供了灵活的配置和扩展机制。本文档旨在描述该系统的业务逻辑层架构包括高阶设计、架构模式、系统边界、核心业务流程、组件交互、数据流、集成模式、技术决策、基础设施要求、可扩展性考虑、部署拓扑、安全性、监控和灾难恢复等横切关注点。

项目结构

kami_backend 项目采用模块化设计,主要分为 api、internal、manifest、utility 等目录。api 目录包含各业务模块的 API 定义internal 目录包含核心业务逻辑manifest 目录包含部署配置utility 目录包含工具类和辅助功能。

graph TD
subgraph "API层"
A[api/authority]
B[api/card_info_apple]
C[api/card_info_jd]
D[api/card_info_walmart]
E[api/order]
F[api/sysUser]
end
subgraph "内部层"
G[internal/controller]
H[internal/service]
I[internal/logic]
J[internal/dao]
K[internal/model]
end
subgraph "工具层"
L[utility/config]
M[utility/integration]
N[utility/monitor]
end
A --> G
B --> G
C --> G
D --> G
E --> G
F --> G
G --> H
H --> I
I --> J
J --> K
L --> H
M --> I
N --> H

图源

核心组件

kami_backend 的核心组件包括用户管理、卡密充值、订单处理、权限控制等。用户管理组件负责用户账户的创建、修改、删除和权限分配。卡密充值组件支持多种卡密类型,包括 Apple、京东、沃尔玛等提供卡密的充值、查询、回调等功能。订单处理组件负责订单的创建、查询、状态更新和统计。权限控制组件基于 Casbin 实现,支持基于角色的访问控制。

组件源

架构概述

kami_backend 采用典型的三层架构,包括 controller、service 和 logic 层。controller 层负责接收和处理 HTTP 请求,调用 service 层提供的接口。service 层是业务逻辑的核心,封装了具体的业务规则和流程,调用 logic 层进行数据访问和处理。logic 层负责与数据库交互,执行 CRUD 操作,并提供数据访问的抽象。

graph TD
A[客户端] --> B[Controller]
B --> C[Service]
C --> D[Logic]
D --> E[DAO]
E --> F[数据库]

图源

详细组件分析

用户管理组件分析

用户管理组件负责用户账户的全生命周期管理,包括创建、修改、删除、查询和权限分配。该组件基于 GoFrame 框架实现,使用 MySQL 作为持久化存储。

类图

classDiagram
class SysUser {
+string Id
+string Username
+int IsAdmin
+string Phone
+*gtime.Time CreatedAt
+*gtime.Time UpdatedAt
+*gtime.Time DeletedAt
+GetCasBinUserPrefix() string
+NotCheckAuthAdminIds(ctx context.Context) *gset.Set
+GetAdminUserByUsernamePassword(ctx context.Context, req *model.UserLoginInput) (user *model.LoginUserOutput, err error)
+GetUserByUsername(ctx context.Context, userName string) (sysUser *model.LoginUserOutput, err error)
+GetUserById(ctx context.Context, id string) (sysUser *model.LoginUserOutput, err error)
+LoginLog(ctx context.Context, params *model.LoginLogParams)
+GetAdminRules(ctx context.Context, userId string) (menuList []*model.UserMenus, permissions []string, err error)
+GetAdminRole(ctx context.Context, userId string, allRoleList []*entity.V1SysRole) (roles []*entity.V1SysRole, err error)
+GetAdminRoleIds(ctx context.Context, userId string) (roleIds []uint, err error)
+GetAllMenus(ctx context.Context) (menus []*model.UserMenus, err error)
+GetAdminMenusByRoleIds(ctx context.Context, roleIds []uint) (menus []*model.UserMenus, err error)
+GetMenusTree(menus []*model.UserMenus, pid uint) []*model.UserMenus
+GetPermissions(ctx context.Context, roleIds []uint) (userButtons []string, err error)
+List(ctx context.Context, req *model.UserSearchInput) (total int, userList []*entity.V1SysUser, err error)
+GetByUserName(ctx context.Context, username string) (userList []*entity.V1SysUser, err error)
+ListWithPayment(ctx context.Context, req *model.UserSearchInput) (total int, userList []*model.UserSearchWithPaymentOutput, err error)
+Add(ctx context.Context, req *model.UserAddInput) (userId string, err error)
+Edit(ctx context.Context, req *model.UserEditInput) (err error)
+EditUserRole(ctx context.Context, roleIds []int64, userId int64) (err error)
+UserNameOrMobileExists(ctx context.Context, userName string, id ...string) (isExist bool, err error)
+GetEditUser(ctx context.Context, id string) (res *model.UserGetEditOutput, err error)
+GetUserInfoById(ctx context.Context, id string, withPwd ...bool) (user *entity.V1SysUser, err error)
+ChangePwd(ctx context.Context, input *model.UserChangePwdInput) (err error)
+ChangeUserStatus(ctx context.Context, input *model.UserStatusInput) (err error)
+DeleteById(ctx context.Context, id string) (err error)
+Delete(ctx context.Context, ids []string) (err error)
+GetUsers(ctx context.Context, ids []string) (users []*model.SysUserSimpleOutput, err error)
+GetUsersAll(ctx context.Context) (users []*model.SysUserSimpleOutput, err error)
+GetUserFromToken(ctx context.Context) (needAuth bool, user *entity.V1SysUser, err error)
+CheckUserNormal(ctx context.Context, userId string) (isNormal bool, err error)
+GetAllUserNormal(ctx context.Context, tx gdb.TX) (user []*entity.V1SysUser, err error)
+GetAllSimpleUser(ctx context.Context) (data []model.UserSimpleUsersOutput, err error)
+GetCurrentOneFromCache(ctx context.Context, channelName consts.CardRedeemAccountCategory) (data *entity.V1SysUser, err error)
+GetOneNormalOneWithPayment(ctx context.Context, userId string, tx gdb.TX) (output *model.UserSearchWithPaymentOutput, err error)
+GetAllNormalWithPayment(ctx context.Context, minAmount float64, tx gdb.TX) (output []*model.UserSearchWithPaymentOutput, err error)
+GetAllNormalWithPaymentAndChannelCfg(ctx context.Context, minAmount float64, tx gdb.TX) (output []*model.UserSearchWithPaymentAndCfgOutput, err error)
+GetNextOne(ctx context.Context, userId string, amount float64, isNext bool, tx gdb.TX) (data *entity.V1SysUser, err error)
+SetTotp(ctx context.Context, data *entity.V1SysUser, key string, secret string) (err error)
+ResetTotp(ctx context.Context, data *entity.V1SysUser) (err error)
}
class SysUserDao {
+V1SysUser *v1SysUserDao
+Get(ctx context.Context, id string) (*entity.V1SysUser, error)
+Create(ctx context.Context, user *entity.V1SysUser) error
+Update(ctx context.Context, user *entity.V1SysUser) error
+Delete(ctx context.Context, id string) error
}
class SysUserModel {
+User *model.User
+UserSearchInput *model.UserSearchInput
+UserSearchWithPaymentOutput *model.UserSearchWithPaymentOutput
+UserSearchWithPaymentAndCfgOutput *model.UserSearchWithPaymentAndCfgOutput
+UserAddInput *model.UserAddInput
+UserEditInput *model.UserEditInput
+UserGetEditOutput *model.UserGetEditOutput
+UserChangePwdInput *model.UserChangePwdInput
+UserStatusInput *model.UserStatusInput
+SysUserSimpleOutput *model.SysUserSimpleOutput
+UserLoginOutInput *model.UserLoginOutInput
+LoginUserOutput *model.LoginUserOutput
+UserLoginOutOutput *model.UserLoginOutOutput
+UserSimpleUsersOutput *model.UserSimpleUsersOutput
}
SysUser --> SysUserDao : "uses"
SysUser --> SysUserModel : "uses"
SysUserDao --> SysUserModel : "returns"

图源

卡密充值组件分析

卡密充值组件支持多种卡密类型,包括 Apple、京东、沃尔玛等提供卡密的充值、查询、回调等功能。该组件基于 GoFrame 框架实现,使用 MySQL 作为持久化存储。

序列图

sequenceDiagram
participant Client as "客户端"
participant Controller as "Controller"
participant Service as "Service"
participant Logic as "Logic"
participant DAO as "DAO"
participant DB as "数据库"
Client->>Controller : POST /api/card_info_apple/v1/recharge_submit
Controller->>Service : AddRechargeOrder(input)
Service->>Logic : AddRechargeOrder(input)
Logic->>DAO : InsertAndGetId(do.V1CardAppleRechargeInfo)
DAO->>DB : INSERT INTO v1_card_apple_recharge_info
DB-->>DAO : 返回ID
DAO-->>Logic : 返回ID
Logic->>DAO : Insert(do.V1CardAppleHistoryInfo)
DAO->>DB : INSERT INTO v1_card_apple_history_info
DB-->>DAO : 返回结果
DAO-->>Logic : 返回结果
Logic-->>Service : 返回订单号
Service-->>Controller : 返回订单号
Controller-->>Client : 返回订单号

图源

订单处理组件分析

订单处理组件负责订单的创建、查询、状态更新和统计。该组件基于 GoFrame 框架实现,使用 MySQL 作为持久化存储。

流程图

flowchart TD
Start([开始]) --> ValidateInput["验证输入参数"]
ValidateInput --> InputValid{"输入有效?"}
InputValid --> |否| ReturnError["返回错误响应"]
InputValid --> |是| CheckOrder["检查订单是否存在"]
CheckOrder --> OrderExists{"订单存在?"}
OrderExists --> |是| UpdateOrder["更新订单状态"]
OrderExists --> |否| CreateOrder["创建新订单"]
CreateOrder --> SaveOrder["保存订单到数据库"]
SaveOrder --> UpdateStatus["更新订单状态"]
UpdateStatus --> ReturnResult["返回结果"]
UpdateOrder --> ReturnResult
ReturnResult --> End([结束])
ReturnError --> End

图源

权限控制组件分析

权限控制组件基于 Casbin 实现,支持基于角色的访问控制。该组件负责用户权限的验证和管理。

类图

classDiagram
class Restriction {
+GetAllProvince(ctx context.Context) []string
+CheckIPIsAllowed(ctx context.Context, ip string, area []string) (isAllowed bool, err error)
+AddToRestrictIP(ctx context.Context, input model.AddRestrictionRecordInput) (err error)
+SetCurrentOrderDisable(ctx context.Context, orderNo string, status consts.RestrictStatus, tx gdb.TX) (err error)
+GetLocationWithProxyByIP(ctx context.Context, ip string) (data *model.RestrictionIPRecordOutput, err error)
+IsInProvince(ctx context.Context, ip string, province []string) (isin bool, m *model.RestrictionIPRecordOutput, err error)
+GetRestrictRecordByCardPass(ctx context.Context, cardPass string) (dataList []entity.V1RestrictIpOrderAccess, err error)
+GetRestrictRecordByIP(ctx context.Context, ip string) (dataList []model.RestrictWithIPRecordOutput, err error)
+GetIPOrderAccessByCardPass(ctx context.Context, cardPass string) (data []entity.V1RestrictIpOrderAccess, err error)
+IsRestrictExistByCardPass(ctx context.Context, cardPass string) (isExist bool)
+IsRestrictExistByIP(ctx context.Context, ip string) (isExist bool)
+IsRestrictDevice(ctx context.Context, deviceId string) (isRestrict bool)
}
class RestrictionDao {
+V1RestrictIpRecord *v1RestrictIpRecordDao
+V1RestrictIpOrderAccess *v1RestrictIpOrderAccessDao
+GetOrSetIPRecord(ctx context.Context, ip string, tx gdb.TX) (m *model.RestrictionIPRecordOutput, err error)
+GetRestrictRecordByCardPass(ctx context.Context, cardPass string) (dataList []entity.V1RestrictIpOrderAccess, err error)
+GetRestrictRecordByIP(ctx context.Context, ip string) (dataList []model.RestrictWithIPRecordOutput, err error)
+GetIPOrderAccessByCardPass(ctx context.Context, cardPass string) (data []entity.V1RestrictIpOrderAccess, err error)
}
class RestrictionModel {
+AddRestrictionRecordInput *model.AddRestrictionRecordInput
+RestrictionIPRecordOutput *model.RestrictionIPRecordOutput
+RestrictWithIPRecordOutput *model.RestrictWithIPRecordOutput
}
Restriction --> RestrictionDao : "uses"
Restriction --> RestrictionModel : "uses"
RestrictionDao --> RestrictionModel : "returns"

图源

依赖分析

kami_backend 依赖于多个外部组件和库,包括 GoFrame 框架、MySQL 数据库、Redis 缓存、OpenTelemetry 监控系统等。GoFrame 框架提供了 Web 服务、数据库访问、配置管理等基础功能。MySQL 数据库用于持久化存储用户、订单、卡密等数据。Redis 缓存用于提高系统性能减少数据库访问压力。OpenTelemetry 监控系统用于收集和分析系统运行时的性能数据。

graph TD
A[kami_backend] --> B[GoFrame]
A --> C[MySQL]
A --> D[Redis]
A --> E[OpenTelemetry]
B --> F[gin]
B --> G[gorm]
C --> H[InnoDB]
D --> I[内存存储]
E --> J[Jaeger]
E --> K[Prometheus]

图源

性能考虑

kami_backend 在设计时充分考虑了性能因素,采用了多种优化措施。首先,系统使用 Redis 缓存热点数据,如用户信息、配置信息等,减少数据库访问次数。其次,系统采用连接池技术,复用数据库连接,减少连接创建和销毁的开销。此外,系统还使用了异步处理机制,将耗时操作放入后台任务队列中执行,提高响应速度。最后,系统通过 OpenTelemetry 监控系统实时监控性能指标,及时发现和解决性能瓶颈。

故障排除指南

当 kami_backend 出现问题时,可以按照以下步骤进行排查:

  1. 检查系统日志,查看是否有错误信息。
  2. 检查数据库连接是否正常,是否有慢查询。
  3. 检查 Redis 缓存是否正常,是否有缓存穿透或雪崩。
  4. 检查 OpenTelemetry 监控系统,查看性能指标是否异常。
  5. 检查配置文件,确认配置项是否正确。
  6. 如果问题仍然无法解决,可以联系技术支持团队。

组件源

结论

kami_backend 是一个功能完善、性能优良的后端服务系统。通过采用分层架构设计,系统实现了良好的模块化和可维护性。通过使用多种优化措施,系统能够高效地处理大量并发请求。通过集成 OpenTelemetry 监控系统,系统具备了强大的可观测性。未来,系统可以进一步优化性能,增加更多功能,提高用户体验。