Files
kami_backend/.qoder/repowiki/zh/content/业务逻辑层架构/业务逻辑层架构.md
danial 2253dc739a feat(jd-cookie):优化订单创建逻辑与状态管理- 新增订单状态 OrderStatusJDOrderFailed用于标识京东订单获取失败
- 新增订单变更类型 OrderChangeTypeJDOrderFailed 用于记录下单失败事件
- 调整订单创建逻辑,支持失败订单重试机制
- 新增 RecordOrderHistoryReq 结构体统一记录订单变更历史参数
- 修改数据库表结构,优化字段类型和索引
- 更新订单创建逻辑,分离本地订单与京东订单创建流程- 增加失败订单重新创建京东订单的处理逻辑
- 调整订单状态检查逻辑,支持更多状态处理
-优化订单历史记录方式,增加备注信息支持
- 更新数据库字符集为 utf8mb4_unicode_ci 提升兼容性
2025-10-18 23:41:31 +08:00

19 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) - [order.go](file://internal/logic/jd_cookie/order.go) - *在提交77aff4289e7b60617a6b97873721f586af264581中更新* - [jd_cookie.go](file://internal/service/jd_cookie.go) - *在提交0fdae6a89fef78f6368400b1fe726d987adda7b1中更新* - [order_create.go](file://internal/logic/jd_cookie/order_create.go) - *在提交bc2d58753b8fe0b4f7150657bf40cfe756ce48de中重构* - [order_utils.go](file://internal/logic/jd_cookie/order_utils.go) - *在提交8bc2d51c8ba46582286270b3dd85e166f2562e51中优化* - [order_jd.go](file://internal/logic/jd_cookie/order_jd.go) - *在提交d1b7f907caa0c3c59628241250901cb7239b25a8中新增功能*

更新摘要

已做更改

  • 更新了京东Cookie订单创建和支付链接刷新功能的文档
  • 增加了京东Cookie账户变更历史记录功能的说明
  • 修订了京东Cookie相关组件的序列图和流程描述
  • 更新了受影响文件的引用来源标记
  • 新增了京东订单支付状态定时检查与卡密提取功能的文档
  • 更新了订单创建逻辑的并发控制机制说明

目录

  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)
+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

图源

京东Cookie组件分析

京东Cookie组件负责京东订单的创建、支付链接刷新以及Cookie账户的管理。根据最新的代码变更该组件已重构了订单创建和支付流程的错误处理机制并增加了Cookie变更历史记录功能。

序列图

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/jd_cookie/v1/create_order
Controller->>Service : CreateOrder(input)
Service->>Logic : CreateOrder(input)
Logic->>DAO : InsertAndGetId(do.V1JdCookieOrder)
DAO->>DB : INSERT INTO v1_jd_cookie_order
DB-->>DAO : 返回订单ID
DAO-->>Logic : 返回订单ID
Logic->>DAO : Insert(do.V1JdCookieOrderChangeHistory)
DAO->>DB : INSERT INTO v1_jd_cookie_order_change_history
DB-->>DAO : 返回结果
DAO-->>Logic : 返回结果
Logic->>Service : 返回订单信息
Service-->>Controller : 返回订单信息
Controller-->>Client : 返回订单信息
Client->>Controller : GET /api/jd_cookie/v1/get_payment_url?order_id=123
Controller->>Service : GetPaymentUrl(orderId)
Service->>Logic : GetPaymentUrl(orderId)
Logic->>DAO : Update(do.V1JdCookieOrder)
DAO->>DB : UPDATE v1_jd_cookie_order SET payment_url = ?
DB-->>DAO : 返回结果
DAO-->>Logic : 返回结果
Logic->>DAO : Insert(do.V1JdCookieOrderChangeHistory)
DAO->>DB : INSERT INTO v1_jd_cookie_order_change_history
DB-->>DAO : 返回结果
DAO-->>Logic : 返回结果
Logic-->>Service : 返回支付链接
Service-->>Controller : 返回支付链接
Controller-->>Client : 返回支付链接

图源

  • order.go - 在提交77aff4289e7b60617a6b97873721f586af264581中更新
  • jd_cookie.go - 在提交0fdae6a89fef78f6368400b1fe726d987adda7b1中更新

权限控制组件分析

权限控制组件基于 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 监控系统,系统具备了强大的可观测性。未来,系统可以进一步优化性能,增加更多功能,提高用户体验。